From bc73c5b1ecaa8001bdeeac46864d4e22026b104a Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 9 Jan 2013 20:08:59 +0100 Subject: [PATCH 001/151] enable directional lighting for character previews --- apps/openmw/mwrender/characterpreview.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index b034e098b..a172d02b1 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -39,6 +39,15 @@ namespace MWRender void CharacterPreview::setup () { mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); + + /// \todo Read the fallback values from INIImporter (Inventory:Directional*) + Ogre::Light* l = mSceneMgr->createLight(); + l->setType (Ogre::Light::LT_DIRECTIONAL); + l->setDirection (Ogre::Vector3(0.3, -0.7, 0.3)); + l->setDiffuseColour (Ogre::ColourValue(1,1,1)); + + mSceneMgr->setAmbientLight (Ogre::ColourValue(0.5, 0.5, 0.5)); + mCamera = mSceneMgr->createCamera (mName); mCamera->setAspectRatio (float(mSizeX) / float(mSizeY)); @@ -72,7 +81,6 @@ namespace MWRender mViewport->setOverlaysEnabled(false); mViewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0, 0)); mViewport->setShadowsEnabled(false); - mViewport->setMaterialScheme("local_map"); mViewport->setVisibilityMask (RV_PlayerPreview); mRenderTarget->setActive(true); mRenderTarget->setAutoUpdated (false); From 111e38ef25546836d243c9b14c72bd055478a53b Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 9 Jan 2013 20:18:26 +0100 Subject: [PATCH 002/151] Revert "fog now distance based instead of depth" This reverts commit 7ee038fdd7fcb51f901893ae0e6554a2f0cc3dc1. --- files/materials/objects.shader | 2 +- files/materials/openmw.configuration | 1 + files/materials/terrain.shader | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 25624351c..130de0f3d 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -265,7 +265,7 @@ #endif #if FOG - float fogValue = shSaturate((length(cameraPos.xyz-worldPos) - fogParams.y) * fogParams.w); + float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); #if UNDERWATER // regular fog only if fragment is above water diff --git a/files/materials/openmw.configuration b/files/materials/openmw.configuration index 2f84680f0..ee97451d3 100644 --- a/files/materials/openmw.configuration +++ b/files/materials/openmw.configuration @@ -1,5 +1,6 @@ configuration water_reflection { + fog false shadows false shadows_pssm false mrt_output false diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index dee733263..9494c1de9 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -337,7 +337,7 @@ #if FOG - float fogValue = shSaturate((length(cameraPos.xyz-worldPos) - fogParams.y) * fogParams.w); + float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); #if UNDERWATER // regular fog only if fragment is above water From bd8d793fec20fe751651abfcebd7ef0704ffbb8b Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 9 Jan 2013 21:41:40 +0100 Subject: [PATCH 003/151] Removing gamma correction due to caused inconsistencies. --- files/materials/core.h | 7 ++++--- files/materials/objects.shader | 2 +- files/materials/terrain.shader | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/files/materials/core.h b/files/materials/core.h index 1c9ea1d1d..0e46369ef 100644 --- a/files/materials/core.h +++ b/files/materials/core.h @@ -1,7 +1,8 @@ -#define gammaCorrectRead(v) pow(max(v, 0.00001f), float3(gammaCorrection,gammaCorrection,gammaCorrection)) -#define gammaCorrectOutput(v) pow(max(v, 0.00001f), float3(1.f/gammaCorrection,1.f/gammaCorrection,1.f/gammaCorrection)) - +//#define gammaCorrectRead(v) pow(max(v, 0.00001f), float3(gammaCorrection,gammaCorrection,gammaCorrection)) +//#define gammaCorrectOutput(v) pow(max(v, 0.00001f), float3(1.f/gammaCorrection,1.f/gammaCorrection,1.f/gammaCorrection)) +#define gammaCorrectRead(v) v +#define gammaCorrectOutput(v) v #if SH_HLSL == 1 || SH_CG == 1 diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 130de0f3d..c68705c42 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -112,7 +112,7 @@ shUniform(float, far) @shAutoConstant(far, far_clip_distance) #endif - shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) + //shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) #if LIGHTING shInput(float3, normalPassthrough) diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 9494c1de9..dfe998210 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -137,7 +137,7 @@ shSampler2D(normalMap) // global normal map - shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) + //shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) @shForeach(@shPropertyString(num_blendmaps)) From b8c6f6640b9f01c0f7925f33819e1da73b34c509 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 9 Jan 2013 21:56:26 +0100 Subject: [PATCH 004/151] Fixing water <-> waterfall blending issues (Sort of... the second part will follow later) --- apps/openmw/mwrender/water.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index e8f099640..80fe54707 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -48,7 +48,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mWater = mSceneManager->createEntity("water"); mWater->setVisibilityFlags(RV_Water); - mWater->setRenderQueueGroup(RQG_Water); mWater->setCastShadows(false); mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); @@ -324,7 +323,11 @@ void Water::applyRTT() mReflectionTarget = rtt; sh::Factory::getInstance ().setTextureAlias ("WaterReflection", mReflectionTexture->getName()); + + mWater->setRenderQueueGroup(RQG_Water); } + else + mWater->setRenderQueueGroup(RQG_Alpha); } void Water::applyVisibilityMask() From d3c0851aa72cb47b977cf6377ae03c73a2859335 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 9 Jan 2013 22:08:42 +0100 Subject: [PATCH 005/151] Changed light attenuation back to linear in all cases, this seems to be what MW does. --- apps/openmw/mwrender/objects.cpp | 7 +++---- apps/openmw/mwrender/water.cpp | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index ee36126f8..810d7af41 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -238,17 +238,16 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f info.time = Ogre::Math::RangeRandom(-500, +500); info.phase = Ogre::Math::RangeRandom(-500, +500); - // adjust the lights depending if we're in an interior or exterior cell - // quadratic means the light intensity falls off quite fast, resulting in a - // dark, atmospheric environment (perfect for exteriors) - // for interiors, we want more "warm" lights, so use linear attenuation. + // changed to linear to look like morrowind bool quadratic = false; + /* if (!lightOutQuadInLin) quadratic = lightQuadratic; else { quadratic = !info.interior; } + */ if (!quadratic) { diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 80fe54707..a16a23b26 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -315,7 +315,7 @@ void Water::applyRTT() vp->setOverlaysEnabled(false); vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); vp->setShadowsEnabled(false); - // use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain) + // use fallback techniques without shadows and without mrt vp->setMaterialScheme("water_reflection"); rtt->addListener(this); rtt->setActive(true); From 455ec0996df77bea43903741b37eda7b57aecb51 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 9 Jan 2013 22:27:58 +0100 Subject: [PATCH 006/151] Shaders & textures are now loaded upon loading the NIF, instead of when the object becomes visible in the camera frustum. Should improve responsiveness. --- components/nifogre/ogre_nif_loader.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 31d873489..35060e50b 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -656,6 +656,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String else instance->getMaterial ()->setShadowCasterMaterial ("openmw_shadowcaster_noalpha"); + sh::Factory::getInstance ()._ensureMaterial (matname, "Default"); + // As of yet UNTESTED code from Chris: /*pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC); pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL); From 35015ef11002547835851979ad6ffd9e48487ceb Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 9 Jan 2013 23:11:15 +0100 Subject: [PATCH 007/151] Change default settings to use no object shaders and per vertex lighting, as some lights in MW look clearly broken with per pixel lighting enabled (e.g. fireplace in census office, ghostfence) --- files/settings-default.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 1768b2f5e..26546c2b1 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -96,7 +96,7 @@ fps = 0 crosshair = true [Objects] -shaders = true +shaders = false # Max. number of lights that affect objects. Setting to 1 will only reflect sunlight # Note: has no effect when shaders are turned off @@ -132,7 +132,7 @@ num lights = 8 # Enable this to get fancy-looking water with reflections and refractions # Only available if object shaders are on # All the settings below have no effect if this is false -shader = true +shader = false rtt size = 512 reflect terrain = true @@ -142,7 +142,7 @@ reflect actors = false reflect misc = false # Enable underwater effect. It is not resource intensive, so only disable it if you have problems. -underwater effect = true +underwater effect = false [Sound] # Device name. Blank means default From 55769aaf911cb06ffa856d5a9d14a77c5f4b3ada Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 10 Jan 2013 01:46:00 +0100 Subject: [PATCH 008/151] Fix selection buffer (i.e. item selection on the inventory character preview) when object shaders were disabled --- apps/openmw/engine.cpp | 4 +--- files/materials/selection.mat | 1 + files/materials/water.mat | 2 +- files/materials/water.shader | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 8c288a2ee..31eb68fa7 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -391,8 +391,6 @@ void OMW::Engine::go() MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, pos); } - std::cout << "\nPress Q/ESC or close window to exit.\n"; - mOgre->getRoot()->addFrameListener (this); // Play some good 'ol tunes @@ -420,7 +418,7 @@ void OMW::Engine::go() // Save user settings settings.saveUser(settingspath); - std::cout << "Quitting peacefully.\n"; + std::cout << "Quitting peacefully." << std::endl; } void OMW::Engine::activate() diff --git a/files/materials/selection.mat b/files/materials/selection.mat index a76dd7179..2cb92f884 100644 --- a/files/materials/selection.mat +++ b/files/materials/selection.mat @@ -1,5 +1,6 @@ material SelectionColour { + allow_fixed_function false pass { vertex_program selection_vertex diff --git a/files/materials/water.mat b/files/materials/water.mat index dcea5a0d0..a5f9f2ec9 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -2,7 +2,7 @@ material Water { pass { - emissive 0.6 0.7 1.0 + emissive 1.0 1.0 1.0 ambient 0 0 0 diffuse 0 0 0 1 specular 0 0 0 32 diff --git a/files/materials/water.shader b/files/materials/water.shader index 6bd277eab..9ebea0f00 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -42,7 +42,7 @@ SH_START_PROGRAM { - shOutputColour(0).xyz = shSample(animatedTexture, UV * 15).xyz * float3(0.6, 0.7, 1.0); + shOutputColour(0).xyz = shSample(animatedTexture, UV * 15).xyz * float3(1.0, 1.0, 1.0); shOutputColour(0).w = 0.7; float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); From 30136eb4496b4e81e62548825ef468906db32029 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 Jan 2013 06:36:48 +0100 Subject: [PATCH 009/151] Update settings UI --- apps/openmw/mwgui/settingswindow.cpp | 60 +++++++++-------------- apps/openmw/mwgui/settingswindow.hpp | 3 +- apps/openmw/mwgui/windowmanagerimp.cpp | 4 +- apps/openmw/mwrender/renderingmanager.cpp | 7 +-- files/mygui/openmw_settings_window.layout | 40 ++++++--------- files/settings-default.cfg | 2 - 6 files changed, 43 insertions(+), 73 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index cdfe4d2b6..294921cdd 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -109,6 +109,7 @@ namespace MWGui getWidget(mReflectActorsButton, "ReflectActorsButton"); getWidget(mReflectTerrainButton, "ReflectTerrainButton"); getWidget(mShadersButton, "ShadersButton"); + getWidget(mShaderModeButton, "ShaderModeButton"); getWidget(mShadowsEnabledButton, "ShadowsEnabledButton"); getWidget(mShadowsLargeDistance, "ShadowsLargeDistance"); getWidget(mShadowsTextureSize, "ShadowsTextureSize"); @@ -122,7 +123,6 @@ namespace MWGui getWidget(mInvertYButton, "InvertYButton"); getWidget(mUISensitivitySlider, "UISensitivitySlider"); getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider"); - getWidget(mGammaSlider, "GammaSlider"); mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -130,6 +130,7 @@ namespace MWGui mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mUnderwaterButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled); + mShaderModeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShaderModeToggled); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -144,7 +145,6 @@ namespace MWGui mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mGammaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -202,14 +202,6 @@ namespace MWGui getWidget(fovText, "FovText"); fovText->setCaption("Field of View (" + boost::lexical_cast(int(Settings::Manager::getFloat("field of view", "General"))) + ")"); - float gammaVal = (Settings::Manager::getFloat("gamma", "Video")-0.1f)/(3.f-0.1f); - mGammaSlider->setScrollPosition(gammaVal * (mGammaSlider->getScrollRange()-1)); - MyGUI::TextBox* gammaText; - getWidget(gammaText, "GammaText"); - std::stringstream gamma; - gamma << std::setprecision (2) << Settings::Manager::getFloat("gamma", "Video"); - gammaText->setCaption("Gamma (" + gamma.str() + ")"); - float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0; mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1)); std::string tf = Settings::Manager::getString("texture filtering", "General"); @@ -250,14 +242,8 @@ namespace MWGui mInvertYButton->setCaptionWithReplacing(Settings::Manager::getBool("invert y axis", "Input") ? "#{sOn}" : "#{sOff}"); - std::string shaders; - if (!Settings::Manager::getBool("shaders", "Objects")) - shaders = "off"; - else - { - shaders = Settings::Manager::getString("shader mode", "General"); - } - mShadersButton->setCaption (shaders); + mShadersButton->setCaption (Settings::Manager::getBool("shaders", "Objects") ? "on" : "off"); + mShaderModeButton->setCaption (Settings::Manager::getString("shader mode", "General")); if (!MWRender::RenderingManager::waterShaderSupported()) { @@ -267,7 +253,7 @@ namespace MWGui mReflectTerrainButton->setEnabled(false); } - if (shaders == "off") + if (!Settings::Manager::getBool("shaders", "Objects")) { mUnderwaterButton->setEnabled (false); mShadowsEnabledButton->setEnabled(false); @@ -424,19 +410,31 @@ namespace MWGui } } + void SettingsWindow::onShaderModeToggled(MyGUI::Widget* _sender) + { + std::string val = static_cast(_sender)->getCaption(); + if (val == "cg") + { + val = hlslGlsl(); + } + else + val = "cg"; + + static_cast(_sender)->setCaption(val); + + Settings::Manager::setString("shader mode", "General", val); + + apply(); + } + void SettingsWindow::onShadersToggled(MyGUI::Widget* _sender) { std::string val = static_cast(_sender)->getCaption(); if (val == "off") - { - val = hlslGlsl(); - } - else if (val == hlslGlsl()) - val = "cg"; + val = "on"; else val = "off"; - - static_cast(_sender)->setCaption(val); + static_cast(_sender)->setCaption (val); if (val == "off") { @@ -461,7 +459,6 @@ namespace MWGui else { Settings::Manager::setBool("shaders", "Objects", true); - Settings::Manager::setString("shader mode", "General", val); // re-enable if (MWRender::RenderingManager::waterShaderSupported()) @@ -521,15 +518,6 @@ namespace MWGui fovText->setCaption("Field of View (" + boost::lexical_cast(int((1-val) * sFovMin + val * sFovMax)) + ")"); Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax); } - else if (scroller == mGammaSlider) - { - Settings::Manager::setFloat("gamma", "Video", (1-val) * 0.1f + val * 3.f); - MyGUI::TextBox* gammaText; - getWidget(gammaText, "GammaText"); - std::stringstream gamma; - gamma << std::setprecision (2) << Settings::Manager::getFloat("gamma", "Video"); - gammaText->setCaption("Gamma (" + gamma.str() + ")"); - } else if (scroller == mAnisotropySlider) { mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(int(val*16)) + ")"); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index e878d0abe..8ca3ad758 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -40,7 +40,6 @@ namespace MWGui MyGUI::Button* mFPSButton; MyGUI::ScrollBar* mViewDistanceSlider; MyGUI::ScrollBar* mFOVSlider; - MyGUI::ScrollBar* mGammaSlider; MyGUI::ScrollBar* mAnisotropySlider; MyGUI::Button* mTextureFilteringButton; MyGUI::TextBox* mAnisotropyLabel; @@ -50,6 +49,7 @@ namespace MWGui MyGUI::Button* mReflectActorsButton; MyGUI::Button* mReflectTerrainButton; MyGUI::Button* mShadersButton; + MyGUI::Button* mShaderModeButton; MyGUI::Button* mUnderwaterButton; MyGUI::Button* mShadowsEnabledButton; @@ -84,6 +84,7 @@ namespace MWGui void onResolutionCancel(); void onShadersToggled(MyGUI::Widget* _sender); + void onShaderModeToggled(MyGUI::Widget* _sender); void onShadowTextureSize(MyGUI::Widget* _sender); void onRebindAction(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 8ec495550..a1f915ac9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -177,8 +177,7 @@ WindowManager::WindowManager( mInputBlocker = mGui->createWidget("",0,0,w,h,MyGUI::Align::Default,"Windows",""); - // The HUD is always on - mHud->setVisible(true); + mHud->setVisible(mHudEnabled); mCharGen = new CharacterCreation(this); @@ -1001,7 +1000,6 @@ void WindowManager::notifyInputActionBound () allowMouse(); } - void WindowManager::showCrosshair (bool show) { mHud->setCrosshairVisible (show && mCrosshairEnabled); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ae7d6612b..ff26b087c 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -134,7 +134,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty(new sh::Vector3(0.5, -0.8, 0.2))); sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(1, 0.6))); sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty(new sh::FloatValue( - Settings::Manager::getFloat ("gamma", "Video")))); + 1.f))); applyCompositors(); @@ -782,11 +782,6 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); mObjects.rebuildStaticGeometry (); } - else if (it->second == "gamma" && it->first == "Video") - { - sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty(new sh::FloatValue( - Settings::Manager::getFloat ("gamma", "Video")))); - } else if (it->second == "shader mode" && it->first == "General") { sh::Language lang; diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 2f9b5a67f..f03305ae7 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -157,53 +157,43 @@ - + - + - + - - - - - - - - + - - - - - - - - - - - - - - + + + + + + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 26546c2b1..31aa60c42 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -28,8 +28,6 @@ vsync = false # PBuffer, FBO, Copy opengl rtt mode = FBO -gamma = 2.2 - [GUI] # 1 is fully opaque menu transparency = 0.84 From 2c3719a6f5f2a4110e412781de0f4b955e1b2441 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 Jan 2013 07:02:12 +0100 Subject: [PATCH 010/151] Disabling PSSM feature to make sure we can fit the max. amount of terrain textures in Morrowind.esm in a single pass. --- apps/openmw/mwgui/settingswindow.cpp | 5 ++++- apps/openmw/mwrender/shadows.cpp | 4 ++-- apps/openmw/mwrender/terrainmaterial.cpp | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 294921cdd..c5c6eada2 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -225,7 +225,10 @@ namespace MWGui mUnderwaterButton->setCaptionWithReplacing(Settings::Manager::getBool("underwater effect", "Water") ? "#{sOn}" : "#{sOff}"); mShadowsTextureSize->setCaption (Settings::Manager::getString ("texture size", "Shadows")); - mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}"); + //mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}"); + mShadowsLargeDistance->setCaptionWithReplacing("#{sOff}"); + mShadowsLargeDistance->setEnabled (false); + mShadowsEnabledButton->setCaptionWithReplacing(Settings::Manager::getBool("enabled", "Shadows") ? "#{sOn}" : "#{sOff}"); mActorShadows->setCaptionWithReplacing(Settings::Manager::getBool("actor shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); mStaticsShadows->setCaptionWithReplacing(Settings::Manager::getBool("statics shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); diff --git a/apps/openmw/mwrender/shadows.cpp b/apps/openmw/mwrender/shadows.cpp index 3d9f13243..808c8b5d9 100644 --- a/apps/openmw/mwrender/shadows.cpp +++ b/apps/openmw/mwrender/shadows.cpp @@ -33,8 +33,8 @@ void Shadows::recreate() // Split shadow maps are currently disabled because the terrain cannot cope with them // (Too many texture units) Solution would be a multi-pass terrain material - bool split = Settings::Manager::getBool("split", "Shadows"); - //const bool split = false; + //bool split = Settings::Manager::getBool("split", "Shadows"); + const bool split = false; sh::Factory::getInstance ().setGlobalSetting ("shadows", enabled && !split ? "true" : "false"); sh::Factory::getInstance ().setGlobalSetting ("shadows_pssm", enabled && split ? "true" : "false"); diff --git a/apps/openmw/mwrender/terrainmaterial.cpp b/apps/openmw/mwrender/terrainmaterial.cpp index 5ef9fe58f..d5e531f86 100644 --- a/apps/openmw/mwrender/terrainmaterial.cpp +++ b/apps/openmw/mwrender/terrainmaterial.cpp @@ -153,7 +153,8 @@ namespace MWRender --freeTextureUnits; // colourmap --freeTextureUnits; - freeTextureUnits -= 3; // shadow PSSM + // shadow + --freeTextureUnits; --freeTextureUnits; // caustics From e4f140841e2e9eacb25c671cbe03c61938b1219c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 12 Jan 2013 08:23:15 +0100 Subject: [PATCH 011/151] Make OpenMW work with Ogre 1.9 --- apps/launcher/graphicspage.cpp | 1 + apps/openmw/mwrender/localmap.cpp | 1 - apps/openmw/mwrender/shadows.cpp | 5 ++--- apps/openmw/mwrender/terrainmaterial.hpp | 1 + apps/openmw/mwrender/water.cpp | 3 --- components/bsa/bsa_archive.cpp | 5 +++++ libs/openengine/ogre/renderer.cpp | 1 + 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 2c4f3430c..cc4cbfe7d 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -122,6 +122,7 @@ bool GraphicsPage::setupOgre() pluginDir = absPluginPath.string(); Files::loadOgrePlugin(pluginDir, "RenderSystem_GL", *mOgre); + Files::loadOgrePlugin(pluginDir, "RenderSystem_GL3Plus", *mOgre); Files::loadOgrePlugin(pluginDir, "RenderSystem_Direct3D9", *mOgre); #ifdef ENABLE_PLUGIN_GL diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index d878cb86e..b34942d28 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -1,6 +1,5 @@ #include "localmap.hpp" -#include #include #include diff --git a/apps/openmw/mwrender/shadows.cpp b/apps/openmw/mwrender/shadows.cpp index 808c8b5d9..595a82294 100644 --- a/apps/openmw/mwrender/shadows.cpp +++ b/apps/openmw/mwrender/shadows.cpp @@ -9,9 +9,6 @@ #include #include -#include -#include - #include #include "renderconst.hpp" @@ -125,6 +122,7 @@ void Shadows::recreate() // -------------------------------------------------------------------------------------------------------------------- // --------------------------- Debug overlays to display the content of shadow maps ----------------------------------- // -------------------------------------------------------------------------------------------------------------------- + /* if (Settings::Manager::getBool("debug", "Shadows")) { OverlayManager& mgr = OverlayManager::getSingleton(); @@ -181,6 +179,7 @@ void Shadows::recreate() if ((overlay = mgr.getByName("DebugOverlay"))) mgr.destroy(overlay); } + */ } PSSMShadowCameraSetup* Shadows::getPSSMSetup() diff --git a/apps/openmw/mwrender/terrainmaterial.hpp b/apps/openmw/mwrender/terrainmaterial.hpp index 3e31b2a58..fe1214cf5 100644 --- a/apps/openmw/mwrender/terrainmaterial.hpp +++ b/apps/openmw/mwrender/terrainmaterial.hpp @@ -67,6 +67,7 @@ namespace MWRender void setGlobalColourMapEnabled(bool enabled); void setGlobalColourMap (Ogre::Terrain* terrain, const std::string& name); + virtual void setLightmapEnabled(bool) {} private: sh::MaterialInstance* mMaterial; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index a16a23b26..04a126367 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -8,9 +8,6 @@ #include #include #include -#include -#include -#include #include "sky.hpp" #include "renderingmanager.hpp" diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index 9913fb8aa..3bff93baa 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -403,6 +403,11 @@ public: return new BSAArchive(name); } + virtual Archive* createInstance(const String& name, bool readOnly) + { + return new BSAArchive(name); + } + void destroyInstance( Archive* arch) { delete arch; } }; diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 3cdb00518..ed5cc9b43 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -192,6 +192,7 @@ void OgreRenderer::configure(const std::string &logPath, pluginDir = absPluginPath.string(); Files::loadOgrePlugin(pluginDir, "RenderSystem_GL", *mRoot); + Files::loadOgrePlugin(pluginDir, "RenderSystem_GL3Plus", *mRoot); Files::loadOgrePlugin(pluginDir, "RenderSystem_Direct3D9", *mRoot); Files::loadOgrePlugin(pluginDir, "Plugin_CgProgramManager", *mRoot); From df602553d10fa69ed4ab6a4902daaefed276749d Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 Jan 2013 09:13:36 +0100 Subject: [PATCH 012/151] Reworked MWRender::Water to be more OOP-ish and possibly allow other reflection types. --- apps/openmw/mwrender/water.cpp | 270 +++++++++++++++++++++------------ apps/openmw/mwrender/water.hpp | 77 ++++++++-- 2 files changed, 238 insertions(+), 109 deletions(-) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 04a126367..27b9fc679 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -24,12 +24,163 @@ using namespace Ogre; namespace MWRender { +CubeReflection::CubeReflection(Ogre::SceneManager* sceneManager) + : Reflection(sceneManager) +{ + Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton ().createManual("CubeReflection", + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_CUBE_MAP, + 512,512, 0, PF_R8G8B8, TU_RENDERTARGET); + + mCamera = mSceneMgr->createCamera ("CubeCamera"); + mCamera->setNearClipDistance (5); + mCamera->setFarClipDistance (1000); + + for (int face = 0; face < 6; ++face) + { + mRenderTargets[face] = texture->getBuffer (face)->getRenderTarget(); + mRenderTargets[face]->removeAllViewports (); + Viewport* vp = mRenderTargets[face]->addViewport (mCamera); + vp->setOverlaysEnabled(false); + vp->setShadowsEnabled(false); + vp->setMaterialScheme ("water_reflection"); + mRenderTargets[face]->setAutoUpdated(false); + + /* + Vector3 lookAt(0,0,0), up(0,0,0), right(0,0,0); + switch(face) + { + case 0: lookAt.x =-1; up.y = 1; right.z = 1; break; // +X + case 1: lookAt.x = 1; up.y = 1; right.z =-1; break; // -X + case 2: lookAt.y =-1; up.z = 1; right.x = 1; break; // +Y + case 3: lookAt.y = 1; up.z =-1; right.x = 1; break; // -Y + case 4: lookAt.z = 1; up.y = 1; right.x =-1; break; // +Z + case 5: lookAt.z =-1; up.y = 1; right.x =-1; break; // -Z + } + Quaternion orient(right, up, lookAt); + mCamera->setOrientation(orient); + */ + } +} + +CubeReflection::~CubeReflection () +{ + Ogre::TextureManager::getSingleton ().remove("CubeReflection"); + mSceneMgr->destroyCamera (mCamera); +} + +void CubeReflection::update () +{ + mParentCamera->getParentSceneNode ()->needUpdate (); + mCamera->setPosition(mParentCamera->getDerivedPosition()); +} + +// -------------------------------------------------------------------------------------------------------------------------------- + +PlaneReflection::PlaneReflection(Ogre::SceneManager* sceneManager, SkyManager* sky) + : Reflection(sceneManager) + , mSky(sky) +{ + mCamera = mSceneMgr->createCamera ("PlaneReflectionCamera"); + mSceneMgr->addRenderQueueListener(this); + + mTexture = TextureManager::getSingleton().createManual("WaterReflection", + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, 512, 512, 0, PF_A8R8G8B8, TU_RENDERTARGET); + + mRenderTarget = mTexture->getBuffer()->getRenderTarget(); + Viewport* vp = mRenderTarget->addViewport(mCamera); + vp->setOverlaysEnabled(false); + vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); + vp->setShadowsEnabled(false); + // use fallback techniques without shadows and without mrt + vp->setMaterialScheme("water_reflection"); + mRenderTarget->addListener(this); + mRenderTarget->setActive(true); + + sh::Factory::getInstance ().setTextureAlias ("WaterReflection", mTexture->getName()); +} + +PlaneReflection::~PlaneReflection () +{ + mRenderTarget->removeListener (this); + mSceneMgr->destroyCamera (mCamera); + TextureManager::getSingleton ().remove("WaterReflection"); +} + +void PlaneReflection::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) +{ + // We don't want the sky to get clipped by custom near clip plane (the water plane) + if (queueGroupId < 20 && mRenderActive) + { + mCamera->disableCustomNearClipPlane(); + Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + } +} + +void PlaneReflection::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) +{ + if (queueGroupId < 20 && mRenderActive) + { + if (!mIsUnderwater) + mCamera->enableCustomNearClipPlane(mErrorPlane); + Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + } +} + +void PlaneReflection::preRenderTargetUpdate(const RenderTargetEvent& evt) +{ + mParentCamera->getParentSceneNode ()->needUpdate (); + mCamera->setOrientation(mParentCamera->getDerivedOrientation()); + mCamera->setPosition(mParentCamera->getDerivedPosition()); + mCamera->setNearClipDistance(mParentCamera->getNearClipDistance()); + mCamera->setFarClipDistance(mParentCamera->getFarClipDistance()); + mCamera->setAspectRatio(mParentCamera->getAspectRatio()); + mCamera->setFOVy(mParentCamera->getFOVy()); + mRenderActive = true; + + Vector3 pos = mParentCamera->getRealPosition(); + pos.y = (mWaterPlane).d*2 - pos.y; + mSky->setSkyPosition(pos); + mCamera->enableReflection(mWaterPlane); +} + +void PlaneReflection::postRenderTargetUpdate(const RenderTargetEvent& evt) +{ + mSky->resetSkyPosition(); + mCamera->disableReflection(); + mCamera->disableCustomNearClipPlane(); + mRenderActive = false; +} + +void PlaneReflection::setWaterPlane (Plane plane) +{ + mWaterPlane = plane; + mErrorPlane = Plane(plane.normal, mWaterPlane.d - 5); +} + +void PlaneReflection::setActive (bool active) +{ + mRenderTarget->setActive(active); +} + +void PlaneReflection::setViewportBackground(Ogre::ColourValue colour) +{ + mRenderTarget->getViewport (0)->setBackgroundColour (colour); +} + +void PlaneReflection::setVisibilityMask (int flags) +{ + mRenderTarget->getViewport (0)->setVisibilityMask (flags); +} + +// -------------------------------------------------------------------------------------------------------------------------------- + Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell) : - mCamera (camera), mSceneManager (camera->getSceneManager()), + mCamera (camera), mSceneMgr (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), - mReflectionTarget(0), mActive(1), mToggled(1), - mReflectionRenderActive(false), mRendering(rend), - mWaterTimer(0.f) + mActive(1), mToggled(1), + mRendering(rend), + mWaterTimer(0.f), + mReflection(NULL) { mSky = rend->getSkyManager(); @@ -43,13 +194,11 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel MeshManager::getSingleton().createPlane("water", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, CELL_SIZE*5, CELL_SIZE * 5, 10, 10, true, 1, 3,3, Vector3::UNIT_Z); - mWater = mSceneManager->createEntity("water"); + mWater = mSceneMgr->createEntity("water"); mWater->setVisibilityFlags(RV_Water); mWater->setCastShadows(false); - mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); - - mReflectionCamera = mSceneManager->createCamera("ReflectionCamera"); + mWaterNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); if(!(cell->mData.mFlags & cell->Interior)) { @@ -72,8 +221,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel underwaterDome->setMaterialName("Underwater_Dome"); */ - mSceneManager->addRenderQueueListener(this); - assignTextures(); setHeight(mTop); @@ -142,12 +289,9 @@ Water::~Water() { MeshManager::getSingleton().remove("water"); - if (mReflectionTarget) - mReflectionTexture->getBuffer()->getRenderTarget()->removeListener(this); - mWaterNode->detachObject(mWater); - mSceneManager->destroyEntity(mWater); - mSceneManager->destroySceneNode(mWaterNode); + mSceneMgr->destroyEntity(mWater); + mSceneMgr->destroySceneNode(mWaterNode); } void Water::changeCell(const ESM::Cell* cell) @@ -166,8 +310,8 @@ void Water::setHeight(const float height) mWaterPlane = Plane(Vector3::UNIT_Y, height); - // small error due to reflection texture size & reflection distortion - mErrorPlane = Plane(Vector3::UNIT_Y, height - 5); + if (mReflection) + mReflection->setWaterPlane(mWaterPlane); mWaterNode->setPosition(0, height, 0); sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(height))); @@ -190,6 +334,9 @@ Water::updateUnderwater(bool underwater) mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID; + if (mReflection) + mReflection->setUnderwater (mIsUnderwater); + updateVisible(); } @@ -198,37 +345,6 @@ Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY) return Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), mTop, -gridY * CELL_SIZE - (CELL_SIZE / 2)); } -void Water::preRenderTargetUpdate(const RenderTargetEvent& evt) -{ - if (evt.source == mReflectionTarget) - { - mCamera->getParentSceneNode ()->needUpdate (); - mReflectionCamera->setOrientation(mCamera->getDerivedOrientation()); - mReflectionCamera->setPosition(mCamera->getDerivedPosition()); - mReflectionCamera->setNearClipDistance(mCamera->getNearClipDistance()); - mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance()); - mReflectionCamera->setAspectRatio(mCamera->getAspectRatio()); - mReflectionCamera->setFOVy(mCamera->getFOVy()); - mReflectionRenderActive = true; - - Vector3 pos = mCamera->getRealPosition(); - pos.y = mTop*2 - pos.y; - mSky->setSkyPosition(pos); - mReflectionCamera->enableReflection(mWaterPlane); - } -} - -void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) -{ - if (evt.source == mReflectionTarget) - { - mSky->resetSkyPosition(); - mReflectionCamera->disableReflection(); - mReflectionCamera->disableCustomNearClipPlane(); - mReflectionRenderActive = false; - } -} - void Water::assignTextures() { if (Settings::Manager::getBool("shader", "Water")) @@ -246,34 +362,16 @@ void Water::assignTextures() void Water::setViewportBackground(const ColourValue& bg) { - if (mReflectionTarget) - mReflectionTarget->getViewport(0)->setBackgroundColour(bg); + if (mReflection) + mReflection->setViewportBackground(bg); } void Water::updateVisible() { mWater->setVisible(mToggled && mActive); - if (mReflectionTarget) - mReflectionTarget->setActive(mToggled && mActive); -} - -void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) -{ - // We don't want the sky to get clipped by custom near clip plane (the water plane) - if (queueGroupId < 20 && mReflectionRenderActive) + if (mReflection) { - mReflectionCamera->disableCustomNearClipPlane(); - Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); - } -} - -void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) -{ - if (queueGroupId < 20 && mReflectionRenderActive) - { - if (!mIsUnderwater) - mReflectionCamera->enableCustomNearClipPlane(mErrorPlane); - Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); + mReflection->setActive(mToggled && mActive); } } @@ -293,10 +391,10 @@ void Water::update(float dt) void Water::applyRTT() { - if (mReflectionTarget) + if (mReflection) { - TextureManager::getSingleton().remove("WaterReflection"); - mReflectionTarget = 0; + delete mReflection; + mReflection = NULL; } // Create rendertarget for reflection @@ -304,23 +402,9 @@ void Water::applyRTT() if (Settings::Manager::getBool("shader", "Water")) { - mReflectionTexture = TextureManager::getSingleton().createManual("WaterReflection", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_A8R8G8B8, TU_RENDERTARGET); - - RenderTarget* rtt = mReflectionTexture->getBuffer()->getRenderTarget(); - Viewport* vp = rtt->addViewport(mReflectionCamera); - vp->setOverlaysEnabled(false); - vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); - vp->setShadowsEnabled(false); - // use fallback techniques without shadows and without mrt - vp->setMaterialScheme("water_reflection"); - rtt->addListener(this); - rtt->setActive(true); - - mReflectionTarget = rtt; - - sh::Factory::getInstance ().setTextureAlias ("WaterReflection", mReflectionTexture->getName()); - + mReflection = new PlaneReflection(mSceneMgr, mSky); + mReflection->setParentCamera (mCamera); + mReflection->setWaterPlane(mWaterPlane); mWater->setRenderQueueGroup(RQG_Water); } else @@ -336,10 +420,8 @@ void Water::applyVisibilityMask() + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") + RV_Sky; - if (mReflectionTarget) - { - mReflectionTexture->getBuffer()->getRenderTarget()->getViewport(0)->setVisibilityMask(mVisibilityFlags); - } + if (mReflection) + mReflection->setVisibilityMask(mVisibilityFlags); } void Water::processChangedSettings(const Settings::CategorySettingVector& settings) diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index f1e3d7a3b..de78542b7 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -30,15 +30,73 @@ namespace MWRender { class SkyManager; class RenderingManager; + class Reflection + { + public: + Reflection(Ogre::SceneManager* sceneManager) + : mSceneMgr(sceneManager) {} + + virtual void setWaterPlane (Ogre::Plane plane) {} + virtual void setParentCamera (Ogre::Camera* parent) { mParentCamera = parent; } + void setUnderwater(bool underwater) { mIsUnderwater = underwater; } + virtual void setActive (bool active) {} + virtual void setViewportBackground(Ogre::ColourValue colour) {} + virtual void update() {} + virtual void setVisibilityMask (int flags) {} + + protected: + Ogre::Camera* mCamera; + Ogre::Camera* mParentCamera; + Ogre::TexturePtr mTexture; + Ogre::SceneManager* mSceneMgr; + bool mIsUnderwater; + }; + + class CubeReflection : public Reflection + { + public: + CubeReflection(Ogre::SceneManager* sceneManager); + virtual ~CubeReflection(); + + virtual void update(); + protected: + Ogre::RenderTarget* mRenderTargets[6]; + }; + + class PlaneReflection : public Reflection, public Ogre::RenderQueueListener, public Ogre::RenderTargetListener + { + public: + PlaneReflection(Ogre::SceneManager* sceneManager, SkyManager* sky); + virtual ~PlaneReflection(); + + virtual void setWaterPlane (Ogre::Plane plane); + virtual void setActive (bool active); + virtual void setVisibilityMask (int flags); + + void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + + void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); + void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); + + virtual void setViewportBackground(Ogre::ColourValue colour); + + protected: + Ogre::RenderTarget* mRenderTarget; + SkyManager* mSky; + Ogre::Plane mWaterPlane; + Ogre::Plane mErrorPlane; + bool mRenderActive; + }; + /// Water rendering class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener, public sh::MaterialInstanceListener { static const int CELL_SIZE = 8192; Ogre::Camera *mCamera; - Ogre::SceneManager *mSceneManager; + Ogre::SceneManager *mSceneMgr; Ogre::Plane mWaterPlane; - Ogre::Plane mErrorPlane; Ogre::SceneNode *mWaterNode; Ogre::Entity *mWater; @@ -52,17 +110,9 @@ namespace MWRender { float mWaterTimer; - bool mReflectionRenderActive; - Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY); protected: - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - - void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); - void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); - void applyRTT(); void applyVisibilityMask(); @@ -75,14 +125,11 @@ namespace MWRender { Ogre::MaterialPtr mMaterial; - Ogre::Camera* mReflectionCamera; - - Ogre::TexturePtr mReflectionTexture; - Ogre::RenderTarget* mReflectionTarget; - bool mUnderwaterEffect; int mVisibilityFlags; + Reflection* mReflection; + public: Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell); ~Water(); From 6faf6f57e1c64870f8bd954679fb16352d2219f4 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 25 Jan 2013 05:19:06 +0100 Subject: [PATCH 013/151] Added settings file reader/writers for openmw.cfg and settings.cfg --- apps/launcher/CMakeLists.txt | 7 ++ apps/launcher/settings/gamesettings.cpp | 34 ++++++++ apps/launcher/settings/gamesettings.hpp | 15 ++++ apps/launcher/settings/graphicssettings.cpp | 46 +++++++++++ apps/launcher/settings/graphicssettings.hpp | 16 ++++ apps/launcher/settings/settingsbase.hpp | 88 +++++++++++++++++++++ 6 files changed, 206 insertions(+) create mode 100644 apps/launcher/settings/gamesettings.cpp create mode 100644 apps/launcher/settings/gamesettings.hpp create mode 100644 apps/launcher/settings/graphicssettings.cpp create mode 100644 apps/launcher/settings/graphicssettings.hpp create mode 100644 apps/launcher/settings/settingsbase.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 09beaf59d..2895b6345 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -9,6 +9,9 @@ set(LAUNCHER model/modelitem.cpp model/esm/esmfile.cpp + settings/gamesettings.cpp + settings/graphicssettings.cpp + utils/filedialog.cpp utils/naturalsort.cpp utils/lineedit.cpp @@ -28,6 +31,10 @@ set(LAUNCHER_HEADER model/modelitem.hpp model/esm/esmfile.hpp + settings/gamesettings.hpp + settings/graphicssettings.hpp + settings/settingsbase.hpp + utils/lineedit.hpp utils/filedialog.hpp utils/naturalsort.hpp diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp new file mode 100644 index 000000000..32f03ddbe --- /dev/null +++ b/apps/launcher/settings/gamesettings.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#include + +#include "gamesettings.hpp" + +GameSettings::GameSettings() +{ +} + +GameSettings::~GameSettings() +{ +} + +bool GameSettings::writeFile(QTextStream &stream) +{ + QMap settings = SettingsBase::getSettings(); + + QMapIterator i(settings); + while (i.hasNext()) { + i.next(); + + // Quote values with spaces + if (i.value().contains(" ")) { + stream << i.key() << "=\"" << i.value() << "\"\n"; + } else { + stream << i.key() << "=" << i.value() << "\n"; + } + + } +} diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp new file mode 100644 index 000000000..c81c67d97 --- /dev/null +++ b/apps/launcher/settings/gamesettings.hpp @@ -0,0 +1,15 @@ +#ifndef GAMESETTINGS_HPP +#define GAMESETTINGS_HPP + +#include "settingsbase.hpp" + +class GameSettings : public SettingsBase> +{ +public: + GameSettings(); + ~GameSettings(); + + bool writeFile(QTextStream &stream); +}; + +#endif // GAMESETTINGS_HPP diff --git a/apps/launcher/settings/graphicssettings.cpp b/apps/launcher/settings/graphicssettings.cpp new file mode 100644 index 000000000..fd70917b5 --- /dev/null +++ b/apps/launcher/settings/graphicssettings.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +#include + +#include "graphicssettings.hpp" + +GraphicsSettings::GraphicsSettings() +{ +} + +GraphicsSettings::~GraphicsSettings() +{ +} + +bool GraphicsSettings::writeFile(QTextStream &stream) +{ + QString sectionPrefix; + QRegExp sectionRe("([^/]+)/(.+)$"); + QMap settings = SettingsBase::getSettings(); + + QMapIterator i(settings); + while (i.hasNext()) { + i.next(); + + QString prefix; + QString key; + + if (sectionRe.exactMatch(i.key())) { + prefix = sectionRe.cap(1); + key = sectionRe.cap(2); + } + + if (sectionPrefix != prefix) { + sectionPrefix = prefix; + stream << "\n[" << prefix << "]\n"; + } + + stream << key << " = " << i.value() << "\n"; + } + + return true; + +} diff --git a/apps/launcher/settings/graphicssettings.hpp b/apps/launcher/settings/graphicssettings.hpp new file mode 100644 index 000000000..8c690ebc5 --- /dev/null +++ b/apps/launcher/settings/graphicssettings.hpp @@ -0,0 +1,16 @@ +#ifndef GRAPHICSSETTINGS_HPP +#define GRAPHICSSETTINGS_HPP + +#include "settingsbase.hpp" + +class GraphicsSettings : public SettingsBase> +{ +public: + GraphicsSettings(); + ~GraphicsSettings(); + + bool writeFile(QTextStream &stream); + +}; + +#endif // GRAPHICSSETTINGS_HPP diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp new file mode 100644 index 000000000..6b8b52762 --- /dev/null +++ b/apps/launcher/settings/settingsbase.hpp @@ -0,0 +1,88 @@ +#ifndef SETTINGSBASE_HPP +#define SETTINGSBASE_HPP + +#include +#include +#include +#include + +#include + +template +class SettingsBase +{ + +public: + SettingsBase() {} + ~SettingsBase() {} + + inline QString value(const QString &key, const QString &defaultValue = QString()) + { + return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key); + } + + inline void setValue(const QString &key, const QString &value) + { + mSettings.insert(key, value); + } + + Map getSettings() {return mSettings;} + + bool readFile(QTextStream &stream) + { + mCache.clear(); + + QString sectionPrefix; + QRegExp sectionRe("^\\[([^]]+)\\]"); + QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); + + while (!stream.atEnd()) { + QString line = stream.readLine().simplified(); + + if (line.isEmpty() || line.startsWith("#")) + continue; + + if (sectionRe.exactMatch(line)) { + sectionPrefix = sectionRe.cap(1); + sectionPrefix.append("/"); + continue; + } + + if (keyRe.indexIn(line) != -1) { + + QString key = keyRe.cap(1).simplified(); + QString value = keyRe.cap(2).simplified(); + + if (!sectionPrefix.isEmpty()) + key.prepend(sectionPrefix); + + // QMap will replace the value if key exists, QMultiMap creates a new one + mCache.insert(key, value); + } + } + + if (mSettings.isEmpty()) { + mSettings = mCache; // This is the first time we read a file + return true; + } + + // Replace values from previous settings + QMapIterator i(mCache); + while (i.hasNext()) { + i.next(); + if (mSettings.contains(i.key())) + mSettings.remove(i.key()); + } + + // Merge the changed keys with those which didn't + mSettings.unite(mCache); + qDebug() << mSettings; + return true; + } + +private: + Map mSettings; + Map mCache; +}; + +#endif // SETTINGSBASE_HPP From 5579df30ff260c48861040350c9c8b7d509d6573 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sat, 26 Jan 2013 18:19:04 +0100 Subject: [PATCH 014/151] Implemented data/data-local support and added settingshandlers to main.cpp --- apps/launcher/main.cpp | 144 +++++++++++++++++++++++- apps/launcher/settings/gamesettings.cpp | 125 +++++++++++++++++++- apps/launcher/settings/gamesettings.hpp | 43 ++++++- 3 files changed, 300 insertions(+), 12 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 7c4cb5f7e..3fef62bc6 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,8 +1,22 @@ #include +#include +#include +#include #include +#include +#include +#include +#include #include +#include + +#include + #include "maindialog.hpp" +#include "settings/gamesettings.hpp" +#include "settings/graphicssettings.hpp" + int main(int argc, char *argv[]) { @@ -30,14 +44,136 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - MainDialog mainWin; + // Create setting file handlers - if (mainWin.setup()) { + Files::ConfigurationManager cfgMgr; + QString userPath = QString::fromStdString(cfgMgr.getUserPath().string()); + QString globalPath = QString::fromStdString(cfgMgr.getGlobalPath().string()); - mainWin.show(); - return app.exec(); + GameSettings gameSettings(cfgMgr); + GraphicsSettings graphicsSettings; + + QStringList paths; + paths.append(userPath + QString("openmw.cfg")); + paths.append(QString("openmw.cfg")); + paths.append(globalPath + QString("openmw.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error opening OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return 0; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + gameSettings.readFile(stream); + } + file.close(); } + if (gameSettings.getDataDirs().isEmpty()) + { + QMessageBox msgBox; + msgBox.setWindowTitle("Error detecting Morrowind installation"); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Cancel); + msgBox.setText(QObject::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(QObject::tr("B&rowse..."), QMessageBox::ActionRole); + + msgBox.exec(); + + QString selectedFile; + if (msgBox.clickedButton() == dirSelectButton) { + selectedFile = QFileDialog::getOpenFileName( + NULL, + QObject::tr("Select master file"), + QDir::currentPath(), + QString("Morrowind master file (*.esm)")); + } + + if (selectedFile.isEmpty()) + return 0; // Cancel was clicked; + + qDebug() << selectedFile; + QFileInfo info(selectedFile); + + // Add the new dir to the settings file and to the data dir container + gameSettings.setValue(QString("data"), info.absolutePath()); + gameSettings.addDataDir(info.absolutePath()); + + } + + // On to the graphics settings + qDebug() << userPath; + + QFile localDefault(QString("settings-default.cfg")); + QFile globalDefault(globalPath + QString("settings-default.cfg")); + + if (!localDefault.exists() && !globalDefault.exists()) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error reading OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not find settings-default.cfg

\ + The problem may be due to an incomplete installation of OpenMW.
\ + Reinstalling OpenMW may resolve the problem.")); + msgBox.exec(); + return 0; + } + + paths.clear(); + paths.append(globalPath + QString("settings-default.cfg")); + paths.append(QString("settings-default.cfg")); + + paths.append(userPath + QString("settings.cfg")); + paths.append(QString("settings.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error opening OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return 0; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + graphicsSettings.readFile(stream); + } + file.close(); + } + + + MainDialog mainWin; + mainWin.setup(); + + mainWin.show(); + QCoreApplication::processEvents(); + return app.exec(); + + return 0; } diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 32f03ddbe..2420c1e6c 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -1,13 +1,17 @@ #include +#include #include #include #include #include +#include + #include "gamesettings.hpp" -GameSettings::GameSettings() +GameSettings::GameSettings(Files::ConfigurationManager &cfg) + : mCfgMgr(cfg) { } @@ -15,11 +19,124 @@ GameSettings::~GameSettings() { } +void GameSettings::validatePaths() +{ + qDebug() << "validate paths!"; + + if (mSettings.isEmpty()) + return; + + QStringList paths = mSettings.values(QString("data")); + Files::PathContainer dataDirs; + + foreach (const QString &path, paths) { + dataDirs.push_back(Files::PathContainer::value_type(path.toStdString())); + } + + // Parse the data dirs to convert the tokenized paths + mCfgMgr.processPaths(dataDirs); + +// // Replace the existing data paths with valid untokenized ones +// mSettings.remove(QString("data")); + mDataDirs.clear(); + + for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { + QString path = QString::fromStdString(it->string()); + path.remove(QChar('\"')); + + QDir dir(path); + if (dir.exists()) + mDataDirs.append(path); + } + + // Do the same for data-local + QString local = mSettings.value(QString("data-local")); + + if (local.isEmpty()) + return; + + dataDirs.clear(); + dataDirs.push_back(Files::PathContainer::value_type(local.toStdString())); + + mCfgMgr.processPaths(dataDirs); +// mSettings.remove(QString("data-local")); + + if (!dataDirs.empty()) { + QString path = QString::fromStdString(dataDirs.front().string()); + path.remove(QChar('\"')); + + QDir dir(path); + if (dir.exists()) + mDataLocal = path; + } + qDebug() << mSettings; + + +} + +QStringList GameSettings::values(const QString &key, const QStringList &defaultValues) +{ + if (!mSettings.values(key).isEmpty()) + return mSettings.values(key); + return defaultValues; +} + +bool GameSettings::readFile(QTextStream &stream) +{ + QMap cache; + QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); + + while (!stream.atEnd()) { + QString line = stream.readLine().simplified(); + + if (line.isEmpty() || line.startsWith("#")) + continue; + + qDebug() << "line: " << line; + if (keyRe.indexIn(line) != -1) { + + QString key = keyRe.cap(1).simplified(); + QString value = keyRe.cap(2).simplified(); + + qDebug() << "key: " << key; + // There can be multiple data keys + if (key == QLatin1String("data")) { + cache.insertMulti(key, value); + } else { + cache.insert(key, value); + } + } + } + + if (mSettings.isEmpty()) { + mSettings = cache; // This is the first time we read a file + validatePaths(); + return true; + } + + // Replace values from previous settings + QMapIterator i(cache); + while (i.hasNext()) { + i.next(); + + // Don't remove existing data entries + if (i.key() == QLatin1String("data")) + continue; + + if (mSettings.contains(i.key())) + mSettings.remove(i.key()); + } + + // Merge the changed keys with those which didn't + mSettings.unite(cache); + validatePaths(); + qDebug() << mSettings; + return true; +} + bool GameSettings::writeFile(QTextStream &stream) { - QMap settings = SettingsBase::getSettings(); - - QMapIterator i(settings); + QMapIterator i(mSettings); while (i.hasNext()) { i.next(); diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index c81c67d97..717ce6e87 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -1,15 +1,50 @@ #ifndef GAMESETTINGS_HPP #define GAMESETTINGS_HPP -#include "settingsbase.hpp" +#include -class GameSettings : public SettingsBase> +#include + +class QTextStream; +class QStringList; +class QString; + +namespace Files { typedef std::vector PathContainer; + struct ConfigurationManager;} + +class GameSettings { public: - GameSettings(); + GameSettings(Files::ConfigurationManager &cfg); ~GameSettings(); - bool writeFile(QTextStream &stream); + inline QString value(const QString &key, const QString &defaultValue = QString()) + { + return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key); + } + + + inline void setValue(const QString &key, const QString &value) + { + mSettings.insert(key, value); + } + + inline QStringList getDataDirs() { return mDataDirs; } + inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); } + inline QString getDataLocal() {return mDataLocal; } + + QStringList values(const QString &key, const QStringList &defaultValues = QStringList()); + bool readFile(QTextStream &stream); + bool writeFile(QTextStream &stream); + +private: + Files::ConfigurationManager &mCfgMgr; + + void validatePaths(); + QMap mSettings; + + QStringList mDataDirs; + QString mDataLocal; }; #endif // GAMESETTINGS_HPP From 25edba088754aec279b41e25d4b244722cd3d037 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 27 Jan 2013 16:39:51 +0100 Subject: [PATCH 015/151] Rewriting the config code of the pages to use the new settings classes --- apps/launcher/CMakeLists.txt | 3 - apps/launcher/datafilespage.cpp | 368 +++++++++++------------------ apps/launcher/datafilespage.hpp | 13 +- apps/launcher/graphicspage.cpp | 94 ++++---- apps/launcher/graphicspage.hpp | 14 +- apps/launcher/main.cpp | 16 +- apps/launcher/maindialog.cpp | 116 +++++---- apps/launcher/maindialog.hpp | 9 +- apps/launcher/utils/filedialog.cpp | 57 ----- apps/launcher/utils/filedialog.hpp | 28 --- 10 files changed, 290 insertions(+), 428 deletions(-) delete mode 100644 apps/launcher/utils/filedialog.cpp delete mode 100644 apps/launcher/utils/filedialog.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 2895b6345..044a0a0b7 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -12,7 +12,6 @@ set(LAUNCHER settings/gamesettings.cpp settings/graphicssettings.cpp - utils/filedialog.cpp utils/naturalsort.cpp utils/lineedit.cpp utils/profilescombobox.cpp @@ -36,7 +35,6 @@ set(LAUNCHER_HEADER settings/settingsbase.hpp utils/lineedit.hpp - utils/filedialog.hpp utils/naturalsort.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp @@ -55,7 +53,6 @@ set(LAUNCHER_HEADER_MOC model/esm/esmfile.hpp utils/lineedit.hpp - utils/filedialog.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp ) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 6b0539c1d..e25300394 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -6,8 +6,9 @@ #include "model/datafilesmodel.hpp" #include "model/esm/esmfile.hpp" +#include "settings/gamesettings.hpp" + #include "utils/profilescombobox.hpp" -#include "utils/filedialog.hpp" #include "utils/lineedit.hpp" #include "utils/naturalsort.hpp" #include "utils/textinputdialog.hpp" @@ -46,9 +47,10 @@ bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2) return index1.row() <= index2.row(); } -DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent) - : QWidget(parent) - , mCfgMgr(cfg) +DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, QWidget *parent) + : mCfgMgr(cfg) + , mGameSettings(gameSettings) + , QWidget(parent) { // Models mMastersModel = new DataFilesModel(this); @@ -178,6 +180,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent) createActions(); setupConfig(); + setupDataFiles(); } void DataFilesPage::createActions() @@ -340,269 +343,176 @@ void DataFilesPage::readConfig() } -bool DataFilesPage::showDataFilesWarning() +void DataFilesPage::setupDataFiles() { + // Set the encoding to the one found in openmw.cfg or the default + mMastersModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); + mPluginsModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); - QMessageBox msgBox; - msgBox.setWindowTitle("Error detecting Morrowind installation"); - msgBox.setIcon(QMessageBox::Warning); - 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.
")); + QStringList paths = mGameSettings.getDataDirs(); - QAbstractButton *dirSelectButton = - msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole); - - msgBox.exec(); - - if (msgBox.clickedButton() == dirSelectButton) { - - // Show a custom dir selection dialog which only accepts valid dirs - QString selectedDir = FileDialog::getExistingDirectory( - this, tr("Select Data Files Directory"), - QDir::currentPath(), - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - - // Add the user selected data directory - if (!selectedDir.isEmpty()) { - mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString())); - mCfgMgr.processPaths(mDataDirs); - } else { - // Cancel from within the dir selection dialog - return false; - } - - } else { - // Cancel - return false; - } - - return true; -} - -bool DataFilesPage::setupDataFiles() -{ - // We use the Configuration Manager to retrieve the configuration values - boost::program_options::variables_map variables; - boost::program_options::options_description desc; - - desc.add_options() - ("data", boost::program_options::value()->default_value(Files::PathContainer(), "data")->multitoken()) - ("data-local", boost::program_options::value()->default_value("")) - ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) - ("encoding", boost::program_options::value()->default_value("win1252")); - - boost::program_options::notify(variables); - - mCfgMgr.readConfiguration(variables, desc); - - if (variables["data"].empty()) { - if (!showDataFilesWarning()) - return false; - } else { - mDataDirs = Files::PathContainer(variables["data"].as()); - } - - std::string local = variables["data-local"].as(); - if (!local.empty()) { - mDataLocal.push_back(Files::PathContainer::value_type(local)); - } - - mCfgMgr.processPaths(mDataDirs); - mCfgMgr.processPaths(mDataLocal); - - // Second chance to display the warning, the data= entries are invalid - while (mDataDirs.empty()) { - if (!showDataFilesWarning()) - return false; - } - - // Set the charset for reading the esm/esp files - QString encoding = QString::fromStdString(variables["encoding"].as()); - if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) { - mMastersModel->setEncoding(encoding); - mPluginsModel->setEncoding(encoding); - } - - // Add the paths to the respective models - for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) { - QString path = QString::fromStdString(it->string()); - path.remove(QChar('\"')); + foreach (const QString &path, paths) { mMastersModel->addMasters(path); mPluginsModel->addPlugins(path); } - // Same for the data-local paths - for (Files::PathContainer::iterator it = mDataLocal.begin(); it != mDataLocal.end(); ++it) { - QString path = QString::fromStdString(it->string()); - path.remove(QChar('\"')); - mMastersModel->addMasters(path); - mPluginsModel->addPlugins(path); + QString dataLocal = mGameSettings.getDataLocal(); + if (!dataLocal.isEmpty()) { + mMastersModel->addMasters(dataLocal); + mPluginsModel->addPlugins(dataLocal); } - mMastersModel->sort(0); - mPluginsModel->sort(0); -// mMastersTable->sortByColumn(3, Qt::AscendingOrder); -// mPluginsTable->sortByColumn(3, Qt::AscendingOrder); - - - readConfig(); - return true; } void DataFilesPage::writeConfig(QString profile) { - // Don't overwrite the config if no masters are found - if (mMastersModel->rowCount() < 1) - return; +// // Don't overwrite the config if no masters are found +// if (mMastersModel->rowCount() < 1) +// return; - QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string()); - QDir userPath(pathStr); +// QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string()); +// QDir userPath(pathStr); - if (!userPath.exists()) { - if (!userPath.mkpath(pathStr)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error creating OpenMW configuration directory"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not create %0

\ - Please make sure you have the right permissions and try again.
").arg(pathStr)); - msgBox.exec(); +// if (!userPath.exists()) { +// if (!userPath.mkpath(pathStr)) { +// QMessageBox msgBox; +// msgBox.setWindowTitle("Error creating OpenMW configuration directory"); +// msgBox.setIcon(QMessageBox::Critical); +// msgBox.setStandardButtons(QMessageBox::Ok); +// msgBox.setText(tr("
Could not create %0

\ +// Please make sure you have the right permissions and try again.
").arg(pathStr)); +// msgBox.exec(); - qApp->quit(); - return; - } - } - // Open the OpenMW config as a QFile - QFile file(pathStr.append("openmw.cfg")); +// qApp->quit(); +// return; +// } +// } +// // Open the OpenMW config as a QFile +// QFile file(pathStr.append("openmw.cfg")); - if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { - // File cannot be opened or created - QMessageBox msgBox; - msgBox.setWindowTitle("Error writing OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not open or create %0

\ - Please make sure you have the right permissions and try again.
").arg(file.fileName())); - msgBox.exec(); +// if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { +// // File cannot be opened or created +// QMessageBox msgBox; +// msgBox.setWindowTitle("Error writing OpenMW configuration file"); +// msgBox.setIcon(QMessageBox::Critical); +// msgBox.setStandardButtons(QMessageBox::Ok); +// msgBox.setText(tr("
Could not open or create %0

\ +// Please make sure you have the right permissions and try again.
").arg(file.fileName())); +// msgBox.exec(); - qApp->quit(); - return; - } +// qApp->quit(); +// return; +// } - QTextStream in(&file); - QByteArray buffer; +// QTextStream in(&file); +// QByteArray buffer; - // Remove all previous entries from config - while (!in.atEnd()) { - QString line = in.readLine(); - if (!line.startsWith("master") && - !line.startsWith("plugin") && - !line.startsWith("data") && - !line.startsWith("data-local")) - { - buffer += line += "\n"; - } - } +// // Remove all previous entries from config +// while (!in.atEnd()) { +// QString line = in.readLine(); +// if (!line.startsWith("master") && +// !line.startsWith("plugin") && +// !line.startsWith("data") && +// !line.startsWith("data-local")) +// { +// buffer += line += "\n"; +// } +// } - file.close(); +// file.close(); - // Now we write back the other config entries - if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error writing OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not write to %0

\ - Please make sure you have the right permissions and try again.
").arg(file.fileName())); - msgBox.exec(); +// // Now we write back the other config entries +// if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { +// QMessageBox msgBox; +// msgBox.setWindowTitle("Error writing OpenMW configuration file"); +// msgBox.setIcon(QMessageBox::Critical); +// msgBox.setStandardButtons(QMessageBox::Ok); +// msgBox.setText(tr("
Could not write to %0

\ +// Please make sure you have the right permissions and try again.
").arg(file.fileName())); +// msgBox.exec(); - qApp->quit(); - return; - } +// qApp->quit(); +// return; +// } - if (!buffer.isEmpty()) { - 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; - } - } +// QTextStream gameConfig(&file); - if (profile.isEmpty()) - profile = mProfilesComboBox->currentText(); +// QString path; - if (profile.isEmpty()) - return; +// // data= directories +// for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) { +// path = QString::fromStdString(it->string()); +// path.remove(QChar('\"')); - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } +// // Make sure the string is quoted when it contains spaces +// if (path.contains(" ")) { +// gameConfig << "data=\"" << path << "\"" << endl; +// } else { +// gameConfig << "data=" << path << endl; +// } +// } - mLauncherConfig->beginGroup("Profiles"); - mLauncherConfig->setValue("CurrentProfile", profile); +// // data-local directory +// if (!mDataLocal.empty()) { +// path = QString::fromStdString(mDataLocal.front().string()); +// path.remove(QChar('\"')); - // Open the profile-name subgroup - mLauncherConfig->beginGroup(profile); - mLauncherConfig->remove(""); // Clear the subgroup +// if (path.contains(" ")) { +// gameConfig << "data-local=\"" << path << "\"" << endl; +// } else { +// gameConfig << "data-local=" << path << endl; +// } +// } - // Now write the masters to the configs - const QStringList masters = mMastersModel->checkedItems(); - // We don't use foreach because we need i - for (int i = 0; i < masters.size(); ++i) { - const QString currentMaster = masters.at(i); +// if (profile.isEmpty()) +// profile = mProfilesComboBox->currentText(); - mLauncherConfig->setValue(QString("Master%0").arg(i), currentMaster); - gameConfig << "master=" << currentMaster << endl; +// if (profile.isEmpty()) +// return; - } +// // Make sure we have no groups open +// while (!mLauncherConfig->group().isEmpty()) { +// mLauncherConfig->endGroup(); +// } - // And finally write all checked plugins - const QStringList plugins = mPluginsModel->checkedItems(); +// mLauncherConfig->beginGroup("Profiles"); +// mLauncherConfig->setValue("CurrentProfile", profile); - 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; - } +// // Open the profile-name subgroup +// mLauncherConfig->beginGroup(profile); +// mLauncherConfig->remove(""); // Clear the subgroup - file.close(); - mLauncherConfig->endGroup(); - mLauncherConfig->endGroup(); - mLauncherConfig->sync(); +// // Now write the masters to the configs +// const QStringList masters = mMastersModel->checkedItems(); + +// // We don't use foreach because we need i +// for (int i = 0; i < masters.size(); ++i) { +// const QString currentMaster = masters.at(i); + +// mLauncherConfig->setValue(QString("Master%0").arg(i), currentMaster); +// gameConfig << "master=" << currentMaster << endl; + +// } + +// // And finally write all checked plugins +// const QStringList plugins = mPluginsModel->checkedItems(); + +// 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; +// } + +// file.close(); +// mLauncherConfig->endGroup(); +// mLauncherConfig->endGroup(); +// mLauncherConfig->sync(); } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 13668ec30..e40d29d60 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -3,9 +3,6 @@ #include #include -#include "utils/profilescombobox.hpp" -#include - class QTableView; class QSortFilterProxyModel; @@ -17,6 +14,8 @@ class ProfilesComboBox; class DataFilesModel; class TextInputDialog; +class ProfilesComboBox; +class GameSettings; namespace Files { struct ConfigurationManager; } @@ -25,13 +24,11 @@ class DataFilesPage : public QWidget Q_OBJECT public: - DataFilesPage(Files::ConfigurationManager& cfg, QWidget *parent = 0); + DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, QWidget *parent = 0); ProfilesComboBox *mProfilesComboBox; void writeConfig(QString profile = QString()); - bool showDataFilesWarning(); - bool setupDataFiles(); public slots: void setCheckState(QModelIndex index); @@ -76,10 +73,9 @@ private: QAction *mUncheckAction; Files::ConfigurationManager &mCfgMgr; - Files::PathContainer mDataDirs; - Files::PathContainer mDataLocal; QSettings *mLauncherConfig; + GameSettings &mGameSettings; TextInputDialog *mNewProfileDialog; @@ -87,6 +83,7 @@ private: // const QStringList selectedMasters(); void createActions(); + void setupDataFiles(); void setupConfig(); void readConfig(); diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 2c4f3430c..fa9d5d254 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -3,12 +3,12 @@ #include #include -#include #include #include -#include +//#include +#include "settings/graphicssettings.hpp" #include "utils/naturalsort.hpp" #include "graphicspage.hpp" @@ -25,9 +25,10 @@ QString getAspect(int x, int y) return QString(QString::number(xaspect) + ":" + QString::number(yaspect)); } -GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) - : QWidget(parent) - , mCfgMgr(cfg) +GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent) + : mCfgMgr(cfg) + , mGraphicsSettings(graphicsSetting) + , QWidget(parent) { QGroupBox *rendererGroup = new QGroupBox(tr("Renderer"), this); @@ -117,9 +118,8 @@ bool GraphicsPage::setupOgre() #endif } - boost::filesystem::path absPluginPath = boost::filesystem::absolute(boost::filesystem::path(pluginDir)); - - pluginDir = absPluginPath.string(); + QDir dir(QString::fromStdString(pluginDir)); + pluginDir = dir.absolutePath().toStdString(); Files::loadOgrePlugin(pluginDir, "RenderSystem_GL", *mOgre); Files::loadOgrePlugin(pluginDir, "RenderSystem_Direct3D9", *mOgre); @@ -154,20 +154,16 @@ bool GraphicsPage::setupOgre() msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not select a valid render system

\ - Please make sure the plugins.cfg file exists and contains a valid rendering plugin.
")); + Please make sure the plugins.cfg file exists and contains a valid rendering plugin.
")); msgBox.exec(); - return false; } // Now fill the GUI elements - int index = mRendererComboBox->findText(QString::fromStdString(Settings::Manager::getString("render system", "Video"))); - + int index = mRendererComboBox->findText(mGraphicsSettings.value(QString("Video/render system"))); if ( index != -1) { mRendererComboBox->setCurrentIndex(index); - } - else - { + } else { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 mRendererComboBox->setCurrentIndex(mRendererComboBox->findText(direct3DName)); #else @@ -180,45 +176,49 @@ bool GraphicsPage::setupOgre() mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); - readConfig(); + // Load the rest of the values + loadSettings(); return true; } -void GraphicsPage::readConfig() +void GraphicsPage::loadSettings() { - if (Settings::Manager::getBool("vsync", "Video")) - mVSyncCheckBox->setCheckState(Qt::Checked); + if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true")) + mVSyncCheckBox->setCheckState(Qt::Checked); - if (Settings::Manager::getBool("fullscreen", "Video")) - mFullScreenCheckBox->setCheckState(Qt::Checked); + if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true")) + mFullScreenCheckBox->setCheckState(Qt::Checked); - int aaIndex = mAntiAliasingComboBox->findText(QString::fromStdString(Settings::Manager::getString("antialiasing", "Video"))); - if (aaIndex != -1) - mAntiAliasingComboBox->setCurrentIndex(aaIndex); + int aaIndex = mAntiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); + if (aaIndex != -1) + mAntiAliasingComboBox->setCurrentIndex(aaIndex); - QString resolution = QString::number(Settings::Manager::getInt("resolution x", "Video")); - resolution.append(" x " + QString::number(Settings::Manager::getInt("resolution y", "Video"))); + QString resolution = mGraphicsSettings.value(QString("Video/resolution x")); + resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); - int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); - if (resIndex != -1) - mResolutionComboBox->setCurrentIndex(resIndex); + int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); + qDebug() << "resolution from file: " << resolution; + if (resIndex != -1) + mResolutionComboBox->setCurrentIndex(resIndex); } -void GraphicsPage::writeConfig() +void GraphicsPage::saveSettings() { - Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState()); - Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState()); - Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString()); - Settings::Manager::setString("render system", "Video", mRendererComboBox->currentText().toStdString()); + mVSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true")) + : mGraphicsSettings.setValue(QString("Video/vsync"), QString("false")); - // Get the current resolution, but with the tabs replaced with a single space - QString resolution = mResolutionComboBox->currentText().simplified(); - QStringList tokens = resolution.split(" ", QString::SkipEmptyParts); + mFullScreenCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("true")) + : mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("false")); - int resX = tokens.at(0).toInt(); - int resY = tokens.at(2).toInt(); - Settings::Manager::setInt("resolution x", "Video", resX); - Settings::Manager::setInt("resolution y", "Video", resY); + mGraphicsSettings.setValue(QString("Video/antialiasing"), mAntiAliasingComboBox->currentText()); + mGraphicsSettings.setValue(QString("Video/render system"), mRendererComboBox->currentText()); + + QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); + + if (resolutionRe.exactMatch(mResolutionComboBox->currentText().simplified())) { + mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); + mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); + } } QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer) @@ -232,16 +232,14 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy { Ogre::StringVector::iterator opt_it; uint idx = 0; - for (opt_it = i->second.possibleValues.begin (); - opt_it != i->second.possibleValues.end (); opt_it++, idx++) - { - if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) - { + for (opt_it = i->second.possibleValues.begin(); + opt_it != i->second.possibleValues.end(); opt_it++, idx++) + { + if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) { result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified(); } } - } // Sort ascending @@ -258,7 +256,7 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) { - QString key ("Video Mode"); + QString key("Video Mode"); QStringList result; uint row = 0; diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index b8166f672..48b9ff785 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -5,8 +5,8 @@ #include #include -#include -#include +//#include +//#include // Static plugin headers #ifdef ENABLE_PLUGIN_GL @@ -21,6 +21,8 @@ class QCheckBox; class QStackedWidget; class QSettings; +class GraphicsSettings; + namespace Files { struct ConfigurationManager; } class GraphicsPage : public QWidget @@ -28,10 +30,10 @@ class GraphicsPage : public QWidget Q_OBJECT public: - GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent = 0); + GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSettings, QWidget *parent = 0); + void saveSettings(); bool setupOgre(); - void writeConfig(); public slots: void rendererChanged(const QString &renderer); @@ -58,12 +60,14 @@ private: QCheckBox *mFullScreenCheckBox; Files::ConfigurationManager &mCfgMgr; + GraphicsSettings &mGraphicsSettings; QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); QStringList getAvailableResolutions(Ogre::RenderSystem *renderer); void createPages(); - void readConfig(); + void loadSettings(); + }; #endif diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 3fef62bc6..43bf50fbc 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -138,9 +138,7 @@ int main(int argc, char *argv[]) paths.clear(); paths.append(globalPath + QString("settings-default.cfg")); paths.append(QString("settings-default.cfg")); - paths.append(userPath + QString("settings.cfg")); - paths.append(QString("settings.cfg")); foreach (const QString &path, paths) { qDebug() << "Loading: " << path; @@ -166,14 +164,14 @@ int main(int argc, char *argv[]) } - MainDialog mainWin; - mainWin.setup(); + MainDialog mainWin(gameSettings, graphicsSettings); + + if (mainWin.setup()) { + mainWin.show(); + } else { + return 0; + } - mainWin.show(); - QCoreApplication::processEvents(); return app.exec(); - - - return 0; } diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 674ccdf67..4d3d24bd9 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -1,11 +1,20 @@ #include +#include "settings/gamesettings.hpp" +#include "settings/graphicssettings.hpp" + +#include "utils/profilescombobox.hpp" + #include "maindialog.hpp" #include "playpage.hpp" #include "graphicspage.hpp" #include "datafilespage.hpp" -MainDialog::MainDialog() +MainDialog::MainDialog(GameSettings &gameSettings, + GraphicsSettings &graphicsSettings) + : mGameSettings(gameSettings) + , mGraphicsSettings(graphicsSettings) + { QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); @@ -122,8 +131,8 @@ void MainDialog::createIcons() void MainDialog::createPages() { mPlayPage = new PlayPage(this); - mGraphicsPage = new GraphicsPage(mCfgMgr, this); - mDataFilesPage = new DataFilesPage(mCfgMgr, this); + mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this); + mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage mPlayPage->mProfilesComboBox->setModel(mDataFilesPage->mProfilesComboBox->model()); @@ -152,46 +161,17 @@ void MainDialog::createPages() bool MainDialog::setup() { - // Create the settings manager and load default settings file - const std::string localdefault = (mCfgMgr.getLocalPath() / "settings-default.cfg").string(); - const std::string globaldefault = (mCfgMgr.getGlobalPath() / "settings-default.cfg").string(); - - // prefer local - if (boost::filesystem::exists(localdefault)) { - mSettings.loadDefault(localdefault); - } else if (boost::filesystem::exists(globaldefault)) { - mSettings.loadDefault(globaldefault); - } else { - QMessageBox msgBox; - msgBox.setWindowTitle("Error reading OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not find %0

\ - The problem may be due to an incomplete installation of OpenMW.
\ - Reinstalling OpenMW may resolve the problem.").arg(QString::fromStdString(globaldefault))); - msgBox.exec(); - return false; - } - - // load user settings if they exist, otherwise just load the default settings as user settings - const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); - - if (boost::filesystem::exists(settingspath)) - mSettings.loadUser(settingspath); - else if (boost::filesystem::exists(localdefault)) - mSettings.loadUser(localdefault); - else if (boost::filesystem::exists(globaldefault)) - mSettings.loadUser(globaldefault); - // Setup the Graphics page if (!mGraphicsPage->setupOgre()) { return false; } // Setup the Data Files page + /* if (!mDataFilesPage->setupDataFiles()) { return false; - } + }*/ + return true; } @@ -208,11 +188,67 @@ void MainDialog::closeEvent(QCloseEvent *event) { // Now write all config files mDataFilesPage->writeConfig(); - mGraphicsPage->writeConfig(); + mGraphicsPage->saveSettings(); - // Save user settings - const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); - mSettings.saveUser(settingspath); + QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); + QDir dir(userPath); + + if (!dir.exists()) { + if (!dir.mkpath(userPath)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error creating OpenMW configuration directory"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not create %0

\ + Please make sure you have the right permissions \ + and try again.
").arg(userPath)); + msgBox.exec(); + event->accept(); + } + } + + // Game settings + QFile file(userPath + QString("openmw.cfg")); + + if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { + // File cannot be opened or created + QMessageBox msgBox; + msgBox.setWindowTitle("Error writing OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not open or create %0 for writing

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + event->accept(); + } + + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mGameSettings.writeFile(stream); + file.close(); + + // Graphics settings + file.setFileName(userPath + QString("settings.cfg")); + + if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { + // File cannot be opened or created + QMessageBox msgBox; + msgBox.setWindowTitle("Error writing OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not open or create %0 for writing

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + event->accept(); + } + + stream.setDevice(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mGraphicsSettings.writeFile(stream); event->accept(); } @@ -221,7 +257,7 @@ void MainDialog::play() { // First do a write of all the configs, just to be sure mDataFilesPage->writeConfig(); - mGraphicsPage->writeConfig(); + //mGraphicsPage->writeConfig(); // Save user settings const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index bf98011cc..c9654b874 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -17,12 +17,15 @@ class PlayPage; class GraphicsPage; class DataFilesPage; +class GameSettings; +class GraphicsSettings; + class MainDialog : public QMainWindow { Q_OBJECT public: - MainDialog(); + MainDialog(GameSettings &gameSettings, GraphicsSettings &GraphicsSettings); public slots: void changePage(QListWidgetItem *current, QListWidgetItem *previous); @@ -43,6 +46,10 @@ private: Files::ConfigurationManager mCfgMgr; Settings::Manager mSettings; + + GameSettings &mGameSettings; + GraphicsSettings &mGraphicsSettings; + }; #endif diff --git a/apps/launcher/utils/filedialog.cpp b/apps/launcher/utils/filedialog.cpp deleted file mode 100644 index 16d677533..000000000 --- a/apps/launcher/utils/filedialog.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "filedialog.hpp" -#include -#include - -FileDialog::FileDialog(QWidget *parent) - : QFileDialog(parent) -{ - // Remove the default Choose button to prevent it being updated elsewhere - QDialogButtonBox *box = qFindChild(this); - Q_ASSERT(box); - box->removeButton(box->button(QDialogButtonBox::Open)); - - // Add our own button so we can disable/enable it - mChooseButton = new QPushButton(tr("&Choose")); - mChooseButton->setIcon(QIcon::fromTheme("document-open")); - mChooseButton->setEnabled(false); - box->addButton(mChooseButton, QDialogButtonBox::AcceptRole); - - connect(this, SIGNAL(directoryEntered(const QString&)), this, SLOT(updateChooseButton(const QString&))); - emit directoryEntered(QDir::currentPath()); -} - -QString FileDialog::getExistingDirectory(QWidget *parent, - const QString &caption, - const QString &dir, - Options options) -{ - // create a non-native file dialog - FileDialog dialog; - dialog.setFileMode(DirectoryOnly); - dialog.setOptions(options |= QFileDialog::DontUseNativeDialog | QFileDialog::ShowDirsOnly | QFileDialog::ReadOnly); - - if (!caption.isEmpty()) - dialog.setWindowTitle(caption); - - if (!dir.isEmpty()) - dialog.setDirectory(dir); - - if (dialog.exec() == QDialog::Accepted) { - return dialog.selectedFiles().value(0); - } - return QString(); -} - -void FileDialog::updateChooseButton(const QString &directory) -{ - QDir currentDir = QDir(directory); - currentDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); - currentDir.setNameFilters(QStringList() << "*.esm" << "*.esp"); - - if (!currentDir.entryList().isEmpty()) { - // There are data files in the current dir - mChooseButton->setEnabled(true); - } else { - mChooseButton->setEnabled(false); - } -} diff --git a/apps/launcher/utils/filedialog.hpp b/apps/launcher/utils/filedialog.hpp deleted file mode 100644 index 7a161ecb9..000000000 --- a/apps/launcher/utils/filedialog.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef FILEDIALOG_HPP -#define FILEDIALOG_HPP - -#include - -class QPushButton; - -class FileDialog : public QFileDialog -{ - Q_OBJECT - -public: - FileDialog(QWidget *parent = 0); - - static QString getExistingDirectory(QWidget *parent = 0, - const QString &caption = QString(), - const QString &dir = QString(), - Options options = ShowDirsOnly); - -private slots: - void updateChooseButton(const QString &directory); - -private: - QPushButton *mChooseButton; -}; - - -#endif // FILEDIALOG_HPP From a461b282c15083e6987356a1643c7b8a5b4295a3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 1 Feb 2013 23:43:23 +0100 Subject: [PATCH 016/151] water ripples (experimental) --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 5 +- apps/openmw/mwrender/ripplesimulation.cpp | 212 ++++++++++++++++++ apps/openmw/mwrender/ripplesimulation.hpp | 72 ++++++ apps/openmw/mwrender/water.cpp | 14 +- apps/openmw/mwrender/water.hpp | 5 +- extern/shiny/Main/Factory.cpp | 2 + files/CMakeLists.txt | 7 + files/materials/core.h | 4 + files/materials/quad.mat | 2 +- files/materials/quad.shaderset | 2 +- files/materials/water.mat | 8 +- files/materials/water.shader | 28 ++- files/materials/watersim.mat | 59 +++++ files/materials/watersim.shaderset | 31 +++ files/materials/watersim_addimpulse.shader | 12 + files/materials/watersim_common.h | 25 +++ files/materials/watersim_heightmap.shader | 42 ++++ .../materials/watersim_heighttonormal.shader | 27 +++ files/water/circle.png | Bin 0 -> 753 bytes 20 files changed, 545 insertions(+), 14 deletions(-) create mode 100644 apps/openmw/mwrender/ripplesimulation.cpp create mode 100644 apps/openmw/mwrender/ripplesimulation.hpp create mode 100644 files/materials/watersim.mat create mode 100644 files/materials/watersim.shaderset create mode 100644 files/materials/watersim_addimpulse.shader create mode 100644 files/materials/watersim_common.h create mode 100644 files/materials/watersim_heightmap.shader create mode 100644 files/materials/watersim_heighttonormal.shader create mode 100644 files/water/circle.png diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 482007090..2c49e848e 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -16,7 +16,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderinginterface localmap occlusionquery terrain terrainmaterial water shadows - compositors characterpreview externalrendering globalmap videoplayer + compositors characterpreview externalrendering globalmap videoplayer ripplesimulation ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ff26b087c..3fed4d994 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -386,7 +386,10 @@ void RenderingManager::update (float duration, bool paused) *world->getPlayer().getPlayer().getCell()->mCell, Ogre::Vector3(cam.x, -cam.z, cam.y)) ); - mWater->update(duration); + + // MW to ogre coordinates + orig = Ogre::Vector3(orig.x, orig.z, -orig.y); + mWater->update(duration, orig); } } diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp new file mode 100644 index 000000000..6096c7ba3 --- /dev/null +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -0,0 +1,212 @@ +#include "ripplesimulation.hpp" + +#include +#include +#include +#include + +#include + +namespace MWRender +{ + + +RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) + : mMainSceneMgr(mainSceneManager), + mTime(0), + mCurrentFrameOffset(0,0), + mPreviousFrameOffset(0,0), + mRippleCenter(0,0), + mTextureSize(512), + mRippleAreaLength(1000), + mImpulseSize(20), + mTexelOffset(0,0) +{ + Ogre::AxisAlignedBox aabInf; + aabInf.setInfinite(); + + + mHeightToNormalMapMaterial = Ogre::MaterialManager::getSingleton().getByName("HeightToNormalMap"); + mHeightmapMaterial = Ogre::MaterialManager::getSingleton().getByName("HeightmapSimulation"); + + mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); + + mCamera = mSceneMgr->createCamera("RippleCamera"); + + mRectangle = new Ogre::Rectangle2D(true); + mRectangle->setBoundingBox(aabInf); + mRectangle->setCorners(-1.0, 1.0, 1.0, -1.0, false); + Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); + node->attachObject(mRectangle); + + mImpulse = new Ogre::Rectangle2D(true); + mImpulse->setCorners(-0.1, 0.1, 0.1, -0.1, false); + mImpulse->setBoundingBox(aabInf); + mImpulse->setMaterial("AddImpulse"); + Ogre::SceneNode* impulseNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); + impulseNode->attachObject(mImpulse); + + float w=0.05; + for (int i=0; i<4; ++i) + { + Ogre::TexturePtr texture; + if (i != 3) + texture = Ogre::TextureManager::getSingleton().createManual("RippleHeight" + Ogre::StringConverter::toString(i), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, mTextureSize, mTextureSize, 1, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); + else + texture = Ogre::TextureManager::getSingleton().createManual("RippleNormal", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, mTextureSize, mTextureSize, 1, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); + + + Ogre::RenderTexture* rt = texture->getBuffer()->getRenderTarget(); + rt->removeAllViewports(); + rt->addViewport(mCamera); + rt->setAutoUpdated(false); + rt->getViewport(0)->setClearEveryFrame(false); + + // debug overlay + Ogre::Rectangle2D* debugOverlay = new Ogre::Rectangle2D(true); + debugOverlay->setCorners(w*2-1, 0.9, (w+0.18)*2-1, 0.4, false); + w += 0.2; + debugOverlay->setBoundingBox(aabInf); + + Ogre::SceneNode* debugNode = mMainSceneMgr->getRootSceneNode()->createChildSceneNode(); + debugNode->attachObject(debugOverlay); + + Ogre::MaterialPtr debugMaterial = Ogre::MaterialManager::getSingleton().create("RippleDebug" + Ogre::StringConverter::toString(i), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + if (i != 3) + debugMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("RippleHeight" + Ogre::StringConverter::toString(i)); + else + debugMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("RippleNormal"); + debugMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false); + + debugOverlay->setMaterial("RippleDebug" + Ogre::StringConverter::toString(i)); + + mRenderTargets[i] = rt; + mTextures[i] = texture; + } + + sh::Factory::getInstance().setSharedParameter("rippleTextureSize", sh::makeProperty( + new sh::Vector4(1.0/512, 1.0/512, 512, 512))); + sh::Factory::getInstance().setSharedParameter("rippleCenter", sh::makeProperty( + new sh::Vector3(0, 0, 0))); + sh::Factory::getInstance().setSharedParameter("rippleAreaLength", sh::makeProperty( + new sh::FloatValue(mRippleAreaLength))); + +} + +RippleSimulation::~RippleSimulation() +{ + delete mRectangle; + + Ogre::Root::getSingleton().destroySceneManager(mSceneMgr); +} + +void RippleSimulation::update(float dt, Ogre::Vector2 position) +{ + // try to keep 20 fps + mTime += dt; + + while (mTime >= 1/20.0) + { + mPreviousFrameOffset = mCurrentFrameOffset; + + mCurrentFrameOffset = position - mRippleCenter; + // add texel offsets from previous frame. + mCurrentFrameOffset += mTexelOffset; + + mTexelOffset = Ogre::Vector2(std::fmod(mCurrentFrameOffset.x, 1.0f/mTextureSize), + std::fmod(mCurrentFrameOffset.y, 1.0f/mTextureSize)); + + // now subtract new offset in order to snap to texels + mCurrentFrameOffset -= mTexelOffset; + + // texture coordinate space + mCurrentFrameOffset /= mRippleAreaLength; + + std::cout << "Offset " << mCurrentFrameOffset << std::endl; + + mRippleCenter = position; + + addImpulses(); + waterSimulation(); + heightMapToNormalMap(); + + swapHeightMaps(); + mTime -= 1/20.0; + } + + sh::Factory::getInstance().setSharedParameter("rippleCenter", sh::makeProperty( + new sh::Vector3(mRippleCenter.x + mTexelOffset.x, mRippleCenter.y + mTexelOffset.y, 0))); +} + +void RippleSimulation::addImpulse(Ogre::Vector2 position) +{ + mImpulses.push(position); +} + +void RippleSimulation::addImpulses() +{ + mRectangle->setVisible(false); + mImpulse->setVisible(true); + + while (mImpulses.size()) + { + Ogre::Vector2 pos = mImpulses.front(); + pos -= mRippleCenter; + pos /= mRippleAreaLength; + float size = mImpulseSize / mRippleAreaLength; + mImpulse->setCorners(pos.x-size, pos.y+size, pos.x+size, pos.y-size, false); + mImpulses.pop(); + + mRenderTargets[1]->update(); + } + + mImpulse->setVisible(false); + mRectangle->setVisible(true); +} + +void RippleSimulation::waterSimulation() +{ + mRectangle->setMaterial("HeightmapSimulation"); + + sh::Factory::getInstance().setTextureAlias("Heightmap0", mTextures[0]->getName()); + sh::Factory::getInstance().setTextureAlias("Heightmap1", mTextures[1]->getName()); + + sh::Factory::getInstance().setSharedParameter("currentFrameOffset", sh::makeProperty( + new sh::Vector3(mCurrentFrameOffset.x, mCurrentFrameOffset.y, 0))); + sh::Factory::getInstance().setSharedParameter("previousFrameOffset", sh::makeProperty( + new sh::Vector3(mPreviousFrameOffset.x, mPreviousFrameOffset.y, 0))); + + mRenderTargets[2]->update(); +} + +void RippleSimulation::heightMapToNormalMap() +{ + mRectangle->setMaterial("HeightToNormalMap"); + + sh::Factory::getInstance().setTextureAlias("Heightmap2", mTextures[2]->getName()); + + mRenderTargets[TEX_NORMAL]->update(); +} + +void RippleSimulation::swapHeightMaps() +{ + // 0 -> 1 -> 2 to 2 -> 0 ->1 + Ogre::RenderTexture* tmp = mRenderTargets[0]; + Ogre::TexturePtr tmp2 = mTextures[0]; + + mRenderTargets[0] = mRenderTargets[1]; + mTextures[0] = mTextures[1]; + + mRenderTargets[1] = mRenderTargets[2]; + mTextures[1] = mTextures[2]; + + mRenderTargets[2] = tmp; + mTextures[2] = tmp2; +} + + +} diff --git a/apps/openmw/mwrender/ripplesimulation.hpp b/apps/openmw/mwrender/ripplesimulation.hpp new file mode 100644 index 000000000..6096fa866 --- /dev/null +++ b/apps/openmw/mwrender/ripplesimulation.hpp @@ -0,0 +1,72 @@ +#ifndef RIPPLE_SIMULATION_H +#define RIPPLE_SIMULATION_H + +#include +#include +#include + +namespace Ogre +{ + class RenderTexture; + class Camera; + class SceneManager; + class Rectangle2D; +} + +namespace MWRender +{ + +class RippleSimulation +{ +public: + RippleSimulation(Ogre::SceneManager* mainSceneManager); + ~RippleSimulation(); + + void update(float dt, Ogre::Vector2 position); + + void addImpulse (Ogre::Vector2 position); + +private: + Ogre::RenderTexture* mRenderTargets[4]; + Ogre::TexturePtr mTextures[4]; + + int mTextureSize; + float mRippleAreaLength; + float mImpulseSize; + + Ogre::Camera* mCamera; + + // own scenemanager to render our simulation + Ogre::SceneManager* mSceneMgr; + Ogre::Rectangle2D* mRectangle; + + // scenemanager to create the debug overlays on + Ogre::SceneManager* mMainSceneMgr; + + Ogre::MaterialPtr mHeightmapMaterial; + Ogre::MaterialPtr mHeightToNormalMapMaterial; + + static const int TEX_NORMAL = 3; + + Ogre::Rectangle2D* mImpulse; + + std::queue mImpulses; + + void addImpulses(); + void heightMapToNormalMap(); + void waterSimulation(); + void swapHeightMaps(); + + float mTime; + + Ogre::Vector2 mRippleCenter; + + Ogre::Vector2 mTexelOffset; + + Ogre::Vector2 mCurrentFrameOffset; + Ogre::Vector2 mPreviousFrameOffset; +}; + +} + +#endif diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 27b9fc679..6ee3890dd 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -12,6 +12,7 @@ #include "sky.hpp" #include "renderingmanager.hpp" #include "compositors.hpp" +#include "ripplesimulation.hpp" #include #include @@ -180,8 +181,11 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mActive(1), mToggled(1), mRendering(rend), mWaterTimer(0.f), - mReflection(NULL) + mReflection(NULL), + mSimulation(NULL) { + mSimulation = new RippleSimulation(mSceneMgr); + mSky = rend->getSkyManager(); mMaterial = MaterialManager::getSingleton().getByName("Water"); @@ -375,7 +379,7 @@ void Water::updateVisible() } } -void Water::update(float dt) +void Water::update(float dt, Ogre::Vector3 player) { /* Ogre::Vector3 pos = mCamera->getDerivedPosition (); @@ -387,6 +391,12 @@ void Water::update(float dt) sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(mWaterTimer))); mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); + + //if (player.y <= mTop) + { + mSimulation->addImpulse(Ogre::Vector2(player.x, player.z)); + } + mSimulation->update(dt, Ogre::Vector2(player.x, player.z)); } void Water::applyRTT() diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index de78542b7..97eb590b3 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -29,6 +29,7 @@ namespace MWRender { class SkyManager; class RenderingManager; + class RippleSimulation; class Reflection { @@ -110,6 +111,8 @@ namespace MWRender { float mWaterTimer; + RippleSimulation* mSimulation; + Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY); protected: @@ -137,7 +140,7 @@ namespace MWRender { void setActive(bool active); void toggle(); - void update(float dt); + void update(float dt, Ogre::Vector3 player); void assignTextures(); diff --git a/extern/shiny/Main/Factory.cpp b/extern/shiny/Main/Factory.cpp index 82d664811..6e87800e5 100644 --- a/extern/shiny/Main/Factory.cpp +++ b/extern/shiny/Main/Factory.cpp @@ -219,6 +219,8 @@ namespace sh break; } + std::cout << "loading " << it->first << std::endl; + MaterialInstance newInstance(it->first, this); newInstance.create(mPlatform); if (!mShadersEnabled) diff --git a/files/CMakeLists.txt b/files/CMakeLists.txt index e8426afb7..65ebc31a2 100644 --- a/files/CMakeLists.txt +++ b/files/CMakeLists.txt @@ -3,6 +3,7 @@ project(resources) set(WATER_FILES underwater_dome.mesh water_nm.png + circle.png ) set(GBUFFER_FILES @@ -43,6 +44,12 @@ set(MATERIAL_FILES selection.mat selection.shader selection.shaderset + watersim_heightmap.shader + watersim_addimpulse.shader + watersim_heighttonormal.shader + watersim_common.h + watersim.mat + watersim.shaderset ) copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}") diff --git a/files/materials/core.h b/files/materials/core.h index 0e46369ef..e498a3809 100644 --- a/files/materials/core.h +++ b/files/materials/core.h @@ -28,6 +28,8 @@ #define shNormalInput(type) , in type normal : NORMAL #define shColourInput(type) , in type colour : COLOR + + #define shFract(val) frac(val) #ifdef SH_VERTEX_SHADER @@ -64,6 +66,8 @@ #if SH_GLSL == 1 + #define shFract(val) fract(val) + @version 120 #define float2 vec2 diff --git a/files/materials/quad.mat b/files/materials/quad.mat index afb7f5111..a484d7f28 100644 --- a/files/materials/quad.mat +++ b/files/materials/quad.mat @@ -4,7 +4,7 @@ material quad pass { - vertex_program quad_vertex + vertex_program transform_vertex fragment_program quad_fragment depth_write $depth_write diff --git a/files/materials/quad.shaderset b/files/materials/quad.shaderset index c61497503..ee230a303 100644 --- a/files/materials/quad.shaderset +++ b/files/materials/quad.shaderset @@ -1,4 +1,4 @@ -shader_set quad_vertex +shader_set transform_vertex { source quad.shader type vertex diff --git a/files/materials/water.mat b/files/materials/water.mat index a5f9f2ec9..c427447d2 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -34,7 +34,13 @@ material Water { direct_texture water_nm.png } - + + texture_unit rippleNormalMap + { + direct_texture RippleNormal + tex_address_mode border + tex_border_colour 0.5 0.5 1.0 + } // for simple_water texture_unit animatedTexture diff --git a/files/materials/water.shader b/files/materials/water.shader index 9ebea0f00..1e14dd596 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -61,7 +61,7 @@ // Inspired by Blender GLSL Water by martinsh ( http://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html ) - +#define RIPPLES 1 #ifdef SH_VERTEX_SHADER @@ -119,8 +119,8 @@ #define WAVE_SCALE 75 // overall wave scale #define BUMP 1.5 // overall water surface bumpiness - #define REFL_BUMP 0.08 // reflection distortion amount - #define REFR_BUMP 0.06 // refraction distortion amount + #define REFL_BUMP 0.16 // reflection distortion amount + #define REFR_BUMP 0.12 // refraction distortion amount #define SCATTER_AMOUNT 3.0 // amount of sunlight scattering #define SCATTER_COLOUR gammaCorrectRead(float3(0.0,1.0,0.95)) // colour of sunlight scattering @@ -159,6 +159,11 @@ shInput(float3, screenCoordsPassthrough) shInput(float4, position) shInput(float, depthPassthrough) + + #if RIPPLES + shUniform(float3, rippleCenter) @shSharedParameter(rippleCenter, rippleCenter) + shUniform(float, rippleAreaLength) @shSharedParameter(rippleAreaLength, rippleAreaLength) + #endif shUniform(float, far) @shAutoConstant(far, far_clip_distance) @@ -166,6 +171,11 @@ shSampler2D(refractionMap) shSampler2D(depthMap) shSampler2D(normalMap) + + #if RIPPLES + shSampler2D(rippleNormalMap) + shUniform(float4x4, wMat) @shAutoConstant(wMat, world_matrix) + #endif shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) #define WIND_SPEED windDir_windSpeed.z @@ -220,8 +230,14 @@ float3 normal = (normal0 * BIG_WAVES_X + normal1 * BIG_WAVES_Y + normal2 * MID_WAVES_X + normal3 * MID_WAVES_Y + normal4 * SMALL_WAVES_X + normal5 * SMALL_WAVES_Y).xzy; - - normal = normalize(float3(normal.x * BUMP, normal.y, normal.z * BUMP)); + + float4 worldPosition = shMatrixMult(wMat, float4(position.xyz, 1)); + float2 relPos = (worldPosition.xz - rippleCenter.xy) / rippleAreaLength + 0.5; + float3 normal_ripple = normalize(shSample(rippleNormalMap, relPos.xy).xyz * 2 - 1); + normal_ripple = normal_ripple.xzy; + + normal = normalize(normal + normal_ripple); + // normal for sunlight scattering float3 lNormal = (normal0 * BIG_WAVES_X*0.5 + normal1 * BIG_WAVES_Y*0.5 + @@ -303,7 +319,7 @@ } shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); - + //shOutputColour(0).xyz = float3(relPos.x, relPos.y, 0); shOutputColour(0).w = 1; } diff --git a/files/materials/watersim.mat b/files/materials/watersim.mat new file mode 100644 index 000000000..b58b1a851 --- /dev/null +++ b/files/materials/watersim.mat @@ -0,0 +1,59 @@ +material HeightmapSimulation +{ + allow_fixed_function false + pass + { + depth_check off + depth_write off + vertex_program transform_vertex + fragment_program watersim_fragment + + texture_unit heightPrevSampler + { + tex_address_mode border + tex_border_colour 0 0 0 + texture_alias Heightmap0 + } + texture_unit heightCurrentSampler + { + tex_address_mode border + tex_border_colour 0 0 0 + texture_alias Heightmap1 + } + } +} + +material HeightToNormalMap +{ + allow_fixed_function false + pass + { + depth_check off + depth_write off + vertex_program transform_vertex + fragment_program height_to_normal_fragment + + texture_unit heightCurrentSampler + { + texture_alias Heightmap2 + } + } +} + +material AddImpulse +{ + allow_fixed_function false + pass + { + depth_check off + depth_write off + scene_blend alpha_blend + vertex_program transform_vertex + fragment_program add_impulse_fragment + + texture_unit alphaMap + { + texture circle.png + } + } +} diff --git a/files/materials/watersim.shaderset b/files/materials/watersim.shaderset new file mode 100644 index 000000000..ea512e25f --- /dev/null +++ b/files/materials/watersim.shaderset @@ -0,0 +1,31 @@ +shader_set transform_vertex +{ + source quad.shader + type vertex + profiles_cg vs_2_0 vp40 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set watersim_fragment +{ + source watersim_heightmap.shader + type fragment + profiles_cg ps_3_0 ps_2_x ps_2_0 fp40 arbfp1 + profiles_hlsl ps_3_0 ps_2_0 +} + +shader_set height_to_normal_fragment +{ + source watersim_heighttonormal.shader + type fragment + profiles_cg ps_3_0 ps_2_x ps_2_0 fp40 arbfp1 + profiles_hlsl ps_3_0 ps_2_0 +} + +shader_set add_impulse_fragment +{ + source watersim_addimpulse.shader + type fragment + profiles_cg ps_3_0 ps_2_x ps_2_0 fp40 arbfp1 + profiles_hlsl ps_3_0 ps_2_0 +} diff --git a/files/materials/watersim_addimpulse.shader b/files/materials/watersim_addimpulse.shader new file mode 100644 index 000000000..3ca4192cd --- /dev/null +++ b/files/materials/watersim_addimpulse.shader @@ -0,0 +1,12 @@ +#include "core.h" +#include "watersim_common.h" + + SH_BEGIN_PROGRAM + shInput(float2, UV) + shSampler2D(alphaMap) + + SH_START_PROGRAM + { + shOutputColour(0) = EncodeHeightmap(1.0); + shOutputColour(0).a = shSample (alphaMap, UV.xy).a; + } diff --git a/files/materials/watersim_common.h b/files/materials/watersim_common.h new file mode 100644 index 000000000..aa7a636a0 --- /dev/null +++ b/files/materials/watersim_common.h @@ -0,0 +1,25 @@ +float DecodeHeightmap(float4 heightmap) +{ + float4 table = float4(1.0, -1.0, 0.0, 0.0); + return dot(heightmap, table); +} + +float DecodeHeightmap(shTexture2D HeightmapSampler, float2 texcoord) +{ + float4 heightmap = shSample(HeightmapSampler, texcoord); + return DecodeHeightmap(heightmap); +} + +float4 EncodeHeightmap(float fHeight) +{ + float h = fHeight; + float positive = fHeight > 0.0 ? fHeight : 0.0; + float negative = fHeight < 0.0 ? -fHeight : 0.0; + + float4 color = float4(0,0,0,0); + + color.r = positive; + color.g = negative; + + return color; +} diff --git a/files/materials/watersim_heightmap.shader b/files/materials/watersim_heightmap.shader new file mode 100644 index 000000000..e19270d39 --- /dev/null +++ b/files/materials/watersim_heightmap.shader @@ -0,0 +1,42 @@ +#include "core.h" + +#define DAMPING 0.92 + +#include "watersim_common.h" + + SH_BEGIN_PROGRAM + shInput(float2, UV) + shSampler2D(heightPrevSampler) + shSampler2D(heightCurrentSampler) + shUniform(float3, previousFrameOffset) @shSharedParameter(previousFrameOffset, previousFrameOffset) + shUniform(float3, currentFrameOffset) @shSharedParameter(currentFrameOffset, currentFrameOffset) + shUniform(float4, rippleTextureSize) @shSharedParameter(rippleTextureSize, rippleTextureSize) + + SH_START_PROGRAM + { + 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) + ); + + float fHeightPrev = DecodeHeightmap(heightPrevSampler, UV.xy + previousFrameOffset.xy + currentFrameOffset.xy); + + float fNeighCurrent = 0; + for ( int i=0; i<4; i++ ) + { + float2 vTexcoord = UV + currentFrameOffset.xy + offset[i].xy * rippleTextureSize.xy; + fNeighCurrent += (DecodeHeightmap(heightCurrentSampler, vTexcoord) * offset[i].z); + } + + float fHeight = fNeighCurrent * 2.0 - fHeightPrev; + + fHeight *= DAMPING; + + shOutputColour(0) = EncodeHeightmap(fHeight); + } + + + + diff --git a/files/materials/watersim_heighttonormal.shader b/files/materials/watersim_heighttonormal.shader new file mode 100644 index 000000000..5402b6bb5 --- /dev/null +++ b/files/materials/watersim_heighttonormal.shader @@ -0,0 +1,27 @@ +#include "core.h" +#include "watersim_common.h" + + SH_BEGIN_PROGRAM + shInput(float2, UV) + shSampler2D(heightCurrentSampler) + shUniform(float4, rippleTextureSize) @shSharedParameter(rippleTextureSize, rippleTextureSize) + + 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) + ); + + float fHeightL = DecodeHeightmap(heightCurrentSampler, UV.xy + offset[0]*rippleTextureSize.xy); + float fHeightR = DecodeHeightmap(heightCurrentSampler, UV.xy + offset[1]*rippleTextureSize.xy); + float fHeightT = DecodeHeightmap(heightCurrentSampler, UV.xy + offset[2]*rippleTextureSize.xy); + float fHeightB = DecodeHeightmap(heightCurrentSampler, UV.xy + offset[3]*rippleTextureSize.xy); + + float3 n = float3(fHeightB - fHeightT, fHeightR - fHeightL, 1.0); + float3 normal = (n + 1.0) * 0.5; + + shOutputColour(0) = float4(normal.rgb, 1.0); + } diff --git a/files/water/circle.png b/files/water/circle.png new file mode 100644 index 0000000000000000000000000000000000000000..9a1cf268c0be2cdae27fe04ee7f7c0aa6de12c11 GIT binary patch literal 753 zcmVPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RY0s#yODLP_H6#xJL8FWQhbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b0$xc(K~#9!?VG<&8$l4pf3r}yK~51x zqM)L&3(GXPrAgYOr>3Lk4JgeU@D%ooAf>PicNCFA3Q(Fz0Zj_eDdq^q=iI@0XFq8g z%YXL!d^@wd^R1{VbwWh8fL)*q99VRLJ>Vno0NepLzy!Fqm;m2Y^|96gs%qr{w1Es5 z0s5aYvhQlwGS&)73oxjN^fEC9fHXz`BmM=rt&w;!ZtXYaT?GL8!0Zi)7h?wW-&_Eo z1q|Pjcrk`RYaK39whD+y2lxtX(=0pyJyo5S`A{fHKC|-FH1gP(CN{?E%OG&pphy0- zIIA=V0OuP-K9BQC1lX{DzVwsu8u@I4$>))+B>>QgfP5aEQe{v?TENeSX8UzZkrykKL0jHxq|slR18ie6i&%hJaRXJH0-u3>;>Esk{G0FcBq$;Re794Y znDGPnq(*%42{?2>9^-iUED6?plGC&pJy{2cNZSr3J>i3@-se-`2!A+Q%mJqk1vt&? z{+2BjJz_gp)50rugLP@Vq8qGLfHVc>U0Sc$6X17bhaaU*iUQ6N9PR-YaTl07 zGrZy^Fz@ww#UwEI<9Nk&62SWuNZVoa;f)=VAFJwPz7V={D8Lnv4n+fis@^-B24my= zq%SbQPhVj0%pc&sHD)iIIC%U|bkP;!y*-``5-%8}h7pn{vCMkPkFQUZP`xp5a z1uzk&z;OiRkC!^glT|jErITI0j0l@xp3c&hnGz`78L}VP0WKRv{?h9Flr;#YYjf%1 jWV$-*_wuxOzdrv5<*cfu_Ri)S00000NkvXXu0mjfBzZwt literal 0 HcmV?d00001 From 15e51b76de89c8366d6573700f63f6f6290c7e3d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Feb 2013 15:46:23 +0100 Subject: [PATCH 017/151] Experimental: Directional shading on local map, separated out refraction render, no longer uses screen depth --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/loadingscreen.cpp | 2 +- apps/openmw/mwrender/characterpreview.cpp | 9 ++-- apps/openmw/mwrender/localmap.cpp | 34 +++++++++---- apps/openmw/mwrender/localmap.hpp | 9 +++- apps/openmw/mwrender/npcanimation.cpp | 6 ++- apps/openmw/mwrender/occlusionquery.cpp | 7 ++- apps/openmw/mwrender/occlusionquery.hpp | 8 +++ apps/openmw/mwrender/refraction.cpp | 62 +++++++++++++++++++++++ apps/openmw/mwrender/refraction.hpp | 36 +++++++++++++ apps/openmw/mwrender/renderconst.hpp | 4 +- apps/openmw/mwrender/renderingmanager.cpp | 53 ++++++++++++------- apps/openmw/mwrender/renderingmanager.hpp | 8 +-- apps/openmw/mwrender/ripplesimulation.cpp | 11 ++-- apps/openmw/mwrender/ripplesimulation.hpp | 3 -- apps/openmw/mwrender/sky.cpp | 4 ++ apps/openmw/mwrender/sky.hpp | 1 + apps/openmw/mwrender/water.cpp | 34 +++++++++---- apps/openmw/mwrender/water.hpp | 5 +- apps/openmw/mwworld/weather.cpp | 4 +- extern/shiny/Main/Factory.cpp | 2 - files/materials/openmw.configuration | 1 - files/materials/water.mat | 2 +- files/materials/water.shader | 22 ++------ libs/openengine/ogre/renderer.cpp | 13 +++++ 25 files changed, 250 insertions(+), 92 deletions(-) create mode 100644 apps/openmw/mwrender/refraction.cpp create mode 100644 apps/openmw/mwrender/refraction.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 2c49e848e..94952329e 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -16,7 +16,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderinginterface localmap occlusionquery terrain terrainmaterial water shadows - compositors characterpreview externalrendering globalmap videoplayer ripplesimulation + compositors characterpreview externalrendering globalmap videoplayer ripplesimulation refraction ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index dd5289edb..8fecf4c34 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -150,7 +150,7 @@ namespace MWGui if (!mFirstLoad) { mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName()); - mRectangle->setVisible(true); + //mRectangle->setVisible(true); } for (unsigned int i = 0; igetNumCompositors(); ++i) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index a172d02b1..704d0b6fd 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -59,7 +59,7 @@ namespace MWRender mNode = renderRoot->createChildSceneNode(); mAnimation = new NpcAnimation(mCharacter, mNode, - MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), RV_PlayerPreview); + MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0); mNode->setVisible (false); @@ -81,7 +81,6 @@ namespace MWRender mViewport->setOverlaysEnabled(false); mViewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0, 0)); mViewport->setShadowsEnabled(false); - mViewport->setVisibilityMask (RV_PlayerPreview); mRenderTarget->setActive(true); mRenderTarget->setAutoUpdated (false); @@ -102,7 +101,7 @@ namespace MWRender delete mAnimation; mAnimation = new NpcAnimation(mCharacter, mNode, - MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), RV_PlayerPreview); + MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0); mNode->setVisible (false); @@ -118,6 +117,7 @@ namespace MWRender InventoryPreview::InventoryPreview(MWWorld::Ptr character) : CharacterPreview(character, 512, 1024, "CharacterPreview", Ogre::Vector3(0, 65, -180), Ogre::Vector3(0,65,0)) + , mSelectionBuffer(NULL) { } @@ -149,7 +149,8 @@ namespace MWRender void InventoryPreview::onSetup () { - mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, RV_PlayerPreview); + if (!mSelectionBuffer) + mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0); mAnimation->playGroup ("inventoryhandtohand", 0, 1); mAnimation->runAnimation (0); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index b34942d28..1d338df12 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -32,6 +32,12 @@ LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManag mCellCamera->setOrientation(Quaternion(sqrt0pt5, -sqrt0pt5, 0, 0)); mCameraNode->attachObject(mCellCamera); + + mLight = mRendering->getScene()->createLight(); + mLight->setType (Ogre::Light::LT_DIRECTIONAL); + mLight->setDirection (Ogre::Vector3(0.3, -0.7, 0.3)); + mLight->setVisible (false); + mLight->setDiffuseColour (ColourValue(0.7,0.7,0.7)); } LocalMap::~LocalMap() @@ -181,17 +187,14 @@ void LocalMap::render(const float x, const float y, const float zlow, const float zhigh, const float xw, const float yw, const std::string& texture) { - // disable fog - // changing FOG_MODE is not a solution when using shaders, thus we have to push linear start/end + // disable fog (only necessary for fixed function, the shader based + // materials already do this through local_map material configuration) const float fStart = mRendering->getScene()->getFogStart(); const float fEnd = mRendering->getScene()->getFogEnd(); const ColourValue& clr = mRendering->getScene()->getFogColour(); - mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, 1000000, 10000000); + mRendering->getScene()->setFog(FOG_NONE); // make everything visible - mRendering->getScene()->setAmbientLight(ColourValue(1,1,1)); - mRenderingManager->disableLights(); - mCameraNode->setPosition(Vector3(x, zhigh+100000, y)); //mCellCamera->setFarClipDistance( (zhigh-zlow) * 1.1 ); mCellCamera->setFarClipDistance(0); // infinite @@ -231,7 +234,8 @@ void LocalMap::render(const float x, const float y, // use fallback techniques without shadows and without mrt vp->setMaterialScheme("local_map"); - rtt->update(); + rtt->setAutoUpdated(true); + rtt->addListener(this); // create "fog of war" texture TexturePtr tex2 = TextureManager::getSingleton().createManual( @@ -263,12 +267,24 @@ void LocalMap::render(const float x, const float y, } } - mRenderingManager->enableLights(); - // re-enable fog mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd); } +void LocalMap::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) +{ + mRenderingManager->disableLights(true); + mLight->setVisible(true); + evt.source->setAutoUpdated(false); +} + +void LocalMap::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) +{ + mRenderingManager->enableLights(true); + mLight->setVisible(false); + evt.source->removeListener(this); +} + void LocalMap::getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y) { pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().z), mAngle); diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 1aedf1325..2b1aa3f62 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -4,6 +4,7 @@ #include #include +#include namespace MWWorld { @@ -17,7 +18,7 @@ namespace MWRender /// /// \brief Local map rendering /// - class LocalMap + class LocalMap : public Ogre::RenderTargetListener { public: LocalMap(OEngine::Render::OgreRenderer*, MWRender::RenderingManager* rendering); @@ -69,6 +70,9 @@ namespace MWRender */ bool isPositionExplored (float nX, float nY, int x, int y, bool interior); + void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + private: OEngine::Render::OgreRenderer* mRendering; MWRender::RenderingManager* mRenderingManager; @@ -90,6 +94,9 @@ namespace MWRender Ogre::SceneNode* mCameraPosNode; Ogre::SceneNode* mCameraRotNode; + // directional light from a fixed angle + Ogre::Light* mLight; + float mAngle; const Ogre::Vector2 rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index d33bdda91..52ad24523 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -95,7 +95,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor base->getUserObjectBindings ().setUserAny (Ogre::Any(-1)); - base->setVisibilityFlags(mVisibilityFlags); + if (mVisibilityFlags != 0) + base->setVisibilityFlags(mVisibilityFlags); bool transparent = false; for(unsigned int j=0;j < base->getNumSubEntities();++j) { @@ -362,7 +363,8 @@ NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int std::vector &parts = entities.mEntities; for(size_t i = 0;i < parts.size();i++) { - parts[i]->setVisibilityFlags(mVisibilityFlags); + if (mVisibilityFlags != 0) + parts[i]->setVisibilityFlags(mVisibilityFlags); parts[i]->getUserObjectBindings ().setUserAny (Ogre::Any(group)); } return entities; diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 6d3f67de9..c9e649fe6 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -16,7 +16,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mSingleObjectQuery(0), mActiveQuery(0), mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false), mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mDoQuery2(false), - mBBNode(0) + mBBNode(0), mActive(false) { mRendering = renderer; mSunNode = sunNode; @@ -108,8 +108,9 @@ bool OcclusionQuery::supported() void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source, const LightList* pLightList, bool suppressRenderStateChanges) { + if (!mActive) return; // The following code activates and deactivates the occlusion queries - // so that the queries only include the rendering of their intended targets + // so that the queries only include the rendering of the intended meshes // Close the last occlusion query // Each occlusion query should only last a single rendering @@ -146,6 +147,8 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocation, bool& repeatThisInvocation) { + if (!mActive) return; + if (mActiveQuery != NULL) { mActiveQuery->endOcclusionQuery(); diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index c76fcccd0..af6f668c1 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -29,6 +29,12 @@ namespace MWRender */ bool supported(); + /** + * make sure to disable occlusion queries before updating unrelated render targets + * @param active + */ + void setActive (bool active) { mActive = active; } + /** * per-frame update */ @@ -85,6 +91,8 @@ namespace MWRender bool mTestResult; + bool mActive; + bool mSupported; bool mDoQuery; bool mDoQuery2; diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp new file mode 100644 index 000000000..175b85223 --- /dev/null +++ b/apps/openmw/mwrender/refraction.cpp @@ -0,0 +1,62 @@ +#include "refraction.hpp" + +#include +#include +#include +#include +#include +#include + +#include "renderconst.hpp" + +namespace MWRender +{ + + Refraction::Refraction(Ogre::Camera *parentCamera) + : mParentCamera(parentCamera) + { + mCamera = mParentCamera->getSceneManager()->createCamera("RefractionCamera"); + + Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual("WaterRefraction", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); + + mRenderTarget = texture->getBuffer()->getRenderTarget(); + Ogre::Viewport* vp = mRenderTarget->addViewport(mCamera); + vp->setOverlaysEnabled(false); + vp->setShadowsEnabled(false); + vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain); + mRenderTarget->setAutoUpdated(true); + mRenderTarget->addListener(this); + } + + Refraction::~Refraction() + { + Ogre::TextureManager::getSingleton().remove("WaterRefraction"); + mParentCamera->getSceneManager()->destroyCamera(mCamera); + mRenderTarget->removeListener(this); + } + + void Refraction::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + { + mParentCamera->getParentSceneNode ()->needUpdate (); + mCamera->setOrientation(mParentCamera->getDerivedOrientation()); + mCamera->setPosition(mParentCamera->getDerivedPosition()); + mCamera->setNearClipDistance(mParentCamera->getNearClipDistance()); + mCamera->setFarClipDistance(mParentCamera->getFarClipDistance()); + mCamera->setAspectRatio(mParentCamera->getAspectRatio()); + mCamera->setFOVy(mParentCamera->getFOVy()); + + mCamera->enableCustomNearClipPlane(mNearClipPlane); + } + + void Refraction::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) + { + + } + + void Refraction::setWaterPlane(Ogre::Plane plane) + { + mNearClipPlane = Ogre::Plane(-plane.normal, - (plane.d + 5) ); + } + +} diff --git a/apps/openmw/mwrender/refraction.hpp b/apps/openmw/mwrender/refraction.hpp new file mode 100644 index 000000000..01ec86521 --- /dev/null +++ b/apps/openmw/mwrender/refraction.hpp @@ -0,0 +1,36 @@ +#ifndef MWRENDER_REFRACTION_H +#define MWRENDER_REFRACTION_H + +#include +#include + +namespace Ogre +{ + class Camera; + class RenderTarget; +} + +namespace MWRender +{ + + class Refraction : public Ogre::RenderTargetListener + { + + public: + Refraction(Ogre::Camera* parentCamera); + ~Refraction(); + + void setWaterPlane (Ogre::Plane plane); + void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + + private: + Ogre::Camera* mParentCamera; + Ogre::Camera* mCamera; + Ogre::RenderTarget* mRenderTarget; + Ogre::Plane mNearClipPlane; + }; + +} + +#endif diff --git a/apps/openmw/mwrender/renderconst.hpp b/apps/openmw/mwrender/renderconst.hpp index 75e243ec7..ee7e023a1 100644 --- a/apps/openmw/mwrender/renderconst.hpp +++ b/apps/openmw/mwrender/renderconst.hpp @@ -54,9 +54,7 @@ enum VisibilityFlags RV_OcclusionQuery = 256, - RV_PlayerPreview = 512, - - RV_Debug = 1024, + RV_Debug = 512, RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water }; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3fed4d994..18337c7d7 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -334,8 +334,13 @@ void RenderingManager::update (float duration, bool paused) mPlayer->setCameraDistance(test.second * orig.distance(dest), false, false); } } + mOcclusionQuery->update(duration); - + + // deactivate queries to make sure we aren't getting false results from several misc render targets + // (will be reactivated at the bottom of this method) + mOcclusionQuery->setActive(false); + mVideoPlayer->update (); mRendering.update(duration); @@ -391,6 +396,8 @@ void RenderingManager::update (float duration, bool paused) orig = Ogre::Vector3(orig.x, orig.z, -orig.y); mWater->update(duration, orig); } + + mOcclusionQuery->setActive(true); } void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store) @@ -608,22 +615,28 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour) mTerrainManager->setAmbient(colour); } -void RenderingManager::sunEnable() +void RenderingManager::sunEnable(bool real) { - // Don't disable the light, as the shaders assume the first light to be directional. - //if (mSun) mSun->setVisible(true); - mSunEnabled = true; + if (real && mSun) mSun->setVisible(true); + else + { + // Don't disable the light, as the shaders assume the first light to be directional. + mSunEnabled = true; + } } -void RenderingManager::sunDisable() +void RenderingManager::sunDisable(bool real) { - // Don't disable the light, as the shaders assume the first light to be directional. - //if (mSun) mSun->setVisible(false); - mSunEnabled = false; - if (mSun) + if (real && mSun) mSun->setVisible(false); + else { - mSun->setDiffuseColour(ColourValue(0,0,0)); - mSun->setSpecularColour(ColourValue(0,0,0)); + // Don't disable the light, as the shaders assume the first light to be directional. + mSunEnabled = false; + if (mSun) + { + mSun->setDiffuseColour(ColourValue(0,0,0)); + mSun->setSpecularColour(ColourValue(0,0,0)); + } } } @@ -654,16 +667,16 @@ void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell) mLocalMap->saveFogOfWar(cell); } -void RenderingManager::disableLights() +void RenderingManager::disableLights(bool sun) { mObjects.disableLights(); - sunDisable(); + sunDisable(sun); } -void RenderingManager::enableLights() +void RenderingManager::enableLights(bool sun) { mObjects.enableLights(); - sunEnable(); + sunEnable(sun); } const bool RenderingManager::useMRT() @@ -867,14 +880,16 @@ void RenderingManager::applyCompositors() mCompositors->removeAll(); if (useMRT()) { + /* mCompositors->addCompositor("gbuffer", 0); mCompositors->setCompositorEnabled("gbuffer", true); mCompositors->addCompositor("gbufferFinalizer", 2); mCompositors->setCompositorEnabled("gbufferFinalizer", true); - } + */ +} - if (mWater) - mWater->assignTextures(); + //if (mWater) + //mWater->assignTextures(); } void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned int &batches) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 68f2d79c3..0a92bb2ea 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -131,11 +131,11 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void setAmbientColour(const Ogre::ColourValue& colour); void setSunColour(const Ogre::ColourValue& colour); void setSunDirection(const Ogre::Vector3& direction); - void sunEnable(); - void sunDisable(); + void sunEnable(bool real); ///< @param real whether or not to really disable the sunlight (otherwise just set diffuse to 0) + void sunDisable(bool real); - void disableLights(); - void enableLights(); + void disableLights(bool sun); ///< @param sun whether or not to really disable the sunlight (otherwise just set diffuse to 0) + void enableLights(bool sun); bool occlusionQuerySupported() { return mOcclusionQuery->supported(); } OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; } diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index 6096c7ba3..043757e88 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -25,10 +25,6 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) Ogre::AxisAlignedBox aabInf; aabInf.setInfinite(); - - mHeightToNormalMapMaterial = Ogre::MaterialManager::getSingleton().getByName("HeightToNormalMap"); - mHeightmapMaterial = Ogre::MaterialManager::getSingleton().getByName("HeightmapSimulation"); - mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); mCamera = mSceneMgr->createCamera("RippleCamera"); @@ -46,7 +42,7 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) Ogre::SceneNode* impulseNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); impulseNode->attachObject(mImpulse); - float w=0.05; + //float w=0.05; for (int i=0; i<4; ++i) { Ogre::TexturePtr texture; @@ -65,11 +61,11 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) rt->getViewport(0)->setClearEveryFrame(false); // debug overlay + /* Ogre::Rectangle2D* debugOverlay = new Ogre::Rectangle2D(true); debugOverlay->setCorners(w*2-1, 0.9, (w+0.18)*2-1, 0.4, false); w += 0.2; debugOverlay->setBoundingBox(aabInf); - Ogre::SceneNode* debugNode = mMainSceneMgr->getRootSceneNode()->createChildSceneNode(); debugNode->attachObject(debugOverlay); @@ -83,6 +79,7 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) debugMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false); debugOverlay->setMaterial("RippleDebug" + Ogre::StringConverter::toString(i)); + */ mRenderTargets[i] = rt; mTextures[i] = texture; @@ -126,8 +123,6 @@ void RippleSimulation::update(float dt, Ogre::Vector2 position) // texture coordinate space mCurrentFrameOffset /= mRippleAreaLength; - std::cout << "Offset " << mCurrentFrameOffset << std::endl; - mRippleCenter = position; addImpulses(); diff --git a/apps/openmw/mwrender/ripplesimulation.hpp b/apps/openmw/mwrender/ripplesimulation.hpp index 6096fa866..72ff3dbd8 100644 --- a/apps/openmw/mwrender/ripplesimulation.hpp +++ b/apps/openmw/mwrender/ripplesimulation.hpp @@ -43,9 +43,6 @@ private: // scenemanager to create the debug overlays on Ogre::SceneManager* mMainSceneMgr; - Ogre::MaterialPtr mHeightmapMaterial; - Ogre::MaterialPtr mHeightToNormalMapMaterial; - static const int TEX_NORMAL = 3; Ogre::Rectangle2D* mImpulse; diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 60ecd4303..91277ebf6 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -628,6 +628,10 @@ void SkyManager::setLightningStrength(const float factor) else mLightning->setVisible(false); } +void SkyManager::setLightningEnabled(bool enabled) +{ + /// \todo +} void SkyManager::setLightningDirection(const Ogre::Vector3& dir) { diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index ee1360853..04d56d4af 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -167,6 +167,7 @@ namespace MWRender void setLightningStrength(const float factor); void setLightningDirection(const Ogre::Vector3& dir); + void setLightningEnabled(bool enabled); ///< disable prior to map render void setGlare(const float glare); void setGlareEnabled(bool enabled); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 6ee3890dd..0533388bc 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -13,6 +13,7 @@ #include "renderingmanager.hpp" #include "compositors.hpp" #include "ripplesimulation.hpp" +#include "refraction.hpp" #include #include @@ -85,7 +86,7 @@ PlaneReflection::PlaneReflection(Ogre::SceneManager* sceneManager, SkyManager* s mSceneMgr->addRenderQueueListener(this); mTexture = TextureManager::getSingleton().createManual("WaterReflection", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, 512, 512, 0, PF_A8R8G8B8, TU_RENDERTARGET); + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, 512, 512, 0, PF_R8G8B8, TU_RENDERTARGET); mRenderTarget = mTexture->getBuffer()->getRenderTarget(); Viewport* vp = mRenderTarget->addViewport(mCamera); @@ -96,6 +97,7 @@ PlaneReflection::PlaneReflection(Ogre::SceneManager* sceneManager, SkyManager* s vp->setMaterialScheme("water_reflection"); mRenderTarget->addListener(this); mRenderTarget->setActive(true); + mRenderTarget->setAutoUpdated(true); sh::Factory::getInstance ().setTextureAlias ("WaterReflection", mTexture->getName()); } @@ -104,6 +106,7 @@ PlaneReflection::~PlaneReflection () { mRenderTarget->removeListener (this); mSceneMgr->destroyCamera (mCamera); + mSceneMgr->removeRenderQueueListener(this); TextureManager::getSingleton ().remove("WaterReflection"); } @@ -127,7 +130,7 @@ void PlaneReflection::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::St } } -void PlaneReflection::preRenderTargetUpdate(const RenderTargetEvent& evt) +void PlaneReflection::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { mParentCamera->getParentSceneNode ()->needUpdate (); mCamera->setOrientation(mParentCamera->getDerivedOrientation()); @@ -144,7 +147,7 @@ void PlaneReflection::preRenderTargetUpdate(const RenderTargetEvent& evt) mCamera->enableReflection(mWaterPlane); } -void PlaneReflection::postRenderTargetUpdate(const RenderTargetEvent& evt) +void PlaneReflection::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { mSky->resetSkyPosition(); mCamera->disableReflection(); @@ -232,7 +235,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel sh::MaterialInstance* m = sh::Factory::getInstance ().getMaterialInstance ("Water"); m->setListener (this); - // ---------------------------------------------------------------------------------------------- // ---------------------------------- reflection debug overlay ---------------------------------- // ---------------------------------------------------------------------------------------------- @@ -296,6 +298,9 @@ Water::~Water() mWaterNode->detachObject(mWater); mSceneMgr->destroyEntity(mWater); mSceneMgr->destroySceneNode(mWaterNode); + + delete mReflection; + delete mRefraction; } void Water::changeCell(const ESM::Cell* cell) @@ -316,6 +321,8 @@ void Water::setHeight(const float height) if (mReflection) mReflection->setWaterPlane(mWaterPlane); + if (mRefraction) + mRefraction->setWaterPlane(mWaterPlane); mWaterNode->setPosition(0, height, 0); sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(height))); @@ -353,7 +360,7 @@ void Water::assignTextures() { if (Settings::Manager::getBool("shader", "Water")) { - +/* CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer"); TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0); @@ -361,6 +368,7 @@ void Water::assignTextures() TexturePtr depthTexture = compositor->getTextureInstance("mrt_output", 1); sh::Factory::getInstance ().setTextureAlias ("SceneDepth", depthTexture->getName()); + */ } } @@ -397,15 +405,15 @@ void Water::update(float dt, Ogre::Vector3 player) mSimulation->addImpulse(Ogre::Vector2(player.x, player.z)); } mSimulation->update(dt, Ogre::Vector2(player.x, player.z)); + + if (mReflection) + mReflection->update(); } void Water::applyRTT() { - if (mReflection) - { - delete mReflection; - mReflection = NULL; - } + delete mReflection; + mReflection = NULL; // Create rendertarget for reflection int rttsize = Settings::Manager::getInt("rtt size", "Water"); @@ -419,6 +427,12 @@ void Water::applyRTT() } else mWater->setRenderQueueGroup(RQG_Alpha); + + + delete mRefraction; + mRefraction = NULL; + + mRefraction = new Refraction(mCamera); } void Water::applyVisibilityMask() diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 97eb590b3..67c788c81 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -30,12 +30,14 @@ namespace MWRender { class SkyManager; class RenderingManager; class RippleSimulation; + class Refraction; class Reflection { public: Reflection(Ogre::SceneManager* sceneManager) : mSceneMgr(sceneManager) {} + virtual ~Reflection() {} virtual void setWaterPlane (Ogre::Plane plane) {} virtual void setParentCamera (Ogre::Camera* parent) { mParentCamera = parent; } @@ -111,7 +113,6 @@ namespace MWRender { float mWaterTimer; - RippleSimulation* mSimulation; Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY); @@ -132,6 +133,8 @@ namespace MWRender { int mVisibilityFlags; Reflection* mReflection; + Refraction* mRefraction; + RippleSimulation* mSimulation; public: Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell); diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 917a8d7d4..514276f9b 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -718,14 +718,14 @@ void WeatherManager::update(float duration) mRendering->getSkyManager()->setLightningStrength(0.f); mRendering->setAmbientColour(result.mAmbientColor); - mRendering->sunEnable(); + mRendering->sunEnable(false); mRendering->setSunColour(result.mSunColor); mRendering->getSkyManager()->setWeather(result); } else { - mRendering->sunDisable(); + mRendering->sunDisable(false); mRendering->skyDisable(); mRendering->getSkyManager()->setLightningStrength(0.f); } diff --git a/extern/shiny/Main/Factory.cpp b/extern/shiny/Main/Factory.cpp index 6e87800e5..82d664811 100644 --- a/extern/shiny/Main/Factory.cpp +++ b/extern/shiny/Main/Factory.cpp @@ -219,8 +219,6 @@ namespace sh break; } - std::cout << "loading " << it->first << std::endl; - MaterialInstance newInstance(it->first, this); newInstance.create(mPlatform); if (!mShadersEnabled) diff --git a/files/materials/openmw.configuration b/files/materials/openmw.configuration index ee97451d3..db3693dd6 100644 --- a/files/materials/openmw.configuration +++ b/files/materials/openmw.configuration @@ -10,7 +10,6 @@ configuration local_map { fog false mrt_output false - lighting false shadows false shadows_pssm false simple_water true diff --git a/files/materials/water.mat b/files/materials/water.mat index c427447d2..2717f26fc 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -20,7 +20,7 @@ material Water texture_unit refractionMap { - texture_alias WaterRefraction + direct_texture WaterRefraction tex_address_mode clamp } diff --git a/files/materials/water.shader b/files/materials/water.shader index 1e14dd596..dbe36a91c 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -201,13 +201,9 @@ SH_START_PROGRAM { - float2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z; screenCoords.y = (1-shSaturate(renderTargetFlipping))+renderTargetFlipping*screenCoords.y; - float depth = shSample(depthMap, screenCoords).x * far - depthPassthrough; - float shoreFade = shSaturate(depth / 50.0); - float2 nCoord = float2(0,0); nCoord = UV * (WAVE_SCALE * 0.05) + WIND_DIR * waterTimer * (WIND_SPEED*0.04); @@ -272,14 +268,8 @@ // refraction float3 R = reflect(vVec, normal); - - // check the depth at the refracted coords, and don't do any normal distortion for the refraction if the object to refract - // is actually above the water (objectDepth < waterDepth) - // this solves silhouettes around objects above the water - float refractDepth = shSample(depthMap, screenCoords-(shoreFade * normal.xz*REFR_BUMP)).x * far - depthPassthrough; - float doRefraction = (refractDepth < 0) ? 0.f : 1.f; - - float3 refraction = gammaCorrectRead(shSample(refractionMap, (screenCoords-(shoreFade * normal.xz*REFR_BUMP * doRefraction))*1.0).rgb); + + float3 refraction = gammaCorrectRead(shSample(refractionMap, (screenCoords-(normal.xz*REFR_BUMP))*1.0).rgb); // brighten up the refraction underwater refraction = (cameraPos.y < 0) ? shSaturate(refraction * 1.5) : refraction; @@ -288,10 +278,7 @@ float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS); shOutputColour(0).xyz = shLerp( shLerp(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpecular.xyz; - - // smooth transition to shore (above water only) - shOutputColour(0).xyz = shLerp(shOutputColour(0).xyz, refraction, (1-shoreFade) * (1-isUnderwater)); - + // fog if (isUnderwater == 1) { @@ -319,8 +306,7 @@ } shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); - //shOutputColour(0).xyz = float3(relPos.x, relPos.y, 0); - shOutputColour(0).w = 1; + shOutputColour(0).w = 1; } #endif diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index ed5cc9b43..e6e1d46b8 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -210,11 +210,24 @@ 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 + /// \todo Why does this break occlusion queries? :( + /* + 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)); params.insert(std::make_pair("vsync", settings.vsync ? "true" : "false")); + mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms); // create the semi-transparent black background texture used by the GUI. From 5334934612d49b065f71c78717c27c08d1e5ae2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Feb 2013 18:03:09 +0100 Subject: [PATCH 018/151] Listen to render window updates and properly activate/deactivate occlusion queries pre/post update. --- apps/openmw/mwrender/refraction.cpp | 5 +++-- apps/openmw/mwrender/renderingmanager.cpp | 19 ++++++++++++++----- apps/openmw/mwrender/renderingmanager.hpp | 8 +++++++- apps/openmw/mwrender/water.cpp | 3 ++- libs/openengine/ogre/renderer.cpp | 1 - 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index 175b85223..88ad70b7f 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -31,9 +31,9 @@ namespace MWRender Refraction::~Refraction() { + mRenderTarget->removeListener(this); Ogre::TextureManager::getSingleton().remove("WaterRefraction"); mParentCamera->getSceneManager()->destroyCamera(mCamera); - mRenderTarget->removeListener(this); } void Refraction::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) @@ -56,7 +56,8 @@ namespace MWRender void Refraction::setWaterPlane(Ogre::Plane plane) { - mNearClipPlane = Ogre::Plane(-plane.normal, - (plane.d + 5) ); + /// \todo + mNearClipPlane = Ogre::Plane( -Ogre::Vector3(0,1,0), 0); } } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 18337c7d7..b2e18f1e8 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -62,6 +62,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); mRendering.setWindowEventListener(this); + mRendering.getWindow()->addListener(this); + mCompositors = new Compositors(mRendering.getViewport()); mWater = 0; @@ -174,6 +176,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const RenderingManager::~RenderingManager () { + mRendering.getWindow()->removeListener(this); mRendering.removeWindowEventListener(this); delete mPlayer; @@ -337,10 +340,6 @@ void RenderingManager::update (float duration, bool paused) mOcclusionQuery->update(duration); - // deactivate queries to make sure we aren't getting false results from several misc render targets - // (will be reactivated at the bottom of this method) - mOcclusionQuery->setActive(false); - mVideoPlayer->update (); mRendering.update(duration); @@ -396,10 +395,20 @@ void RenderingManager::update (float duration, bool paused) orig = Ogre::Vector3(orig.x, orig.z, -orig.y); mWater->update(duration, orig); } +} +void RenderingManager::preRenderTargetUpdate(const RenderTargetEvent &evt) +{ mOcclusionQuery->setActive(true); } +void RenderingManager::postRenderTargetUpdate(const RenderTargetEvent &evt) +{ + // deactivate queries to make sure we aren't getting false results from several misc render targets + // (will be reactivated at the bottom of this method) + mOcclusionQuery->setActive(false); +} + void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store) { const MWWorld::Store &lands = @@ -886,7 +895,7 @@ void RenderingManager::applyCompositors() mCompositors->addCompositor("gbufferFinalizer", 2); mCompositors->setCompositorEnabled("gbufferFinalizer", true); */ -} + } //if (mWater) //mWater->assignTextures(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 0a92bb2ea..71ac742c2 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -11,6 +11,8 @@ #include +#include + #include "renderinginterface.hpp" #include "objects.hpp" @@ -47,7 +49,7 @@ namespace MWRender class GlobalMap; class VideoPlayer; -class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener { +class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener, public Ogre::RenderTargetListener { private: @@ -137,6 +139,10 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void disableLights(bool sun); ///< @param sun whether or not to really disable the sunlight (otherwise just set diffuse to 0) void enableLights(bool sun); + + void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + bool occlusionQuerySupported() { return mOcclusionQuery->supported(); } OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 0533388bc..4ef2aea66 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -185,6 +185,7 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mRendering(rend), mWaterTimer(0.f), mReflection(NULL), + mRefraction(NULL), mSimulation(NULL) { mSimulation = new RippleSimulation(mSceneMgr); @@ -317,7 +318,7 @@ void Water::setHeight(const float height) { mTop = height; - mWaterPlane = Plane(Vector3::UNIT_Y, height); + mWaterPlane = Plane(Vector3::UNIT_Y, -height); if (mReflection) mReflection->setWaterPlane(mWaterPlane); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index e6e1d46b8..039aba226 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -211,7 +211,6 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& mRoot->initialise(false); // create a hidden 1x1 background window to keep resources when recreating the secondary (real) window - /// \todo Why does this break occlusion queries? :( /* NameValuePairList params_; params_.insert(std::make_pair("title", title)); From 979a874220267be05b290314846ce34bd054f4d6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Feb 2013 19:01:59 +0100 Subject: [PATCH 019/151] Fixed the custom near clip planes --- apps/openmw/mwrender/refraction.cpp | 6 +++--- apps/openmw/mwrender/refraction.hpp | 2 +- apps/openmw/mwrender/water.cpp | 13 +++++++------ apps/openmw/mwrender/water.hpp | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index 88ad70b7f..85642bc08 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -25,6 +25,7 @@ namespace MWRender vp->setOverlaysEnabled(false); vp->setShadowsEnabled(false); vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain); + vp->setMaterialScheme("water_reflection"); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); } @@ -54,10 +55,9 @@ namespace MWRender } - void Refraction::setWaterPlane(Ogre::Plane plane) + void Refraction::setHeight(float height) { - /// \todo - mNearClipPlane = Ogre::Plane( -Ogre::Vector3(0,1,0), 0); + mNearClipPlane = Ogre::Plane( -Ogre::Vector3(0,1,0), -(height + 5)); } } diff --git a/apps/openmw/mwrender/refraction.hpp b/apps/openmw/mwrender/refraction.hpp index 01ec86521..e3777d9cf 100644 --- a/apps/openmw/mwrender/refraction.hpp +++ b/apps/openmw/mwrender/refraction.hpp @@ -20,7 +20,7 @@ namespace MWRender Refraction(Ogre::Camera* parentCamera); ~Refraction(); - void setWaterPlane (Ogre::Plane plane); + void setHeight (float height); void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 4ef2aea66..877a9a953 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -155,10 +155,10 @@ void PlaneReflection::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) mRenderActive = false; } -void PlaneReflection::setWaterPlane (Plane plane) +void PlaneReflection::setHeight (float height) { - mWaterPlane = plane; - mErrorPlane = Plane(plane.normal, mWaterPlane.d - 5); + mWaterPlane = Plane(Ogre::Vector3(0,1,0), height); + mErrorPlane = Plane(Ogre::Vector3(0,1,0), height - 5); } void PlaneReflection::setActive (bool active) @@ -321,9 +321,9 @@ void Water::setHeight(const float height) mWaterPlane = Plane(Vector3::UNIT_Y, -height); if (mReflection) - mReflection->setWaterPlane(mWaterPlane); + mReflection->setHeight(height); if (mRefraction) - mRefraction->setWaterPlane(mWaterPlane); + mRefraction->setHeight(height); mWaterNode->setPosition(0, height, 0); sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(height))); @@ -423,7 +423,7 @@ void Water::applyRTT() { mReflection = new PlaneReflection(mSceneMgr, mSky); mReflection->setParentCamera (mCamera); - mReflection->setWaterPlane(mWaterPlane); + mReflection->setHeight(mTop); mWater->setRenderQueueGroup(RQG_Water); } else @@ -434,6 +434,7 @@ void Water::applyRTT() mRefraction = NULL; mRefraction = new Refraction(mCamera); + mRefraction->setHeight(mTop); } void Water::applyVisibilityMask() diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 67c788c81..cf181674a 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -39,7 +39,7 @@ namespace MWRender { : mSceneMgr(sceneManager) {} virtual ~Reflection() {} - virtual void setWaterPlane (Ogre::Plane plane) {} + virtual void setHeight (float height) {} virtual void setParentCamera (Ogre::Camera* parent) { mParentCamera = parent; } void setUnderwater(bool underwater) { mIsUnderwater = underwater; } virtual void setActive (bool active) {} @@ -72,7 +72,7 @@ namespace MWRender { PlaneReflection(Ogre::SceneManager* sceneManager, SkyManager* sky); virtual ~PlaneReflection(); - virtual void setWaterPlane (Ogre::Plane plane); + virtual void setHeight (float height); virtual void setActive (bool active); virtual void setVisibilityMask (int flags); From a44dfcd2acaf65ea657a14545b718718957e4872 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Feb 2013 19:28:31 +0100 Subject: [PATCH 020/151] Now that refraction is separated out, we don't have to worry about rendering order. Should fix transparency blending issues around water (eg waterfalls) for good. --- apps/openmw/mwrender/renderingmanager.cpp | 10 +++++----- apps/openmw/mwrender/water.cpp | 5 +---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b2e18f1e8..aa73bc49b 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -867,8 +867,8 @@ void RenderingManager::windowResized(Ogre::RenderWindow* rw) mVideoPlayer->setResolution (rw->getWidth(), rw->getHeight()); const Settings::CategorySettingVector& changed = Settings::Manager::apply(); - MWBase::Environment::get().getInputManager()->processChangedSettings(changed); //FIXME - MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); // FIXME + MWBase::Environment::get().getInputManager()->processChangedSettings(changed); + MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); } void RenderingManager::windowClosed(Ogre::RenderWindow* rw) @@ -878,9 +878,9 @@ void RenderingManager::windowClosed(Ogre::RenderWindow* rw) bool RenderingManager::waterShaderSupported() { - const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); - if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) - return false; + //const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); + //if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) + //return false; return true; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 877a9a953..0eb35323d 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -424,11 +424,8 @@ void Water::applyRTT() mReflection = new PlaneReflection(mSceneMgr, mSky); mReflection->setParentCamera (mCamera); mReflection->setHeight(mTop); - mWater->setRenderQueueGroup(RQG_Water); } - else - mWater->setRenderQueueGroup(RQG_Alpha); - + mWater->setRenderQueueGroup(RQG_Alpha); delete mRefraction; mRefraction = NULL; From 5cc8af0f14ff975899f2bfbc4e5801311e9191db Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Feb 2013 20:06:03 +0100 Subject: [PATCH 021/151] fix map positions --- apps/openmw/mwgui/loadingscreen.cpp | 2 +- apps/openmw/mwrender/localmap.cpp | 27 +++++++++++++++------------ apps/openmw/mwrender/localmap.hpp | 8 ++++++++ apps/openmw/mwrender/water.cpp | 2 +- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 8fecf4c34..dd5289edb 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -150,7 +150,7 @@ namespace MWGui if (!mFirstLoad) { mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName()); - //mRectangle->setVisible(true); + mRectangle->setVisible(true); } for (unsigned int i = 0; igetNumCompositors(); ++i) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 1d338df12..3a906138b 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -187,15 +187,6 @@ void LocalMap::render(const float x, const float y, const float zlow, const float zhigh, const float xw, const float yw, const std::string& texture) { - // disable fog (only necessary for fixed function, the shader based - // materials already do this through local_map material configuration) - const float fStart = mRendering->getScene()->getFogStart(); - const float fEnd = mRendering->getScene()->getFogEnd(); - const ColourValue& clr = mRendering->getScene()->getFogColour(); - mRendering->getScene()->setFog(FOG_NONE); - - // make everything visible - mCameraNode->setPosition(Vector3(x, zhigh+100000, y)); //mCellCamera->setFarClipDistance( (zhigh-zlow) * 1.1 ); mCellCamera->setFarClipDistance(0); // infinite @@ -224,6 +215,9 @@ void LocalMap::render(const float x, const float y, TU_RENDERTARGET); RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); + + mCameraSettings[rtt] = Vector3(x, zhigh+100000, y); + rtt->setAutoUpdated(false); Viewport* vp = rtt->addViewport(mCellCamera); vp->setOverlaysEnabled(false); @@ -266,13 +260,19 @@ void LocalMap::render(const float x, const float y, //rtt->writeContentsToFile("./" + texture + ".jpg"); } } - - // re-enable fog - mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd); } void LocalMap::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { + // disable fog (only necessary for fixed function, the shader based + // materials already do this through local_map material configuration) + mOldFogStart = mRendering->getScene()->getFogStart(); + mOldFogEnd = mRendering->getScene()->getFogEnd(); + mOldFogClr = mRendering->getScene()->getFogColour(); + mRendering->getScene()->setFog(FOG_NONE); + + mCellCamera->setPosition(mCameraSettings[evt.source]); + mRenderingManager->disableLights(true); mLight->setVisible(true); evt.source->setAutoUpdated(false); @@ -283,6 +283,9 @@ void LocalMap::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) mRenderingManager->enableLights(true); mLight->setVisible(false); evt.source->removeListener(this); + + // re-enable fog + mRendering->getScene()->setFog(FOG_LINEAR, mOldFogClr, 0, mOldFogStart, mOldFogEnd); } void LocalMap::getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 2b1aa3f62..1f528f138 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -4,6 +4,7 @@ #include #include +#include #include namespace MWWorld @@ -120,6 +121,13 @@ namespace MWRender int mCellX, mCellY; Ogre::AxisAlignedBox mBounds; std::string mInteriorName; + + Ogre::ColourValue mOldFogClr; + float mOldFogStart; + float mOldFogEnd; + + // maps texture name to according camera settings + std::map mCameraSettings; }; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 0eb35323d..f2854c879 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -401,7 +401,7 @@ void Water::update(float dt, Ogre::Vector3 player) mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); - //if (player.y <= mTop) + if (player.y <= mTop) { mSimulation->addImpulse(Ogre::Vector2(player.x, player.z)); } From fa07288b151d8c6addd9d42177737f29f9b82d78 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Feb 2013 20:29:50 +0100 Subject: [PATCH 022/151] tweaked map light color --- apps/openmw/mwrender/localmap.cpp | 4 ++++ apps/openmw/mwrender/localmap.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 3a906138b..ccad0a5e8 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -271,6 +271,9 @@ void LocalMap::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) mOldFogClr = mRendering->getScene()->getFogColour(); mRendering->getScene()->setFog(FOG_NONE); + mOldAmbient = mRendering->getScene()->getAmbientLight(); + mRendering->getScene()->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3)); + mCellCamera->setPosition(mCameraSettings[evt.source]); mRenderingManager->disableLights(true); @@ -286,6 +289,7 @@ void LocalMap::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) // re-enable fog mRendering->getScene()->setFog(FOG_LINEAR, mOldFogClr, 0, mOldFogStart, mOldFogEnd); + mRendering->getScene()->setAmbientLight(mOldAmbient); } void LocalMap::getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 1f528f138..afdf4b6e5 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -123,6 +123,7 @@ namespace MWRender std::string mInteriorName; Ogre::ColourValue mOldFogClr; + Ogre::ColourValue mOldAmbient; float mOldFogStart; float mOldFogEnd; From a29919d02dd08a58114c22750bc49185e7fe704a Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Feb 2013 00:39:56 +0100 Subject: [PATCH 023/151] restored global map --- apps/openmw/mwrender/localmap.cpp | 47 +++++++++++-------------------- apps/openmw/mwrender/localmap.hpp | 11 +------- 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index ccad0a5e8..e0b7d9a11 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -191,6 +191,20 @@ void LocalMap::render(const float x, const float y, mCellCamera->setFarClipDistance(0); // infinite mCellCamera->setOrthoWindow(xw, yw); + mCellCamera->setPosition(Vector3(x, zhigh+100000, y)); + + // disable fog (only necessary for fixed function, the shader based + // materials already do this through local_map material configuration) + float oldFogStart = mRendering->getScene()->getFogStart(); + float oldFogEnd = mRendering->getScene()->getFogEnd(); + Ogre::ColourValue oldFogColour = mRendering->getScene()->getFogColour(); + mRendering->getScene()->setFog(FOG_NONE); + + // set up lighting + Ogre::ColourValue oldAmbient = mRendering->getScene()->getAmbientLight(); + mRendering->getScene()->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3)); + mRenderingManager->disableLights(true); + mLight->setVisible(true); TexturePtr tex; // try loading from memory @@ -216,8 +230,6 @@ void LocalMap::render(const float x, const float y, RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); - mCameraSettings[rtt] = Vector3(x, zhigh+100000, y); - rtt->setAutoUpdated(false); Viewport* vp = rtt->addViewport(mCellCamera); vp->setOverlaysEnabled(false); @@ -228,8 +240,7 @@ void LocalMap::render(const float x, const float y, // use fallback techniques without shadows and without mrt vp->setMaterialScheme("local_map"); - rtt->setAutoUpdated(true); - rtt->addListener(this); + rtt->update(); // create "fog of war" texture TexturePtr tex2 = TextureManager::getSingleton().createManual( @@ -260,36 +271,12 @@ void LocalMap::render(const float x, const float y, //rtt->writeContentsToFile("./" + texture + ".jpg"); } } -} - -void LocalMap::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) -{ - // disable fog (only necessary for fixed function, the shader based - // materials already do this through local_map material configuration) - mOldFogStart = mRendering->getScene()->getFogStart(); - mOldFogEnd = mRendering->getScene()->getFogEnd(); - mOldFogClr = mRendering->getScene()->getFogColour(); - mRendering->getScene()->setFog(FOG_NONE); - - mOldAmbient = mRendering->getScene()->getAmbientLight(); - mRendering->getScene()->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3)); - - mCellCamera->setPosition(mCameraSettings[evt.source]); - - mRenderingManager->disableLights(true); - mLight->setVisible(true); - evt.source->setAutoUpdated(false); -} - -void LocalMap::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) -{ mRenderingManager->enableLights(true); mLight->setVisible(false); - evt.source->removeListener(this); // re-enable fog - mRendering->getScene()->setFog(FOG_LINEAR, mOldFogClr, 0, mOldFogStart, mOldFogEnd); - mRendering->getScene()->setAmbientLight(mOldAmbient); + mRendering->getScene()->setFog(FOG_LINEAR, oldFogColour, 0, oldFogStart, oldFogEnd); + mRendering->getScene()->setAmbientLight(oldAmbient); } void LocalMap::getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index afdf4b6e5..9c82258f9 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -5,7 +5,6 @@ #include #include -#include namespace MWWorld { @@ -19,7 +18,7 @@ namespace MWRender /// /// \brief Local map rendering /// - class LocalMap : public Ogre::RenderTargetListener + class LocalMap { public: LocalMap(OEngine::Render::OgreRenderer*, MWRender::RenderingManager* rendering); @@ -71,9 +70,6 @@ namespace MWRender */ bool isPositionExplored (float nX, float nY, int x, int y, bool interior); - void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - private: OEngine::Render::OgreRenderer* mRendering; MWRender::RenderingManager* mRenderingManager; @@ -122,11 +118,6 @@ namespace MWRender Ogre::AxisAlignedBox mBounds; std::string mInteriorName; - Ogre::ColourValue mOldFogClr; - Ogre::ColourValue mOldAmbient; - float mOldFogStart; - float mOldFogEnd; - // maps texture name to according camera settings std::map mCameraSettings; }; From 3772cd9257cf127fdbb476d169e831536852572a Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Feb 2013 14:29:46 +0100 Subject: [PATCH 024/151] Refraction can be disabled separately now --- apps/openmw/mwgui/settingswindow.cpp | 6 ++++ apps/openmw/mwgui/settingswindow.hpp | 1 + apps/openmw/mwrender/renderingmanager.cpp | 22 +++++++++----- apps/openmw/mwrender/water.cpp | 10 ++++-- files/materials/core.h | 6 ---- files/materials/objects.shader | 11 ++----- files/materials/terrain.shader | 16 ++++------ files/materials/water.mat | 3 ++ files/materials/water.shader | 37 ++++++++++++++--------- files/mygui/openmw_settings_window.layout | 7 +++++ files/settings-default.cfg | 6 ++-- 11 files changed, 72 insertions(+), 53 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index c5c6eada2..343c96cec 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -123,6 +123,7 @@ namespace MWGui getWidget(mInvertYButton, "InvertYButton"); getWidget(mUISensitivitySlider, "UISensitivitySlider"); getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider"); + getWidget(mRefractionButton, "RefractionButton"); mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -133,6 +134,7 @@ namespace MWGui mShaderModeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShaderModeToggled); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mRefractionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mReflectTerrainButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mReflectActorsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -248,6 +250,8 @@ namespace MWGui mShadersButton->setCaption (Settings::Manager::getBool("shaders", "Objects") ? "on" : "off"); mShaderModeButton->setCaption (Settings::Manager::getString("shader mode", "General")); + mRefractionButton->setCaption (Settings::Manager::getBool("refraction", "Water") ? "on" : "off"); + if (!MWRender::RenderingManager::waterShaderSupported()) { mWaterShaderButton->setEnabled(false); @@ -376,6 +380,8 @@ namespace MWGui { if (_sender == mWaterShaderButton) Settings::Manager::setBool("shader", "Water", newState); + else if (_sender == mRefractionButton) + Settings::Manager::setBool("refraction", "Water", newState); else if (_sender == mUnderwaterButton) { Settings::Manager::setBool("underwater effect", "Water", newState); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 8ca3ad758..55cc0a870 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -51,6 +51,7 @@ namespace MWGui MyGUI::Button* mShadersButton; MyGUI::Button* mShaderModeButton; MyGUI::Button* mUnderwaterButton; + MyGUI::Button* mRefractionButton; MyGUI::Button* mShadowsEnabledButton; MyGUI::Button* mShadowsLargeDistance; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index aa73bc49b..69f3914e5 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -135,8 +135,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(0))); sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty(new sh::Vector3(0.5, -0.8, 0.2))); sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(1, 0.6))); - sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty(new sh::FloatValue( - 1.f))); + sh::Factory::getInstance ().setGlobalSetting ("refraction", Settings::Manager::getBool("refraction", "Water") ? "true" : "false"); applyCompositors(); @@ -757,6 +756,7 @@ Compositors* RenderingManager::getCompositors() void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) { bool changeRes = false; + bool rebuild = false; // rebuild static geometry (necessary after any material changes) for (Settings::CategorySettingVector::const_iterator it=settings.begin(); it != settings.end(); ++it) { @@ -794,18 +794,23 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec applyCompositors(); sh::Factory::getInstance ().setGlobalSetting ("mrt_output", useMRT() ? "true" : "false"); sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true"); - mObjects.rebuildStaticGeometry (); + rebuild = true; mRendering.getViewport ()->setClearEveryFrame (true); } + else if (it->second == "refraction" && it->first == "Water") + { + sh::Factory::getInstance ().setGlobalSetting ("refraction", Settings::Manager::getBool("refraction", "Water") ? "true" : "false"); + rebuild = true; + } else if (it->second == "underwater effect" && it->first == "Water") { sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water")); - mObjects.rebuildStaticGeometry (); + rebuild = true; } else if (it->second == "shaders" && it->first == "Objects") { sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); - mObjects.rebuildStaticGeometry (); + rebuild = true; } else if (it->second == "shader mode" && it->first == "General") { @@ -818,13 +823,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec else lang = sh::Language_CG; sh::Factory::getInstance ().setCurrentLanguage (lang); - mObjects.rebuildStaticGeometry (); + rebuild = true; } else if (it->first == "Shadows") { mShadows->recreate (); - mObjects.rebuildStaticGeometry (); + rebuild = true; } } @@ -842,6 +847,9 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec if (mWater) mWater->processChangedSettings(settings); + + if (rebuild) + mObjects.rebuildStaticGeometry(); } void RenderingManager::setMenuTransparency(float val) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index f2854c879..433aa8af8 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -430,8 +430,11 @@ void Water::applyRTT() delete mRefraction; mRefraction = NULL; - mRefraction = new Refraction(mCamera); - mRefraction->setHeight(mTop); + if (Settings::Manager::getBool("refraction", "Water")) + { + mRefraction = new Refraction(mCamera); + mRefraction->setHeight(mTop); + } } void Water::applyVisibilityMask() @@ -455,7 +458,8 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin it != settings.end(); ++it) { if ( it->first == "Water" && ( - it->second == "shader" + it->second == "shader" + || it->second == "refraction" || it->second == "rtt size")) applyRT = true; diff --git a/files/materials/core.h b/files/materials/core.h index e498a3809..3385e5fac 100644 --- a/files/materials/core.h +++ b/files/materials/core.h @@ -1,9 +1,3 @@ -//#define gammaCorrectRead(v) pow(max(v, 0.00001f), float3(gammaCorrection,gammaCorrection,gammaCorrection)) -//#define gammaCorrectOutput(v) pow(max(v, 0.00001f), float3(1.f/gammaCorrection,1.f/gammaCorrection,1.f/gammaCorrection)) - -#define gammaCorrectRead(v) v -#define gammaCorrectOutput(v) v - #if SH_HLSL == 1 || SH_CG == 1 #define shTexture2D sampler2D diff --git a/files/materials/objects.shader b/files/materials/objects.shader index c68705c42..1e9c4a334 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -112,8 +112,6 @@ shUniform(float, far) @shAutoConstant(far, far_clip_distance) #endif - //shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) - #if LIGHTING shInput(float3, normalPassthrough) shInput(float3, objSpacePositionPassthrough) @@ -180,7 +178,6 @@ SH_START_PROGRAM { shOutputColour(0) = shSample(diffuseMap, UV); - shOutputColour(0).xyz = gammaCorrectRead(shOutputColour(0).xyz); #if LIGHTING float3 normal = normalize(normalPassthrough); @@ -271,7 +268,7 @@ // regular fog only if fragment is above water if (worldPos.y > waterLevel || waterEnabled != 1.f) #endif - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); #endif // prevent negative colour output (for example with negative lights) @@ -286,11 +283,11 @@ float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85)) *waterSunGradient * 0.5; + float3 waterSunColour = float3(0.0,1.0,0.85) *waterSunGradient * 0.5; float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = ( gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0; + float3 watercolour = ( float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; @@ -303,8 +300,6 @@ shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater * waterEnabled); #endif - shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); - #if MRT shOutputColour(1) = float4(depthPassthrough / far,1,1,1); #endif diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index dfe998210..9b891e1e8 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -137,8 +137,6 @@ shSampler2D(normalMap) // global normal map - //shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) - @shForeach(@shPropertyString(num_blendmaps)) shSampler2D(blendMap@shIterator) @@ -254,9 +252,9 @@ #if IS_FIRST_PASS == 1 && @shIterator == 0 // first layer of first pass doesn't need a blend map - albedo = gammaCorrectRead(shSample(diffuseMap0, UV * 10).rgb); + albedo = shSample(diffuseMap0, UV * 10).rgb; #else - albedo = shLerp(albedo, gammaCorrectRead(shSample(diffuseMap@shIterator, UV * 10).rgb), blendValues@shPropertyString(blendmap_component_@shIterator)); + albedo = shLerp(albedo, shSample(diffuseMap@shIterator, UV * 10).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); #endif @shEndForeach @@ -343,7 +341,7 @@ // regular fog only if fragment is above water if (worldPos.y > waterLevel) #endif - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); #endif // prevent negative colour output (for example with negative lights) @@ -358,12 +356,12 @@ float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85))*waterSunGradient * 0.5; + float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0; - float3 waterext = gammaCorrectRead(float3(0.6, 0.9, 1.0));//water extinction + float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; + float3 waterext = float3(0.6, 0.9, 1.0);//water extinction watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; @@ -376,8 +374,6 @@ shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); #endif - shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); - #if MRT shOutputColour(1) = float4(depth / far,1,1,1); #endif diff --git a/files/materials/water.mat b/files/materials/water.mat index 2717f26fc..7546606fc 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -11,6 +11,9 @@ material Water fragment_program water_fragment cull_hardware none + + scene_blend alpha_blend + depth_write off texture_unit reflectionMap { diff --git a/files/materials/water.shader b/files/materials/water.shader index dbe36a91c..b02b4761c 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -62,6 +62,7 @@ // Inspired by Blender GLSL Water by martinsh ( http://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html ) #define RIPPLES 1 +#define REFRACTION @shGlobalSettingBool(refraction) #ifdef SH_VERTEX_SHADER @@ -123,9 +124,9 @@ #define REFR_BUMP 0.12 // refraction distortion amount #define SCATTER_AMOUNT 3.0 // amount of sunlight scattering - #define SCATTER_COLOUR gammaCorrectRead(float3(0.0,1.0,0.95)) // colour of sunlight scattering + #define SCATTER_COLOUR float3(0.0,1.0,0.95) // colour of sunlight scattering - #define SUN_EXT gammaCorrectRead(float3(0.45, 0.55, 0.68)) //sunlight extinction + #define SUN_EXT float3(0.45, 0.55, 0.68) //sunlight extinction #define SPEC_HARDNESS 256 // specular highlights hardness @@ -168,7 +169,9 @@ shUniform(float, far) @shAutoConstant(far, far_clip_distance) shSampler2D(reflectionMap) +#if REFRACTION shSampler2D(refractionMap) +#endif shSampler2D(depthMap) shSampler2D(normalMap) @@ -186,9 +189,6 @@ shUniform(float4, sunPosition) @shAutoConstant(sunPosition, light_position, 0) shUniform(float4, sunSpecular) @shAutoConstant(sunSpecular, light_specular_colour, 0) - - shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) - shUniform(float, renderTargetFlipping) @shAutoConstant(renderTargetFlipping, render_target_flipping) @@ -255,7 +255,7 @@ float s = shSaturate(dot(lR, vVec)*2.0-1.2); float lightScatter = shSaturate(dot(-lVec,lNormal)*0.7+0.3) * s * SCATTER_AMOUNT * waterSunFade_sunHeight.x * shSaturate(1.0-exp(-waterSunFade_sunHeight.y)); - float3 scatterColour = shLerp(float3(SCATTER_COLOUR)*gammaCorrectRead(float3(1.0,0.4,0.0)), SCATTER_COLOUR, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); + float3 scatterColour = shLerp(float3(SCATTER_COLOUR)*float3(1.0,0.4,0.0), SCATTER_COLOUR, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); // fresnel float ior = (cameraPos.y>0)?(1.333/1.0):(1.0/1.333); //air to water; water to air @@ -264,32 +264,36 @@ fresnel = shSaturate(fresnel); // reflection - float3 reflection = gammaCorrectRead(shSample(reflectionMap, screenCoords+(normal.xz*REFL_BUMP)).rgb); + float3 reflection = shSample(reflectionMap, screenCoords+(normal.xz*REFL_BUMP)).rgb; // refraction float3 R = reflect(vVec, normal); - float3 refraction = gammaCorrectRead(shSample(refractionMap, (screenCoords-(normal.xz*REFR_BUMP))*1.0).rgb); +#if REFRACTION + float3 refraction = shSample(refractionMap, (screenCoords-(normal.xz*REFR_BUMP))*1.0).rgb; // brighten up the refraction underwater refraction = (cameraPos.y < 0) ? shSaturate(refraction * 1.5) : refraction; - +#endif // specular float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS); +#if REFRACTION shOutputColour(0).xyz = shLerp( shLerp(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpecular.xyz; - +#else + shOutputColour(0).xyz = reflection + specular * sunSpecular.xyz; +#endif // fog if (isUnderwater == 1) { float waterSunGradient = dot(-vVec, -lVec); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85))*waterSunGradient * 0.5; + float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; float waterGradient = dot(-vVec, float3(0.0,-1.0,0.0)); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0; - float3 waterext = gammaCorrectRead(float3(0.6, 0.9, 1.0));//water extinction + float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; + float3 waterext = float3(0.6, 0.9, 1.0);//water extinction watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); float darkness = VISIBILITY*2.0; @@ -302,11 +306,14 @@ else { float fogValue = shSaturate((length(cameraPos.xyz-position.xyz) - fogParams.y) * fogParams.w); - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColor), fogValue); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); } - shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); +#if REFRACTION shOutputColour(0).w = 1; +#else + shOutputColour(0).w = shSaturate(fresnel + specular); +#endif } #endif diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index f03305ae7..5b7f106f3 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -285,6 +285,13 @@
+ + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 31aa60c42..044cc3406 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -127,11 +127,10 @@ fog end factor = 1.0 num lights = 8 [Water] -# Enable this to get fancy-looking water with reflections and refractions -# Only available if object shaders are on -# All the settings below have no effect if this is false shader = false +refraction = false + rtt size = 512 reflect terrain = true reflect statics = false @@ -139,7 +138,6 @@ reflect small statics = false reflect actors = false reflect misc = false -# Enable underwater effect. It is not resource intensive, so only disable it if you have problems. underwater effect = false [Sound] From 499f3ac0d18165cdf0079fa5c711aa390993fd42 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Feb 2013 16:40:41 +0100 Subject: [PATCH 025/151] Slightly better ripple normal blending. Not physically accurate at all, but looks good. --- apps/openmw/mwrender/ripplesimulation.cpp | 10 +++++++--- apps/openmw/mwrender/ripplesimulation.hpp | 2 ++ apps/openmw/mwrender/water.cpp | 3 ++- files/materials/water.shader | 7 ++++--- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index 043757e88..249397005 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -20,7 +20,8 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) mTextureSize(512), mRippleAreaLength(1000), mImpulseSize(20), - mTexelOffset(0,0) + mTexelOffset(0,0), + mFirstUpdate(true) { Ogre::AxisAlignedBox aabInf; aabInf.setInfinite(); @@ -106,7 +107,7 @@ void RippleSimulation::update(float dt, Ogre::Vector2 position) // try to keep 20 fps mTime += dt; - while (mTime >= 1/20.0) + while (mTime >= 1/20.0 || mFirstUpdate) { mPreviousFrameOffset = mCurrentFrameOffset; @@ -130,7 +131,10 @@ void RippleSimulation::update(float dt, Ogre::Vector2 position) heightMapToNormalMap(); swapHeightMaps(); - mTime -= 1/20.0; + if (!mFirstUpdate) + mTime -= 1/20.0; + else + mFirstUpdate = false; } sh::Factory::getInstance().setSharedParameter("rippleCenter", sh::makeProperty( diff --git a/apps/openmw/mwrender/ripplesimulation.hpp b/apps/openmw/mwrender/ripplesimulation.hpp index 72ff3dbd8..c792a3214 100644 --- a/apps/openmw/mwrender/ripplesimulation.hpp +++ b/apps/openmw/mwrender/ripplesimulation.hpp @@ -34,6 +34,8 @@ private: float mRippleAreaLength; float mImpulseSize; + bool mFirstUpdate; + Ogre::Camera* mCamera; // own scenemanager to render our simulation diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 433aa8af8..4ff8945ac 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -401,7 +401,8 @@ void Water::update(float dt, Ogre::Vector3 player) mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); - if (player.y <= mTop) + /// \todo player.y is the scene node position (which is above the head) and not the feet position + //if (player.y <= mTop) { mSimulation->addImpulse(Ogre::Vector2(player.x, player.z)); } diff --git a/files/materials/water.shader b/files/materials/water.shader index b02b4761c..400fbefb2 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -120,8 +120,8 @@ #define WAVE_SCALE 75 // overall wave scale #define BUMP 1.5 // overall water surface bumpiness - #define REFL_BUMP 0.16 // reflection distortion amount - #define REFR_BUMP 0.12 // refraction distortion amount + #define REFL_BUMP 0.08 // reflection distortion amount + #define REFR_BUMP 0.06 // refraction distortion amount #define SCATTER_AMOUNT 3.0 // amount of sunlight scattering #define SCATTER_COLOUR float3(0.0,1.0,0.95) // colour of sunlight scattering @@ -232,7 +232,8 @@ float3 normal_ripple = normalize(shSample(rippleNormalMap, relPos.xy).xyz * 2 - 1); normal_ripple = normal_ripple.xzy; - normal = normalize(normal + normal_ripple); + //normal = normalize(normal + normal_ripple); + normal = normalize(float3(normal.x + normal_ripple.x, normal.y, normal.z + normal_ripple.z)); // normal for sunlight scattering From c4d518132f83cb0697361fa98e69e3b1bd6a8b88 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Feb 2013 19:22:08 +0100 Subject: [PATCH 026/151] With the 1x1 background window trick, we can apply VSync without restart. Some issues left though. --- apps/openmw/mwbase/inputmanager.hpp | 3 +++ apps/openmw/mwgui/settingswindow.cpp | 8 ++----- apps/openmw/mwinput/inputmanagerimp.cpp | 28 ++++++++++++++++++---- apps/openmw/mwinput/inputmanagerimp.hpp | 8 +++++++ apps/openmw/mwrender/renderingmanager.cpp | 29 ++++++++++++++++++++++- apps/openmw/mwrender/renderingmanager.hpp | 2 ++ libs/openengine/ogre/renderer.cpp | 25 +++++++++++++++---- libs/openengine/ogre/renderer.hpp | 3 +++ 8 files changed, 90 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwbase/inputmanager.hpp b/apps/openmw/mwbase/inputmanager.hpp index 8293cbfa7..f69e1a152 100644 --- a/apps/openmw/mwbase/inputmanager.hpp +++ b/apps/openmw/mwbase/inputmanager.hpp @@ -39,6 +39,9 @@ namespace MWBase virtual int getNumActions() = 0; virtual void enableDetectingBindingMode (int action) = 0; virtual void resetToDefaultBindings() = 0; + + virtual void create () = 0; + virtual void destroy () = 0; }; } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 343c96cec..75fc2b7a2 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -370,14 +370,10 @@ namespace MWGui apply(); } } - else if (_sender == mVSyncButton) - { - Settings::Manager::setBool("vsync", "Video", newState); - MWBase::Environment::get().getWindowManager()-> - messageBox("VSync will be applied after a restart", std::vector()); - } else { + if (_sender == mVSyncButton) + Settings::Manager::setBool("vsync", "Video", newState); if (_sender == mWaterShaderButton) Settings::Manager::setBool("shader", "Water", newState); else if (_sender == mRefractionButton) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 1f270df8b..95d221933 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -41,9 +41,11 @@ namespace MWInput , mMouseX(ogre.getWindow()->getWidth ()/2.f) , mMouseY(ogre.getWindow()->getHeight ()/2.f) , mMouseWheel(0) - , mUserFile(userFile) , mDragDrop(false) , mGuiCursorEnabled(false) + , mDebug(debug) + , mUserFile(userFile) + , mUserFileExists(userFileExists) , mInvertY (Settings::Manager::getBool("invert y axis", "Input")) , mCameraSensitivity (Settings::Manager::getFloat("camera sensitivity", "Input")) , mUISensitivity (Settings::Manager::getFloat("ui sensitivity", "Input")) @@ -51,8 +53,15 @@ namespace MWInput , mUIYMultiplier (Settings::Manager::getFloat("ui y multiplier", "Input")) , mPreviewPOVDelay(0.f) , mTimeIdle(0.f) + , mCreated(false) { - Ogre::RenderWindow* window = ogre.getWindow (); + create(); + } + + + void InputManager::create() + { + Ogre::RenderWindow* window = mOgre.getWindow (); size_t windowHnd; resetIdleTime(); @@ -67,7 +76,7 @@ namespace MWInput // Set non-exclusive mouse and keyboard input if the user requested // it. - if (debug) + if (mDebug) { #if defined OIS_WIN32_PLATFORM pl.insert(std::make_pair(std::string("w32_mouse"), @@ -112,7 +121,7 @@ namespace MWInput MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, mMouse->getMouseState ().Z.abs); - std::string file = userFileExists ? userFile : ""; + std::string file = mUserFileExists ? mUserFile : ""; mInputCtrl = new ICS::InputControlSystem(file, true, this, NULL, A_Last); loadKeyDefaults(); @@ -131,9 +140,11 @@ namespace MWInput mControlSwitch["vanitymode"] = true; changeInputMode(false); + + mCreated = true; } - InputManager::~InputManager() + void InputManager::destroy() { mInputCtrl->save (mUserFile); @@ -142,6 +153,12 @@ namespace MWInput mInputManager->destroyInputObject(mKeyboard); mInputManager->destroyInputObject(mMouse); OIS::InputManager::destroyInputSystem(mInputManager); + mCreated = false; + } + + InputManager::~InputManager() + { + destroy(); } void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue) @@ -239,6 +256,7 @@ namespace MWInput void InputManager::update(float dt, bool loading) { + if (!mCreated) return; // Tell OIS to handle all input events mKeyboard->capture(); mMouse->capture(); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 9deed1f28..100bba4fb 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -131,6 +131,8 @@ namespace MWInput std::string mUserFile; + bool mCreated; + bool mDragDrop; bool mInvertY; @@ -148,9 +150,15 @@ namespace MWInput float mMouseX; float mMouseY; int mMouseWheel; + bool mDebug; + bool mUserFileExists; std::map mControlSwitch; + public: + virtual void create(); + virtual void destroy(); + private: void adjustMouseRegion(int width, int height); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 69f3914e5..9e50b2bce 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -46,7 +46,8 @@ namespace MWRender { RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine) - : mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine) + : mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine), + mRecreateWindowInNextFrame(false) { // select best shader mode bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos); @@ -323,6 +324,22 @@ RenderingManager::moveObjectToCell( void RenderingManager::update (float duration, bool paused) { + if (mRecreateWindowInNextFrame) + { + MWBase::Environment::get().getInputManager()->destroy(); + + OEngine::Render::WindowSettings windowSettings; + windowSettings.fullscreen = Settings::Manager::getBool("fullscreen", "Video"); + windowSettings.window_x = Settings::Manager::getInt("resolution x", "Video"); + windowSettings.window_y = Settings::Manager::getInt("resolution y", "Video"); + windowSettings.vsync = Settings::Manager::getBool("vsync", "Video"); + std::string aa = Settings::Manager::getString("antialiasing", "Video"); + windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0"; + mRendering.recreateWindow("OpenMW", windowSettings); + + MWBase::Environment::get().getInputManager()->create(); + mRecreateWindowInNextFrame = false; + } Ogre::Vector3 orig, dest; mPlayer->setCameraDistance(); if (!mPlayer->getPosition(orig, dest)) { @@ -756,6 +773,7 @@ Compositors* RenderingManager::getCompositors() void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) { bool changeRes = false; + bool recreateWindow = false; bool rebuild = false; // rebuild static geometry (necessary after any material changes) for (Settings::CategorySettingVector::const_iterator it=settings.begin(); it != settings.end(); ++it) @@ -774,6 +792,8 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec || it->second == "resolution y" || it->second == "fullscreen")) changeRes = true; + else if (it->first == "Video" && it->second == "vsync") + recreateWindow = true; else if (it->second == "field of view" && it->first == "General") mRendering.setFov(Settings::Manager::getFloat("field of view", "General")); else if ((it->second == "texture filtering" && it->first == "General") @@ -845,6 +865,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } + if (recreateWindow) + { + mRecreateWindowInNextFrame = true; + // We can not do this now, because this might get triggered from the input listener + // and destroying/recreating the input system at that point would cause a crash + } + if (mWater) mWater->processChangedSettings(settings); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 71ac742c2..670f3dc85 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -260,6 +260,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList MWRender::Compositors* mCompositors; VideoPlayer* mVideoPlayer; + + bool mRecreateWindowInNextFrame; }; } diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 039aba226..e0abf420e 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -205,13 +205,31 @@ void OgreRenderer::configure(const std::string &logPath, rs->setConfigOption ("RTT Preferred Mode", rttMode); } +void OgreRenderer::recreateWindow(const std::string &title, const WindowSettings &settings) +{ + Ogre::ColourValue viewportBG = mView->getBackgroundColour(); + + mRoot->destroyRenderTarget(mWindow); + NameValuePairList params; + params.insert(std::make_pair("title", title)); + params.insert(std::make_pair("FSAA", settings.fsaa)); + params.insert(std::make_pair("vsync", settings.vsync ? "true" : "false")); + + mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms); + + // Create one viewport, entire window + mView = mWindow->addViewport(mCamera); + mView->setBackgroundColour(viewportBG); + + adjustViewport(); +} + void OgreRenderer::createWindow(const std::string &title, const WindowSettings& settings) { 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")); @@ -219,7 +237,6 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& 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)); @@ -271,12 +288,12 @@ void OgreRenderer::adjustViewport() void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) { - Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); + //Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); } void OgreRenderer::removeWindowEventListener(Ogre::WindowEventListener* listener) { - Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, listener); + //Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, listener); } void OgreRenderer::setFov(float fov) diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index a8788dfca..251dc9c54 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -66,6 +66,7 @@ namespace OEngine #endif class Fader; + class OgreRenderer { #if defined(__APPLE__) && !defined(__LP64__) @@ -138,6 +139,8 @@ namespace OEngine /// Create a window with the given title void createWindow(const std::string &title, const WindowSettings& settings); + void recreateWindow (const std::string &title, const WindowSettings& settings); + /// Set up the scene manager, camera and viewport void createScene(const std::string& camName="Camera",// Camera name float fov=55, // Field of view angle From 31f760cccec9a1bab571181e38699f8357b8b285 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Feb 2013 20:26:13 +0100 Subject: [PATCH 027/151] Fixing issues from last commit: restored input and occlusion queries --- apps/openmw/mwinput/inputmanagerimp.cpp | 11 +++-------- apps/openmw/mwinput/inputmanagerimp.hpp | 2 -- apps/openmw/mwrender/occlusionquery.cpp | 13 ++++++++++++- apps/openmw/mwrender/occlusionquery.hpp | 1 - apps/openmw/mwrender/renderingmanager.cpp | 13 ++++++++++++- apps/openmw/mwrender/water.cpp | 2 +- libs/openengine/ogre/renderer.cpp | 4 ++-- 7 files changed, 30 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 95d221933..00849503c 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -53,9 +53,10 @@ namespace MWInput , mUIYMultiplier (Settings::Manager::getFloat("ui y multiplier", "Input")) , mPreviewPOVDelay(0.f) , mTimeIdle(0.f) - , mCreated(false) { create(); + + changeInputMode(false); } @@ -138,10 +139,6 @@ namespace MWInput mControlSwitch["playermagic"] = true; mControlSwitch["playerviewswitch"] = true; mControlSwitch["vanitymode"] = true; - - changeInputMode(false); - - mCreated = true; } void InputManager::destroy() @@ -153,7 +150,6 @@ namespace MWInput mInputManager->destroyInputObject(mKeyboard); mInputManager->destroyInputObject(mMouse); OIS::InputManager::destroyInputSystem(mInputManager); - mCreated = false; } InputManager::~InputManager() @@ -250,13 +246,12 @@ namespace MWInput case A_ToggleHUD: mWindows.toggleHud(); break; - } + } } } void InputManager::update(float dt, bool loading) { - if (!mCreated) return; // Tell OIS to handle all input events mKeyboard->capture(); mMouse->capture(); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 100bba4fb..7be35ee0b 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -131,8 +131,6 @@ namespace MWInput std::string mUserFile; - bool mCreated; - bool mDragDrop; bool mInvertY; diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index c9e649fe6..8d16d7b7d 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -15,7 +15,7 @@ using namespace Ogre; OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) : mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mSingleObjectQuery(0), mActiveQuery(0), mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false), - mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mDoQuery2(false), + mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mBBNode(0), mActive(false) { mRendering = renderer; @@ -94,6 +94,9 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod OcclusionQuery::~OcclusionQuery() { + mRendering->getScene()->removeRenderObjectListener (this); + mRendering->getScene()->removeRenderQueueListener(this); + RenderSystem* renderSystem = Root::getSingleton().getRenderSystem(); if (mSunTotalAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunTotalAreaQuery); if (mSunVisibleAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunVisibleAreaQuery); @@ -109,6 +112,7 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass const LightList* pLightList, bool suppressRenderStateChanges) { if (!mActive) return; + // The following code activates and deactivates the occlusion queries // so that the queries only include the rendering of the intended meshes @@ -116,6 +120,7 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass // Each occlusion query should only last a single rendering if (mActiveQuery != NULL) { + std::cout << "ending query (notifyRenderSingleObject)" << std::endl; mActiveQuery->endOcclusionQuery(); mActiveQuery = NULL; } @@ -123,6 +128,7 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass // Open a new occlusion query if (mDoQuery == true) { + std::cout << "opening new query" << std::endl; if (rend == mBBQueryTotal) { mActiveQuery = mSunTotalAreaQuery; @@ -208,6 +214,7 @@ void OcclusionQuery::update(float duration) && !mSunVisibleAreaQuery->isStillOutstanding() && !mSingleObjectQuery->isStillOutstanding()) { + std::cout << "update(), nothing is outstanding"<< std::endl; unsigned int totalPixels; unsigned int visiblePixels; @@ -243,6 +250,8 @@ void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::SceneNod assert( !occlusionTestPending() && "Occlusion test still pending"); + std::cout << "Occlusion test called " << std::endl; + mBBQuerySingleObject->setVisible(true); mObjectNode->setPosition(position); @@ -250,6 +259,8 @@ void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::SceneNod mObjectNode->setScale( Vector3(1,1,1)*(position - mRendering->getCamera()->getRealPosition()).length() ); mQuerySingleObjectRequested = true; + + mDoQuery = true; } bool OcclusionQuery::occlusionTestPending() diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index af6f668c1..c7a5757d3 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -95,7 +95,6 @@ namespace MWRender bool mSupported; bool mDoQuery; - bool mDoQuery2; bool mQuerySingleObjectRequested; bool mQuerySingleObjectStarted; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 9e50b2bce..afbdbb06f 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -326,6 +326,10 @@ void RenderingManager::update (float duration, bool paused) { if (mRecreateWindowInNextFrame) { + mRecreateWindowInNextFrame = false; + + mRendering.removeWindowEventListener(this); + mRendering.getWindow()->removeListener(this); MWBase::Environment::get().getInputManager()->destroy(); OEngine::Render::WindowSettings windowSettings; @@ -338,8 +342,15 @@ void RenderingManager::update (float duration, bool paused) mRendering.recreateWindow("OpenMW", windowSettings); MWBase::Environment::get().getInputManager()->create(); - mRecreateWindowInNextFrame = false; + mRendering.setWindowEventListener (this); + mRendering.getWindow()->addListener(this); + + // this is necessary, otherwise it would just endlessly wait for the last query and it would never return + delete mOcclusionQuery; + mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); } + + Ogre::Vector3 orig, dest; mPlayer->setCameraDistance(); if (!mPlayer->getPosition(orig, dest)) { diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 4ff8945ac..867829564 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -418,7 +418,7 @@ void Water::applyRTT() mReflection = NULL; // Create rendertarget for reflection - int rttsize = Settings::Manager::getInt("rtt size", "Water"); + //int rttsize = Settings::Manager::getInt("rtt size", "Water"); if (Settings::Manager::getBool("shader", "Water")) { diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index e0abf420e..c4f35e087 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -288,12 +288,12 @@ void OgreRenderer::adjustViewport() void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) { - //Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); + Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); } void OgreRenderer::removeWindowEventListener(Ogre::WindowEventListener* listener) { - //Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, listener); + Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, listener); } void OgreRenderer::setFov(float fov) From 608c112f34461760264240ded5f5140d2a24c7c2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Feb 2013 20:48:25 +0100 Subject: [PATCH 028/151] Supply the new render window to mygui --- apps/openmw/mwgui/loadingscreen.hpp | 2 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 15 ++++++++++++--- apps/openmw/mwgui/windowmanagerimp.hpp | 1 + apps/openmw/mwrender/occlusionquery.cpp | 5 ----- libs/openengine/gui/manager.cpp | 6 ++++++ libs/openengine/gui/manager.hpp | 2 ++ 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index c14087a3b..24b385071 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -19,6 +19,8 @@ namespace MWGui void onResChange(int w, int h); + void updateWindow(Ogre::RenderWindow* rw) { mWindow = rw; } + private: bool mFirstLoad; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index a1f915ac9..3ae0f37c5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -56,10 +56,11 @@ using namespace MWGui; WindowManager::WindowManager( - const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, + const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *ogre, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage) : mGuiManager(NULL) + , mRendering(ogre) , mHud(NULL) , mMap(NULL) , mMenu(NULL) @@ -111,7 +112,7 @@ WindowManager::WindowManager( { // Set up the GUI system - mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, logpath); + mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath); mGui = mGuiManager->getGui(); //Register own widgets with MyGUI @@ -172,7 +173,7 @@ WindowManager::WindowManager( mEnchantingDialog = new EnchantingDialog(*this); mTrainingWindow = new TrainingWindow(*this); - mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this); + mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this); mLoadingScreen->onResChange (w,h); mInputBlocker = mGui->createWidget("",0,0,w,h,MyGUI::Align::Default,"Windows",""); @@ -763,6 +764,7 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); bool changeRes = false; + bool windowRecreated = false; for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it) { @@ -772,6 +774,8 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector { changeRes = true; } + else if (it->first == "Video" && it->second == "vsync") + windowRecreated = true; else if (it->first == "HUD" && it->second == "crosshair") mCrosshairEnabled = Settings::Manager::getBool ("crosshair", "HUD"); else if (it->first == "GUI" && it->second == "subtitles") @@ -795,6 +799,11 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y)); mInputBlocker->setSize(MyGUI::IntSize(x,y)); } + if (windowRecreated) + { + mGuiManager->updateWindow (mRendering->getWindow ()); + mLoadingScreen->updateWindow (mRendering->getWindow ()); + } } void WindowManager::pushGuiMode(GuiMode mode) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 8bcb88e22..bae195669 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -229,6 +229,7 @@ namespace MWGui private: OEngine::GUI::MyGUIManager *mGuiManager; + OEngine::Render::OgreRenderer *mRendering; HUD *mHud; MapWindow *mMap; MainMenu *mMenu; diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 8d16d7b7d..81a3f4327 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -120,7 +120,6 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass // Each occlusion query should only last a single rendering if (mActiveQuery != NULL) { - std::cout << "ending query (notifyRenderSingleObject)" << std::endl; mActiveQuery->endOcclusionQuery(); mActiveQuery = NULL; } @@ -128,7 +127,6 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass // Open a new occlusion query if (mDoQuery == true) { - std::cout << "opening new query" << std::endl; if (rend == mBBQueryTotal) { mActiveQuery = mSunTotalAreaQuery; @@ -214,7 +212,6 @@ void OcclusionQuery::update(float duration) && !mSunVisibleAreaQuery->isStillOutstanding() && !mSingleObjectQuery->isStillOutstanding()) { - std::cout << "update(), nothing is outstanding"<< std::endl; unsigned int totalPixels; unsigned int visiblePixels; @@ -250,8 +247,6 @@ void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::SceneNod assert( !occlusionTestPending() && "Occlusion test still pending"); - std::cout << "Occlusion test called " << std::endl; - mBBQuerySingleObject->setVisible(true); mObjectNode->setPosition(position); diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index 925891e1b..9cc2bf381 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -56,6 +56,12 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool mGui->initialise("core.xml"); } +void MyGUIManager::updateWindow (Ogre::RenderWindow *wnd) +{ + mRenderManager->setRenderWindow (wnd); + mRenderManager->setActiveViewport(0); +} + void MyGUIManager::shutdown() { mGui->shutdown (); diff --git a/libs/openengine/gui/manager.hpp b/libs/openengine/gui/manager.hpp index c0f98da88..39948a829 100644 --- a/libs/openengine/gui/manager.hpp +++ b/libs/openengine/gui/manager.hpp @@ -38,6 +38,8 @@ namespace GUI shutdown(); } + void updateWindow (Ogre::RenderWindow* wnd); + void setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false, const std::string& logDir = std::string("")); void shutdown(); From 86d65519e370041b7b9422bb85a188eadba96c56 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Feb 2013 23:57:30 +0100 Subject: [PATCH 029/151] Settings window fix --- apps/openmw/mwgui/settingswindow.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 75fc2b7a2..eaea022c0 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -247,10 +247,10 @@ namespace MWGui mInvertYButton->setCaptionWithReplacing(Settings::Manager::getBool("invert y axis", "Input") ? "#{sOn}" : "#{sOff}"); - mShadersButton->setCaption (Settings::Manager::getBool("shaders", "Objects") ? "on" : "off"); + mShadersButton->setCaptionWithReplacing (Settings::Manager::getBool("shaders", "Objects") ? "#{sOn}" : "#{sOff}"); mShaderModeButton->setCaption (Settings::Manager::getString("shader mode", "General")); - mRefractionButton->setCaption (Settings::Manager::getBool("refraction", "Water") ? "on" : "off"); + mRefractionButton->setCaptionWithReplacing (Settings::Manager::getBool("refraction", "Water") ? "#{sOn}" : "#{sOff}"); if (!MWRender::RenderingManager::waterShaderSupported()) { @@ -434,14 +434,17 @@ namespace MWGui void SettingsWindow::onShadersToggled(MyGUI::Widget* _sender) { - std::string val = static_cast(_sender)->getCaption(); - if (val == "off") - val = "on"; - else - val = "off"; - static_cast(_sender)->setCaption (val); + std::string on = mWindowManager.getGameSettingString("sOn", "On"); + std::string off = mWindowManager.getGameSettingString("sOff", "On"); - if (val == "off") + std::string val = static_cast(_sender)->getCaption(); + if (val == off) + val = on; + else + val = off; + static_cast(_sender)->setCaptionWithReplacing (val); + + if (val == off) { Settings::Manager::setBool("shaders", "Objects", false); From e4ed397b2d35d77398a2d6596657b2a6eba67d74 Mon Sep 17 00:00:00 2001 From: Michal Sciubidlo Date: Sun, 10 Feb 2013 14:02:06 +0100 Subject: [PATCH 030/151] Merge plugins and masters list view in openDialog. Simplify datafilesmodel. --- components/fileorderlist/datafileslist.cpp | 68 +---------- components/fileorderlist/datafileslist.hpp | 2 - .../fileorderlist/model/datafilesmodel.cpp | 108 +++--------------- .../fileorderlist/model/datafilesmodel.hpp | 17 +-- 4 files changed, 28 insertions(+), 167 deletions(-) diff --git a/components/fileorderlist/datafileslist.cpp b/components/fileorderlist/datafileslist.cpp index d25060baa..80d58b35f 100644 --- a/components/fileorderlist/datafileslist.cpp +++ b/components/fileorderlist/datafileslist.cpp @@ -48,8 +48,7 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) : QWidget(parent) , mCfgMgr(cfg) { - // Models - mMastersModel = new DataFilesModel(this); + // Model mPluginsModel = new DataFilesModel(this); mPluginsProxyModel = new QSortFilterProxyModel(); @@ -78,29 +77,6 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) QCheckBox checkBox; unsigned int height = checkBox.sizeHint().height() + 4; - mMastersTable = new QTableView(this); - mMastersTable->setModel(mMastersModel); - mMastersTable->setObjectName("MastersTable"); - mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection); - mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mMastersTable->setAlternatingRowColors(true); - mMastersTable->horizontalHeader()->setStretchLastSection(true); - mMastersTable->horizontalHeader()->hide(); - - // Set the row height to the size of the checkboxes - mMastersTable->verticalHeader()->setDefaultSectionSize(height); - mMastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - mMastersTable->verticalHeader()->hide(); - mMastersTable->setColumnHidden(1, true); - mMastersTable->setColumnHidden(2, true); - mMastersTable->setColumnHidden(3, true); - mMastersTable->setColumnHidden(4, true); - mMastersTable->setColumnHidden(5, true); - mMastersTable->setColumnHidden(6, true); - mMastersTable->setColumnHidden(7, true); - mMastersTable->setColumnHidden(8, true); - mPluginsTable = new QTableView(this); mPluginsTable->setModel(mPluginsProxyModel); mPluginsTable->setObjectName("PluginsTable"); @@ -124,26 +100,14 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) mPluginsTable->setColumnHidden(7, true); mPluginsTable->setColumnHidden(8, true); - // Add both tables to a splitter - QSplitter *splitter = new QSplitter(this); - splitter->setOrientation(Qt::Horizontal); - splitter->addWidget(mMastersTable); - splitter->addWidget(mPluginsTable); - - // Adjust the default widget widths inside the splitter - QList sizeList; - sizeList << 175 << 200; - splitter->setSizes(sizeList); - QVBoxLayout *pageLayout = new QVBoxLayout(this); pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(splitter); + pageLayout->addWidget(mPluginsTable); connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - - connect(mMastersModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); + + connect(mPluginsModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); @@ -178,7 +142,6 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString { // Set the charset for reading the esm/esp files if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) { - mMastersModel->setEncoding(encoding); mPluginsModel->setEncoding(encoding); } @@ -186,11 +149,9 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { QString path = QString::fromStdString(it->string()); path.remove(QChar('\"')); - mMastersModel->addMasters(path); - mPluginsModel->addPlugins(path); + mPluginsModel->addFiles(path); } - mMastersModel->sort(0); mPluginsModel->sort(0); // mMastersTable->sortByColumn(3, Qt::AscendingOrder); // mPluginsTable->sortByColumn(3, Qt::AscendingOrder); @@ -200,11 +161,6 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString void DataFilesList::selectedFiles(std::vector& paths) { - QStringList masterPaths = mMastersModel->checkedItemsPaths(); - foreach (const QString &path, masterPaths) - { - paths.push_back(path.toStdString()); - } QStringList pluginPaths = mPluginsModel->checkedItemsPaths(); foreach (const QString &path, pluginPaths) { @@ -281,19 +237,12 @@ void DataFilesList::setCheckState(QModelIndex index) : mPluginsModel->setCheckState(sourceIndex, Qt::Checked); } - if (object->objectName() == QLatin1String("MastersTable")) { - (mMastersModel->checkState(index) == Qt::Checked) - ? mMastersModel->setCheckState(index, Qt::Unchecked) - : mMastersModel->setCheckState(index, Qt::Checked); - } - return; } void DataFilesList::uncheckAll() { - mMastersModel->uncheckAll(); mPluginsModel->uncheckAll(); } @@ -338,14 +287,9 @@ void DataFilesList::setCheckState(const QString& element, Qt::CheckState state) { mPluginsModel->setCheckState(mPluginsModel->indexFromItem(file), Qt::Checked); } - else - { - file = mMastersModel->findItem(element); - mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked); - } } QStringList DataFilesList::checkedFiles() { - return mMastersModel->checkedItems() + mPluginsModel->checkedItems(); + return mPluginsModel->checkedItems(); } \ No newline at end of file diff --git a/components/fileorderlist/datafileslist.hpp b/components/fileorderlist/datafileslist.hpp index 4b158d316..64584d1fb 100644 --- a/components/fileorderlist/datafileslist.hpp +++ b/components/fileorderlist/datafileslist.hpp @@ -49,12 +49,10 @@ public slots: void refresh(); private: - DataFilesModel *mMastersModel; DataFilesModel *mPluginsModel; QSortFilterProxyModel *mPluginsProxyModel; - QTableView *mMastersTable; QTableView *mPluginsTable; QMenu *mContextMenu; diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 5bb199679..4c33a555f 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -159,7 +159,7 @@ Qt::ItemFlags DataFilesModel::flags(const QModelIndex &index) const if (!file) return Qt::NoItemFlags; - if (mAvailableFiles.contains(file->fileName())) { + if (canBeChecked(file)) { if (index.column() == 0) { return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; } else { @@ -212,7 +212,6 @@ bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, in QString name = item(index.row())->fileName(); mCheckStates[name] = static_cast(value.toInt()); - emit checkedItemsChanged(checkedItems(), uncheckedItems()); emit layoutChanged(); return true; } @@ -263,73 +262,12 @@ void DataFilesModel::addFile(EsmFile *file) emit endInsertRows(); } -void DataFilesModel::addMasters(const QString &path) +void DataFilesModel::addFiles(const QString &path) { QDir dir(path); - dir.setNameFilters(QStringList(QLatin1String("*.esp"))); - - // Read the dependencies from the plugins - foreach (const QString &path, dir.entryList()) { - try { - ESM::ESMReader fileReader; - ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(mEncoding.toStdString())); - fileReader.setEncoder(&encoder); - fileReader.open(dir.absoluteFilePath(path).toStdString()); - - ESM::ESMReader::MasterList mlist = fileReader.getMasters(); - - for (unsigned int i = 0; i < mlist.size(); ++i) { - QString master = QString::fromStdString(mlist[i].name); - - // Add the plugin to the internal dependency map - mDependencies[master].append(path); - - // Don't add esps - if (master.endsWith(".esp", Qt::CaseInsensitive)) - continue; - - QFileInfo info(dir.absoluteFilePath(master)); - - EsmFile *file = new EsmFile(master); - file->setDates(info.lastModified(), info.lastRead()); - file->setPath(info.absoluteFilePath()); - - // Add the master to the table - if (findItem(master) == 0) - addFile(file); - - - } - - } catch(std::runtime_error &e) { - // An error occurred while reading the .esp - qWarning() << "Error reading esp: " << e.what(); - continue; - } - } - - // See if the masters actually exist in the filesystem - dir.setNameFilters(QStringList(QLatin1String("*.esm"))); - - foreach (const QString &path, dir.entryList()) { - QFileInfo info(dir.absoluteFilePath(path)); - - if (findItem(path) == 0) { - EsmFile *file = new EsmFile(path); - file->setDates(info.lastModified(), info.lastRead()); - - addFile(file); - } - - // Make the master selectable - mAvailableFiles.append(path); - } -} - -void DataFilesModel::addPlugins(const QString &path) -{ - QDir dir(path); - dir.setNameFilters(QStringList(QLatin1String("*.esp"))); + QStringList filters; + filters << "*.esp" << "*.esm"; + dir.setNameFilters(filters); foreach (const QString &path, dir.entryList()) { QFileInfo info(dir.absoluteFilePath(path)); @@ -347,9 +285,6 @@ void DataFilesModel::addPlugins(const QString &path) for (unsigned int i = 0; i < mlist.size(); ++i) { QString master = QString::fromStdString(mlist[i].name); masters.append(master); - - // Add the plugin to the internal dependency map - mDependencies[master].append(path); } file->setAuthor(QString::fromStdString(fileReader.getAuthor())); @@ -421,7 +356,7 @@ QStringList DataFilesModel::checkedItems() QString name = file->fileName(); // Only add the items that are in the checked list and available - if (mCheckStates[name] == Qt::Checked && mAvailableFiles.contains(name)) + if (mCheckStates[name] == Qt::Checked && canBeChecked(file)) list << name; } @@ -439,8 +374,8 @@ QStringList DataFilesModel::checkedItemsPaths() for (it = mFiles.constBegin(); it != itEnd; ++it) { EsmFile *file = item(i); ++i; - - if (mCheckStates[file->fileName()] == Qt::Checked && mAvailableFiles.contains(file->fileName())) + + if (mCheckStates[file->fileName()] == Qt::Checked && canBeChecked(file)) list << file->path(); } @@ -475,24 +410,17 @@ QStringList DataFilesModel::uncheckedItems() return list; } -void DataFilesModel::slotcheckedItemsChanged(const QStringList &checkedItems, const QStringList &unCheckedItems) +bool DataFilesModel::canBeChecked(EsmFile *file) const { - emit layoutAboutToBeChanged(); - - QStringList list; - - foreach (const QString &file, checkedItems) { - list << mDependencies[file]; - } - - foreach (const QString &file, unCheckedItems) { - foreach (const QString &remove, mDependencies[file]) { - list.removeAll(remove); + //element can be checked if all its dependencies are + bool canBeChecked = true; + foreach (const QString &master, file->masters()) + { + if (!mCheckStates.contains(master) || mCheckStates[master] != Qt::Checked) + { + canBeChecked = false; + break; } } - - mAvailableFiles.clear(); - mAvailableFiles.append(list); - - emit layoutChanged(); + return canBeChecked; } diff --git a/components/fileorderlist/model/datafilesmodel.hpp b/components/fileorderlist/model/datafilesmodel.hpp index adc80eac2..0e5008abe 100644 --- a/components/fileorderlist/model/datafilesmodel.hpp +++ b/components/fileorderlist/model/datafilesmodel.hpp @@ -34,10 +34,7 @@ public: void setEncoding(const QString &encoding); - void addFile(EsmFile *file); - - void addMasters(const QString &path); - void addPlugins(const QString &path); + void addFiles(const QString &path); void uncheckAll(); @@ -51,18 +48,12 @@ public: QModelIndex indexFromItem(EsmFile *item) const; EsmFile* findItem(const QString &name); EsmFile* item(int row) const; - -signals: - void checkedItemsChanged(const QStringList checkedItems, const QStringList unCheckedItems); - -public slots: - void slotcheckedItemsChanged(const QStringList &checkedItems, const QStringList &unCheckedItems); private: + bool canBeChecked(EsmFile *file) const; + void addFile(EsmFile *file); + QList mFiles; - QStringList mAvailableFiles; - - QHash mDependencies; QHash mCheckStates; QString mEncoding; From 0df7c7e5c17aff76fab9c4352a1904271c99c731 Mon Sep 17 00:00:00 2001 From: Michal Sciubidlo Date: Sun, 10 Feb 2013 14:08:54 +0100 Subject: [PATCH 031/151] Rename mPlugins* to mFiles* --- components/fileorderlist/datafileslist.cpp | 108 ++++++++++----------- components/fileorderlist/datafileslist.hpp | 6 +- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/components/fileorderlist/datafileslist.cpp b/components/fileorderlist/datafileslist.cpp index 80d58b35f..5ea2e051d 100644 --- a/components/fileorderlist/datafileslist.cpp +++ b/components/fileorderlist/datafileslist.cpp @@ -49,11 +49,11 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) , mCfgMgr(cfg) { // Model - mPluginsModel = new DataFilesModel(this); + mFilesModel = new DataFilesModel(this); - mPluginsProxyModel = new QSortFilterProxyModel(); - mPluginsProxyModel->setDynamicSortFilter(true); - mPluginsProxyModel->setSourceModel(mPluginsModel); + mFilesProxyModel = new QSortFilterProxyModel(); + mFilesProxyModel->setDynamicSortFilter(true); + mFilesProxyModel->setSourceModel(mFilesModel); // Filter toolbar QLabel *filterLabel = new QLabel(tr("&Filter:"), this); @@ -77,41 +77,41 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) QCheckBox checkBox; unsigned int height = checkBox.sizeHint().height() + 4; - mPluginsTable = new QTableView(this); - mPluginsTable->setModel(mPluginsProxyModel); - mPluginsTable->setObjectName("PluginsTable"); - mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); - mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mPluginsTable->setSelectionMode(QAbstractItemView::SingleSelection); - mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mPluginsTable->setAlternatingRowColors(true); - mPluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); - mPluginsTable->horizontalHeader()->setStretchLastSection(true); - mPluginsTable->horizontalHeader()->hide(); + mFilesTable = new QTableView(this); + mFilesTable->setModel(mFilesProxyModel); + mFilesTable->setObjectName("PluginsTable"); + mFilesTable->setContextMenuPolicy(Qt::CustomContextMenu); + mFilesTable->setSelectionBehavior(QAbstractItemView::SelectRows); + mFilesTable->setSelectionMode(QAbstractItemView::SingleSelection); + mFilesTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + mFilesTable->setAlternatingRowColors(true); + mFilesTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + mFilesTable->horizontalHeader()->setStretchLastSection(true); + mFilesTable->horizontalHeader()->hide(); - mPluginsTable->verticalHeader()->setDefaultSectionSize(height); - mPluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - mPluginsTable->setColumnHidden(1, true); - mPluginsTable->setColumnHidden(2, true); - mPluginsTable->setColumnHidden(3, true); - mPluginsTable->setColumnHidden(4, true); - mPluginsTable->setColumnHidden(5, true); - mPluginsTable->setColumnHidden(6, true); - mPluginsTable->setColumnHidden(7, true); - mPluginsTable->setColumnHidden(8, true); + mFilesTable->verticalHeader()->setDefaultSectionSize(height); + mFilesTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + mFilesTable->setColumnHidden(1, true); + mFilesTable->setColumnHidden(2, true); + mFilesTable->setColumnHidden(3, true); + mFilesTable->setColumnHidden(4, true); + mFilesTable->setColumnHidden(5, true); + mFilesTable->setColumnHidden(6, true); + mFilesTable->setColumnHidden(7, true); + mFilesTable->setColumnHidden(8, true); QVBoxLayout *pageLayout = new QVBoxLayout(this); pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(mPluginsTable); + pageLayout->addWidget(mFilesTable); - connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(mFilesTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - connect(mPluginsModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); + connect(mFilesModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mFilesModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + connect(mFilesTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); createActions(); } @@ -142,17 +142,17 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString { // Set the charset for reading the esm/esp files if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) { - mPluginsModel->setEncoding(encoding); + mFilesModel->setEncoding(encoding); } // Add the paths to the respective models for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { QString path = QString::fromStdString(it->string()); path.remove(QChar('\"')); - mPluginsModel->addFiles(path); + mFilesModel->addFiles(path); } - mPluginsModel->sort(0); + mFilesModel->sort(0); // mMastersTable->sortByColumn(3, Qt::AscendingOrder); // mPluginsTable->sortByColumn(3, Qt::AscendingOrder); @@ -161,7 +161,7 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString void DataFilesList::selectedFiles(std::vector& paths) { - QStringList pluginPaths = mPluginsModel->checkedItemsPaths(); + QStringList pluginPaths = mFilesModel->checkedItemsPaths(); foreach (const QString &path, pluginPaths) { paths.push_back(path.toStdString()); @@ -171,11 +171,11 @@ void DataFilesList::selectedFiles(std::vector& paths) void DataFilesList::check() { // Check the current selection - if (!mPluginsTable->selectionModel()->hasSelection()) { + if (!mFilesTable->selectionModel()->hasSelection()) { return; } - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); //sort selection ascending because selectedIndexes returns an unsorted list //qSort(indexes.begin(), indexes.end(), rowSmallerThan); @@ -184,18 +184,18 @@ void DataFilesList::check() if (!index.isValid()) return; - mPluginsModel->setCheckState(index, Qt::Checked); + mFilesModel->setCheckState(index, Qt::Checked); } } void DataFilesList::uncheck() { // uncheck the current selection - if (!mPluginsTable->selectionModel()->hasSelection()) { + if (!mFilesTable->selectionModel()->hasSelection()) { return; } - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); //sort selection ascending because selectedIndexes returns an unsorted list //qSort(indexes.begin(), indexes.end(), rowSmallerThan); @@ -204,17 +204,17 @@ void DataFilesList::uncheck() if (!index.isValid()) return; - mPluginsModel->setCheckState(index, Qt::Unchecked); + mFilesModel->setCheckState(index, Qt::Unchecked); } } void DataFilesList::refresh() { - mPluginsModel->sort(0); + mFilesModel->sort(0); // Refresh the plugins table - mPluginsTable->scrollToTop(); + mFilesTable->scrollToTop(); } @@ -230,11 +230,11 @@ void DataFilesList::setCheckState(QModelIndex index) return; if (object->objectName() == QLatin1String("PluginsTable")) { - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(index); + QModelIndex sourceIndex = mFilesProxyModel->mapToSource(index); - (mPluginsModel->checkState(sourceIndex) == Qt::Checked) - ? mPluginsModel->setCheckState(sourceIndex, Qt::Unchecked) - : mPluginsModel->setCheckState(sourceIndex, Qt::Checked); + (mFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mFilesModel->setCheckState(sourceIndex, Qt::Checked); } return; @@ -243,25 +243,25 @@ void DataFilesList::setCheckState(QModelIndex index) void DataFilesList::uncheckAll() { - mPluginsModel->uncheckAll(); + mFilesModel->uncheckAll(); } void DataFilesList::filterChanged(const QString filter) { QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString); - mPluginsProxyModel->setFilterRegExp(regExp); + mFilesProxyModel->setFilterRegExp(regExp); } void DataFilesList::showContextMenu(const QPoint &point) { // Make sure there are plugins in the view - if (!mPluginsTable->selectionModel()->hasSelection()) { + if (!mFilesTable->selectionModel()->hasSelection()) { return; } - QPoint globalPos = mPluginsTable->mapToGlobal(point); + QPoint globalPos = mFilesTable->mapToGlobal(point); - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); // Show the check/uncheck actions depending on the state of the selected items mUncheckAction->setEnabled(false); @@ -271,7 +271,7 @@ void DataFilesList::showContextMenu(const QPoint &point) if (!index.isValid()) return; - (mPluginsModel->checkState(index) == Qt::Checked) + (mFilesModel->checkState(index) == Qt::Checked) ? mUncheckAction->setEnabled(true) : mCheckAction->setEnabled(true); } @@ -282,14 +282,14 @@ void DataFilesList::showContextMenu(const QPoint &point) void DataFilesList::setCheckState(const QString& element, Qt::CheckState state) { - EsmFile *file = mPluginsModel->findItem(element); + EsmFile *file = mFilesModel->findItem(element); if (file) { - mPluginsModel->setCheckState(mPluginsModel->indexFromItem(file), Qt::Checked); + mFilesModel->setCheckState(mFilesModel->indexFromItem(file), Qt::Checked); } } QStringList DataFilesList::checkedFiles() { - return mPluginsModel->checkedItems(); + return mFilesModel->checkedItems(); } \ No newline at end of file diff --git a/components/fileorderlist/datafileslist.hpp b/components/fileorderlist/datafileslist.hpp index 64584d1fb..69a20393c 100644 --- a/components/fileorderlist/datafileslist.hpp +++ b/components/fileorderlist/datafileslist.hpp @@ -49,11 +49,11 @@ public slots: void refresh(); private: - DataFilesModel *mPluginsModel; + DataFilesModel *mFilesModel; - QSortFilterProxyModel *mPluginsProxyModel; + QSortFilterProxyModel *mFilesProxyModel; - QTableView *mPluginsTable; + QTableView *mFilesTable; QMenu *mContextMenu; From f4d60ae7b203b90c9714fff9fa81eb06a79f278e Mon Sep 17 00:00:00 2001 From: Michal Sciubidlo Date: Sun, 10 Feb 2013 19:59:25 +0100 Subject: [PATCH 032/151] Files sorting (masters then plugins). Remove unneeded includes. --- apps/launcher/datafilespage.cpp | 7 --- components/fileorderlist/datafileslist.cpp | 1 - .../fileorderlist/model/datafilesmodel.cpp | 44 +++++-------------- .../fileorderlist/model/esm/esmfile.hpp | 18 ++++---- 4 files changed, 21 insertions(+), 49 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 52b8c9cbe..8afece00b 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -7,12 +7,7 @@ #include #include -////#include "model/datafilesmodel.hpp" -////#include "model/esm/esmfile.hpp" - #include "utils/profilescombobox.hpp" -////#include "utils/filedialog.hpp" -////#include "utils/naturalsort.hpp" #include "utils/textinputdialog.hpp" #include "datafilespage.hpp" @@ -527,7 +522,5 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); mDataFilesList->uncheckAll(); - ////mMastersModel->uncheckAll(); - ////mPluginsModel->uncheckAll(); readConfig(); } diff --git a/components/fileorderlist/datafileslist.cpp b/components/fileorderlist/datafileslist.cpp index 5ea2e051d..2f1b555c1 100644 --- a/components/fileorderlist/datafileslist.cpp +++ b/components/fileorderlist/datafileslist.cpp @@ -8,7 +8,6 @@ #include "utils/filedialog.hpp" #include "utils/lineedit.hpp" -#include "utils/naturalsort.hpp" #include "datafileslist.hpp" diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 4c33a555f..682ef0128 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -8,8 +8,6 @@ #include "esm/esmfile.hpp" -#include "../utils/naturalsort.hpp" - #include "datafilesmodel.hpp" DataFilesModel::DataFilesModel(QObject *parent) : @@ -219,39 +217,21 @@ bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, in return false; } +bool lessThanEsmFile(const EsmFile *e1, const EsmFile *e2) +{ + //Masters first then alphabetically + if (e1->fileName().endsWith(".esm") && !e2->fileName().endsWith(".esm")) + return true; + 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) { - // TODO: Make this more efficient emit layoutAboutToBeChanged(); - - QList sortedFiles; - - QMultiMap timestamps; - - foreach (EsmFile *file, mFiles) - timestamps.insert(file->modified().toString(Qt::ISODate), file->fileName()); - - QMapIterator ti(timestamps); - - while (ti.hasNext()) { - ti.next(); - - QModelIndex index = indexFromItem(findItem(ti.value())); - - if (!index.isValid()) - continue; - - EsmFile *file = item(index.row()); - - if (!file) - continue; - - sortedFiles.append(file); - } - - mFiles.clear(); - mFiles = sortedFiles; - + qSort(mFiles.begin(), mFiles.end(), lessThanEsmFile); emit layoutChanged(); } diff --git a/components/fileorderlist/model/esm/esmfile.hpp b/components/fileorderlist/model/esm/esmfile.hpp index ad267aa75..52b3fbd00 100644 --- a/components/fileorderlist/model/esm/esmfile.hpp +++ b/components/fileorderlist/model/esm/esmfile.hpp @@ -26,15 +26,15 @@ public: void setMasters(const QStringList &masters); void setDescription(const QString &description); - inline QString fileName() { return mFileName; } - inline QString author() { return mAuthor; } - inline int size() { return mSize; } - inline QDateTime modified() { return mModified; } - inline QDateTime accessed() { return mAccessed; } - inline float version() { return mVersion; } - inline QString path() { return mPath; } - inline QStringList masters() { return mMasters; } - inline QString description() { return mDescription; } + inline QString fileName() const { return mFileName; } + inline QString author() const { return mAuthor; } + inline int size() const { return mSize; } + inline QDateTime modified() const { return mModified; } + inline QDateTime accessed() const { return mAccessed; } + inline float version() const { return mVersion; } + inline QString path() const { return mPath; } + inline QStringList masters() const { return mMasters; } + inline QString description() const { return mDescription; } private: From aa2547151769a91b6a84704ab338b0bdee4ecac3 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 11 Feb 2013 15:01:00 +0100 Subject: [PATCH 033/151] WIP: working on improving the config file handling --- apps/launcher/CMakeLists.txt | 6 + apps/launcher/datafilespage.cpp | 295 +++++++++----------- apps/launcher/datafilespage.hpp | 14 +- apps/launcher/main.cpp | 34 ++- apps/launcher/maindialog.cpp | 79 ++++-- apps/launcher/maindialog.hpp | 16 +- apps/launcher/model/datafilesmodel.cpp | 4 +- apps/launcher/settings/gamesettings.cpp | 9 +- apps/launcher/settings/launchersettings.cpp | 45 +++ apps/launcher/settings/launchersettings.hpp | 16 ++ apps/launcher/settings/settingsbase.hpp | 23 +- apps/launcher/utils/lineedit.cpp | 13 +- apps/launcher/utils/lineedit.hpp | 2 +- apps/launcher/utils/profilescombobox.cpp | 65 ++++- apps/launcher/utils/profilescombobox.hpp | 4 +- 15 files changed, 404 insertions(+), 221 deletions(-) create mode 100644 apps/launcher/settings/launchersettings.cpp create mode 100644 apps/launcher/settings/launchersettings.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 044a0a0b7..3c721e238 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -11,7 +11,9 @@ set(LAUNCHER settings/gamesettings.cpp settings/graphicssettings.cpp + settings/launchersettings.cpp + utils/comboboxlineedit.cpp utils/naturalsort.cpp utils/lineedit.cpp utils/profilescombobox.cpp @@ -32,8 +34,10 @@ set(LAUNCHER_HEADER settings/gamesettings.hpp settings/graphicssettings.hpp + settings/launchersettings.hpp settings/settingsbase.hpp + utils/comboboxlineedit.cpp utils/lineedit.hpp utils/naturalsort.hpp utils/profilescombobox.hpp @@ -52,6 +56,7 @@ set(LAUNCHER_HEADER_MOC model/modelitem.hpp model/esm/esmfile.hpp + utils/comboboxlineedit.hpp utils/lineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp @@ -86,6 +91,7 @@ ENDIF(OGRE_STATIC) add_executable(omwlauncher ${GUI_TYPE} ${LAUNCHER} + ${LAUNCHER_HEADER} ${RCC_SRCS} ${MOC_SRCS} ) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index e25300394..12323b1f1 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -7,6 +7,7 @@ #include "model/esm/esmfile.hpp" #include "settings/gamesettings.hpp" +#include "settings/launchersettings.hpp" #include "utils/profilescombobox.hpp" #include "utils/lineedit.hpp" @@ -47,9 +48,10 @@ bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2) return index1.row() <= index2.row(); } -DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, QWidget *parent) +DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent) : mCfgMgr(cfg) , mGameSettings(gameSettings) + , mLauncherSettings(launcherSettings) , QWidget(parent) { // Models @@ -129,15 +131,19 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mPluginsTable->setColumnHidden(8, true); // Add both tables to a splitter - QSplitter *splitter = new QSplitter(this); - splitter->setOrientation(Qt::Horizontal); - splitter->addWidget(mMastersTable); - splitter->addWidget(mPluginsTable); + mSplitter = new QSplitter(this); + mSplitter->setOrientation(Qt::Horizontal); + mSplitter->setChildrenCollapsible(false); // Don't allow the widgets to be hidden + mSplitter->addWidget(mMastersTable); + mSplitter->addWidget(mPluginsTable); // Adjust the default widget widths inside the splitter QList sizeList; - sizeList << 175 << 200; - splitter->setSizes(sizeList); + sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt(); + sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt(); + qDebug() << sizeList; + + mSplitter->setSizes(sizeList); // Bottom part with profile options QLabel *profileLabel = new QLabel(tr("Current Profile: "), this); @@ -158,7 +164,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam QVBoxLayout *pageLayout = new QVBoxLayout(this); pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(splitter); + pageLayout->addWidget(mSplitter); pageLayout->addWidget(mProfileToolBar); // Create a dialog for the new profile name input @@ -178,8 +184,9 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); + connect(mSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter())); + createActions(); - setupConfig(); setupDataFiles(); } @@ -221,126 +228,50 @@ void DataFilesPage::createActions() } -void DataFilesPage::setupConfig() -{ - // Open our config file - QString config = QString::fromStdString((mCfgMgr.getUserPath() / "launcher.cfg").string()); - mLauncherConfig = new QSettings(config, QSettings::IniFormat); - - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } - - mLauncherConfig->beginGroup("Profiles"); - QStringList profiles = mLauncherConfig->childGroups(); - - // Add the profiles to the combobox - foreach (const QString &profile, profiles) { - - if (profile.contains(QRegExp("[^a-zA-Z0-9_]"))) - continue; // Profile name contains garbage - - - qDebug() << "adding " << profile; - mProfilesComboBox->addItem(profile); - } - - // Add a default profile - if (mProfilesComboBox->findText(QString("Default")) == -1) { - mProfilesComboBox->addItem(QString("Default")); - } - - QString currentProfile = mLauncherConfig->value("CurrentProfile").toString(); - - if (currentProfile.isEmpty()) { - // No current profile selected - currentProfile = "Default"; - } - - const int currentIndex = mProfilesComboBox->findText(currentProfile); - if (currentIndex != -1) { - // Profile is found - mProfilesComboBox->setCurrentIndex(currentIndex); - } - - mLauncherConfig->endGroup(); -} - - void DataFilesPage::readConfig() { - // Don't read the config if no masters are found - if (mMastersModel->rowCount() < 1) - return; +// // Don't read the config if no masters are found +// if (mMastersModel->rowCount() < 1) +// return; - QString profile = mProfilesComboBox->currentText(); - - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } - - mLauncherConfig->beginGroup("Profiles"); - mLauncherConfig->beginGroup(profile); - - QStringList childKeys = mLauncherConfig->childKeys(); - QStringList plugins; - - // Sort the child keys numerical instead of alphabetically - // i.e. Plugin1, Plugin2 instead of Plugin1, Plugin10 - qSort(childKeys.begin(), childKeys.end(), naturalSortLessThanCI); - - foreach (const QString &key, childKeys) { - const QString keyValue = mLauncherConfig->value(key).toString(); - - if (key.startsWith("Plugin")) { - //QStringList checked = mPluginsModel->checkedItems(); - EsmFile *file = mPluginsModel->findItem(keyValue); - QModelIndex index = mPluginsModel->indexFromItem(file); - - mPluginsModel->setCheckState(index, Qt::Checked); - // Move the row to the top of te view - //mPluginsModel->moveRow(index.row(), checked.count()); - plugins << keyValue; - } - - if (key.startsWith("Master")) { - EsmFile *file = mMastersModel->findItem(keyValue); - mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked); - } - } - - qDebug() << plugins; - - -// // Set the checked item positions -// const QStringList checked = mPluginsModel->checkedItems(); -// for (int i = 0; i < plugins.size(); ++i) { -// EsmFile *file = mPluginsModel->findItem(plugins.at(i)); -// QModelIndex index = mPluginsModel->indexFromItem(file); -// mPluginsModel->moveRow(index.row(), i); -// qDebug() << "Moving: " << plugins.at(i) << " from: " << index.row() << " to: " << i << " count: " << checked.count(); +// QString profile = mProfilesComboBox->currentText(); +// // Make sure we have no groups open +// while (!mLauncherConfig->group().isEmpty()) { +// mLauncherConfig->endGroup(); // } - // Iterate over the plugins to set their checkstate and position -// for (int i = 0; i < plugins.size(); ++i) { -// const QString plugin = plugins.at(i); +// mLauncherConfig->beginGroup("Profiles"); +// mLauncherConfig->beginGroup(profile); -// const QList pluginList = mPluginsModel->findItems(plugin); +// QStringList childKeys = mLauncherConfig->childKeys(); +// QStringList plugins; -// if (!pluginList.isEmpty()) -// { -// foreach (const QStandardItem *currentPlugin, pluginList) { -// mPluginsModel->setData(currentPlugin->index(), Qt::Checked, Qt::CheckStateRole); +// // Sort the child keys numerical instead of alphabetically +// // i.e. Plugin1, Plugin2 instead of Plugin1, Plugin10 +// qSort(childKeys.begin(), childKeys.end(), naturalSortLessThanCI); -// // Move the plugin to the position specified in the config file -// mPluginsModel->insertRow(i, mPluginsModel->takeRow(currentPlugin->row())); -// } +// foreach (const QString &key, childKeys) { +// const QString keyValue = mLauncherConfig->value(key).toString(); + +// if (key.startsWith("Plugin")) { +// //QStringList checked = mPluginsModel->checkedItems(); +// EsmFile *file = mPluginsModel->findItem(keyValue); +// QModelIndex index = mPluginsModel->indexFromItem(file); + +// mPluginsModel->setCheckState(index, Qt::Checked); +// // Move the row to the top of te view +// //mPluginsModel->moveRow(index.row(), checked.count()); +// plugins << keyValue; +// } + +// if (key.startsWith("Master")) { +// EsmFile *file = mMastersModel->findItem(keyValue); +// mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked); // } // } +// qDebug() << plugins; } void DataFilesPage::setupDataFiles() @@ -362,10 +293,43 @@ void DataFilesPage::setupDataFiles() mPluginsModel->addPlugins(dataLocal); } + loadSettings(); +} + +void DataFilesPage::loadSettings() +{ + qDebug() << "load settings"; +} + +void DataFilesPage::saveSettings() +{ + QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + qDebug() << "save settings" << profile; + + QStringList items = mMastersModel->checkedItems(); + + foreach(const QString &master, items) { + mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), master); + } + + items.clear(); + items = mPluginsModel->checkedItems(); + + qDebug() << items.size(); + + foreach(const QString &plugin, items) { + qDebug() << "setting " << plugin; + mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), plugin); + } + + + } void DataFilesPage::writeConfig(QString profile) { + + // // Don't overwrite the config if no masters are found // if (mMastersModel->rowCount() < 1) // return; @@ -518,21 +482,22 @@ void DataFilesPage::writeConfig(QString profile) void DataFilesPage::newProfile() { - if (mNewProfileDialog->exec() == QDialog::Accepted) { +// if (mNewProfileDialog->exec() == QDialog::Accepted) { - const QString text = mNewProfileDialog->lineEdit()->text(); - mProfilesComboBox->addItem(text); +// const QString text = mNewProfileDialog->lineEdit()->text(); +// mProfilesComboBox->addItem(text); +// mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(text)); +// } - // Copy the currently checked items to cfg - writeConfig(text); - mLauncherConfig->sync(); - - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(text)); - } + mDeleteProfileAction->setEnabled(false); + mProfilesComboBox->setCurrentIndex(-1); + mProfilesComboBox->setEditEnabled(true); + mProfilesComboBox->lineEdit()->setFocus(); } void DataFilesPage::updateOkButton(const QString &text) { + // We do this here because we need the profiles combobox text if (text.isEmpty()) { mNewProfileDialog->setOkButtonEnabled(false); return; @@ -543,6 +508,16 @@ void DataFilesPage::updateOkButton(const QString &text) : mNewProfileDialog->setOkButtonEnabled(false); } +void DataFilesPage::updateSplitter() +{ + // Sigh, update the saved splitter size in settings only when moved + // Since getting mSplitter->sizes() if page is hidden returns invalid values + QList sizes = mSplitter->sizes(); + + mLauncherSettings.setValue(QString("General/MastersTable/width"), QString::number(sizes.at(0))); + mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1))); +} + void DataFilesPage::deleteProfile() { QString profile = mProfilesComboBox->currentText(); @@ -562,18 +537,8 @@ void DataFilesPage::deleteProfile() msgBox.exec(); if (msgBox.clickedButton() == deleteButton) { - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } - - mLauncherConfig->beginGroup("Profiles"); - - // Open the profile-name subgroup - mLauncherConfig->beginGroup(profile); - mLauncherConfig->remove(""); // Clear the subgroup - mLauncherConfig->endGroup(); - mLauncherConfig->endGroup(); + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); // Remove the profile from the combobox mProfilesComboBox->removeItem(mProfilesComboBox->findText(profile)); @@ -624,11 +589,8 @@ void DataFilesPage::refresh() { mPluginsModel->sort(0); - // Refresh the plugins table mPluginsTable->scrollToTop(); - writeConfig(); - readConfig(); } @@ -679,50 +641,43 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre mProfilesComboBox->setEditEnabled(true); } - if (!previous.isEmpty()) { - writeConfig(previous); - mLauncherConfig->sync(); - - if (mProfilesComboBox->currentIndex() == -1) - return; - - } else { + if (previous.isEmpty()) return; - } + + if (mProfilesComboBox->findText(previous) == -1) + return; // Profile was deleted + + // Store the previous profile + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), previous); + saveSettings(); + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); + mMastersModel->uncheckAll(); mPluginsModel->uncheckAll(); - readConfig(); + loadSettings(); } void DataFilesPage::profileRenamed(const QString &previous, const QString ¤t) { + qDebug() << "rename"; if (previous.isEmpty()) return; // Save the new profile name - writeConfig(current); + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); + saveSettings(); - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } + // Remove the old one + mLauncherSettings.remove(QString("Profiles/") + previous + QString("/master")); + mLauncherSettings.remove(QString("Profiles/") + previous + QString("/plugin")); - mLauncherConfig->beginGroup("Profiles"); + // Remove the profile from the combobox + mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); - // Open the profile-name subgroup - mLauncherConfig->beginGroup(previous); - mLauncherConfig->remove(""); // Clear the subgroup - mLauncherConfig->endGroup(); - mLauncherConfig->endGroup(); - mLauncherConfig->sync(); - - // Remove the profile from the combobox - mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); - - mMastersModel->uncheckAll(); - mPluginsModel->uncheckAll(); - readConfig(); + mMastersModel->uncheckAll(); + mPluginsModel->uncheckAll(); + loadSettings(); } void DataFilesPage::showContextMenu(const QPoint &point) diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index e40d29d60..2dbbdb667 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -6,16 +6,18 @@ class QTableView; class QSortFilterProxyModel; -class QSettings; class QAction; class QToolBar; +class QSplitter; class QMenu; + class ProfilesComboBox; class DataFilesModel; class TextInputDialog; class ProfilesComboBox; class GameSettings; +class LauncherSettings; namespace Files { struct ConfigurationManager; } @@ -24,11 +26,13 @@ class DataFilesPage : public QWidget Q_OBJECT public: - DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, QWidget *parent = 0); + DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0); ProfilesComboBox *mProfilesComboBox; void writeConfig(QString profile = QString()); + void saveSettings(); + public slots: void setCheckState(QModelIndex index); @@ -38,6 +42,7 @@ public slots: void profileChanged(const QString &previous, const QString ¤t); void profileRenamed(const QString &previous, const QString ¤t); void updateOkButton(const QString &text); + void updateSplitter(); // Action slots void newProfile(); @@ -61,6 +66,7 @@ private: QToolBar *mProfileToolBar; QMenu *mContextMenu; + QSplitter *mSplitter; QAction *mNewProfileAction; QAction *mDeleteProfileAction; @@ -74,8 +80,8 @@ private: Files::ConfigurationManager &mCfgMgr; - QSettings *mLauncherConfig; GameSettings &mGameSettings; + LauncherSettings &mLauncherSettings; TextInputDialog *mNewProfileDialog; @@ -87,6 +93,8 @@ private: void setupConfig(); void readConfig(); + void loadSettings(); + }; #endif diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 43bf50fbc..ba84518c1 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -16,6 +16,7 @@ #include "maindialog.hpp" #include "settings/gamesettings.hpp" #include "settings/graphicssettings.hpp" +#include "settings/launchersettings.hpp" int main(int argc, char *argv[]) @@ -52,6 +53,7 @@ int main(int argc, char *argv[]) GameSettings gameSettings(cfgMgr); GraphicsSettings graphicsSettings; + LauncherSettings launcherSettings; QStringList paths; paths.append(userPath + QString("openmw.cfg")); @@ -118,8 +120,6 @@ int main(int argc, char *argv[]) } // On to the graphics settings - qDebug() << userPath; - QFile localDefault(QString("settings-default.cfg")); QFile globalDefault(globalPath + QString("settings-default.cfg")); @@ -163,8 +163,36 @@ int main(int argc, char *argv[]) file.close(); } + // Now the launcher settings + paths.clear(); + paths.append(QString("launcher.cfg")); + paths.append(userPath + QString("launcher.cfg")); - MainDialog mainWin(gameSettings, graphicsSettings); + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error opening OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return 0; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + launcherSettings.readFile(stream); + } + file.close(); + } + + + MainDialog mainWin(gameSettings, graphicsSettings, launcherSettings); if (mainWin.setup()) { mainWin.show(); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 4d3d24bd9..f48ea603b 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -2,6 +2,7 @@ #include "settings/gamesettings.hpp" #include "settings/graphicssettings.hpp" +#include "settings/launchersettings.hpp" #include "utils/profilescombobox.hpp" @@ -11,9 +12,11 @@ #include "datafilespage.hpp" MainDialog::MainDialog(GameSettings &gameSettings, - GraphicsSettings &graphicsSettings) + GraphicsSettings &graphicsSettings, + LauncherSettings &launcherSettings) : mGameSettings(gameSettings) , mGraphicsSettings(graphicsSettings) + , mLauncherSettings(launcherSettings) { QWidget *centralWidget = new QWidget(this); @@ -132,7 +135,7 @@ void MainDialog::createPages() { mPlayPage = new PlayPage(this); mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this); - mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, this); + mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage mPlayPage->mProfilesComboBox->setModel(mDataFilesPage->mProfilesComboBox->model()); @@ -161,18 +164,11 @@ void MainDialog::createPages() bool MainDialog::setup() { - // Setup the Graphics page + // Call this so we can exit on Ogre errors before mainwindow is shown if (!mGraphicsPage->setupOgre()) { return false; } - // Setup the Data Files page - /* - if (!mDataFilesPage->setupDataFiles()) { - return false; - }*/ - - return true; } @@ -184,11 +180,28 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) mPagesWidget->setCurrentIndex(mIconWidget->row(current)); } -void MainDialog::closeEvent(QCloseEvent *event) +void MainDialog::loadSettings() +{ + +} + +void MainDialog::saveSettings() +{ + QString width = QString::number(this->width()); + QString height = QString::number(this->height()); + + mLauncherSettings.setValue(QString("General/MainWindow/width"), width); + mLauncherSettings.setValue(QString("General/MainWindow/height"), height); + + qDebug() << "size: " << width << height; +} + +void MainDialog::writeSettings() { // Now write all config files - mDataFilesPage->writeConfig(); + saveSettings(); mGraphicsPage->saveSettings(); + mDataFilesPage->saveSettings(); QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); QDir dir(userPath); @@ -203,7 +216,7 @@ void MainDialog::closeEvent(QCloseEvent *event) Please make sure you have the right permissions \ and try again.
").arg(userPath)); msgBox.exec(); - event->accept(); + return; } } @@ -220,7 +233,7 @@ void MainDialog::closeEvent(QCloseEvent *event) Please make sure you have the right permissions \ and try again.
").arg(file.fileName())); msgBox.exec(); - event->accept(); + return; } QTextStream stream(&file); @@ -242,26 +255,52 @@ void MainDialog::closeEvent(QCloseEvent *event) Please make sure you have the right permissions \ and try again.
").arg(file.fileName())); msgBox.exec(); - event->accept(); + return; } stream.setDevice(&file); stream.setCodec(QTextCodec::codecForName("UTF-8")); mGraphicsSettings.writeFile(stream); + file.close(); + // Launcher settings + file.setFileName(userPath + QString("launcher.cfg")); + + if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { + // File cannot be opened or created + QMessageBox msgBox; + msgBox.setWindowTitle("Error writing Launcher configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not open or create %0 for writing

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return; + } + + stream.setDevice(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mLauncherSettings.writeFile(stream); + file.close(); +} + +void MainDialog::closeEvent(QCloseEvent *event) +{ + saveSettings(); + writeSettings(); event->accept(); } void MainDialog::play() { // First do a write of all the configs, just to be sure - mDataFilesPage->writeConfig(); + //mDataFilesPage->writeConfig(); //mGraphicsPage->writeConfig(); - - // Save user settings - const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); - mSettings.saveUser(settingspath); + saveSettings(); + writeSettings(); #ifdef Q_OS_WIN QString game = "./openmw.exe"; diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index c9654b874..7167d101d 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -4,7 +4,6 @@ #include #include -#include class QListWidget; class QListWidgetItem; @@ -19,22 +18,31 @@ class DataFilesPage; class GameSettings; class GraphicsSettings; +class LauncherSettings; class MainDialog : public QMainWindow { Q_OBJECT public: - MainDialog(GameSettings &gameSettings, GraphicsSettings &GraphicsSettings); + MainDialog(GameSettings &gameSettings, + GraphicsSettings &GraphicsSettings, + LauncherSettings &launcherSettings); + + bool setup(); public slots: void changePage(QListWidgetItem *current, QListWidgetItem *previous); void play(); - bool setup(); private: void createIcons(); void createPages(); + + void loadSettings(); + void saveSettings(); + void writeSettings(); + void closeEvent(QCloseEvent *event); QListWidget *mIconWidget; @@ -45,10 +53,10 @@ private: DataFilesPage *mDataFilesPage; Files::ConfigurationManager mCfgMgr; - Settings::Manager mSettings; GameSettings &mGameSettings; GraphicsSettings &mGraphicsSettings; + LauncherSettings &mLauncherSettings; }; diff --git a/apps/launcher/model/datafilesmodel.cpp b/apps/launcher/model/datafilesmodel.cpp index e84dbe0ac..ae59cc3c3 100644 --- a/apps/launcher/model/datafilesmodel.cpp +++ b/apps/launcher/model/datafilesmodel.cpp @@ -334,6 +334,7 @@ void DataFilesModel::addPlugins(const QString &path) QFileInfo info(dir.absoluteFilePath(path)); EsmFile *file = new EsmFile(path); + try { ESM::ESMReader fileReader; ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(mEncoding.toStdString())); @@ -361,7 +362,8 @@ void DataFilesModel::addPlugins(const QString &path) // Put the file in the table - addFile(file); + if (findItem(path) == 0) + addFile(file); } catch(std::runtime_error &e) { // An error occurred while reading the .esp qWarning() << "Error reading esp: " << e.what(); diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 2420c1e6c..5f0fb77bc 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -101,7 +101,14 @@ bool GameSettings::readFile(QTextStream &stream) qDebug() << "key: " << key; // There can be multiple data keys if (key == QLatin1String("data")) { - cache.insertMulti(key, value); + // Remove keys from previous config and overwrite them + mSettings.remove(key); + QStringList values = cache.values(key); + if (!values.contains(value)) { + // Do not insert duplicate values + qDebug() << "values does not contain: " << value << values; + cache.insertMulti(key, value); + } } else { cache.insert(key, value); } diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp new file mode 100644 index 000000000..c189c282f --- /dev/null +++ b/apps/launcher/settings/launchersettings.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#include "launchersettings.hpp" + +LauncherSettings::LauncherSettings() +{ +} + +LauncherSettings::~LauncherSettings() +{ +} + + +bool LauncherSettings::writeFile(QTextStream &stream) +{ + QString sectionPrefix; + QRegExp sectionRe("([^/]+)/(.+)$"); + QMap settings = SettingsBase::getSettings(); + + QMapIterator i(settings); + while (i.hasNext()) { + i.next(); + + QString prefix; + QString key; + + if (sectionRe.exactMatch(i.key())) { + prefix = sectionRe.cap(1); + key = sectionRe.cap(2); + } + + if (sectionPrefix != prefix) { + sectionPrefix = prefix; + stream << "\n[" << prefix << "]\n"; + } + + stream << key << "=" << i.value() << "\n"; + } + + return true; + +} diff --git a/apps/launcher/settings/launchersettings.hpp b/apps/launcher/settings/launchersettings.hpp new file mode 100644 index 000000000..cf4dd4c9f --- /dev/null +++ b/apps/launcher/settings/launchersettings.hpp @@ -0,0 +1,16 @@ +#ifndef LAUNCHERSETTINGS_HPP +#define LAUNCHERSETTINGS_HPP + +#include "settingsbase.hpp" + +class LauncherSettings : public SettingsBase> +{ +public: + LauncherSettings(); + ~LauncherSettings(); + + bool writeFile(QTextStream &stream); + +}; + +#endif // LAUNCHERSETTINGS_HPP diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index 6b8b52762..e09ea6203 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -2,6 +2,7 @@ #define SETTINGSBASE_HPP #include +#include #include #include #include @@ -26,6 +27,17 @@ public: mSettings.insert(key, value); } + inline void setMultiValue(const QString &key, const QString &value) + { + mSettings.insertMulti(key, value); + } + + + inline void remove(const QString &key) + { + mSettings.remove(key); + } + Map getSettings() {return mSettings;} bool readFile(QTextStream &stream) @@ -56,11 +68,18 @@ public: if (!sectionPrefix.isEmpty()) key.prepend(sectionPrefix); - // QMap will replace the value if key exists, QMultiMap creates a new one - mCache.insert(key, value); + mSettings.remove(key); + + QStringList values = mCache.values(key); + if (!values.contains(value)) { + // QMap will replace the value if key exists, QMultiMap creates a new one + mCache.insert(key, value); + } } } + qDebug() << "HI THERE! " << mCache; + if (mSettings.isEmpty()) { mSettings = mCache; // This is the first time we read a file return true; diff --git a/apps/launcher/utils/lineedit.cpp b/apps/launcher/utils/lineedit.cpp index dac196425..b0f339589 100644 --- a/apps/launcher/utils/lineedit.cpp +++ b/apps/launcher/utils/lineedit.cpp @@ -1,7 +1,8 @@ -#include "lineedit.hpp" #include #include +#include "lineedit.hpp" + LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) { @@ -13,9 +14,11 @@ LineEdit::LineEdit(QWidget *parent) mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); mClearButton->hide(); connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear())); - connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateCloseButton(const QString&))); + connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateClearButton(const QString&))); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); + + setObjectName(QString("LineEdit")); + setStyleSheet(QString("LineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); QSize msz = minimumSizeHint(); setMinimumSize(qMax(msz.width(), mClearButton->sizeHint().height() + frameWidth * 2 + 2), qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2)); @@ -29,9 +32,7 @@ void LineEdit::resizeEvent(QResizeEvent *) (rect().bottom() + 1 - sz.height())/2); } -void LineEdit::updateCloseButton(const QString& text) +void LineEdit::updateClearButton(const QString& text) { mClearButton->setVisible(!text.isEmpty()); } - - diff --git a/apps/launcher/utils/lineedit.hpp b/apps/launcher/utils/lineedit.hpp index 2ed76d6eb..14bd7b1b4 100644 --- a/apps/launcher/utils/lineedit.hpp +++ b/apps/launcher/utils/lineedit.hpp @@ -25,7 +25,7 @@ protected: void resizeEvent(QResizeEvent *); private slots: - void updateCloseButton(const QString &text); + void updateClearButton(const QString &text); private: QToolButton *mClearButton; diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index 8354d4a78..3a75ba417 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -1,45 +1,94 @@ #include #include #include +#include +#include #include "profilescombobox.hpp" +#include "comboboxlineedit.hpp" ProfilesComboBox::ProfilesComboBox(QWidget *parent) : QComboBox(parent) { mValidator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore - - setEditable(true); + setEditEnabled(true); setValidator(mValidator); setCompleter(0); connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(slotIndexChanged(int))); - connect(lineEdit(), SIGNAL(returnPressed()), this, - SLOT(slotReturnPressed())); + + } void ProfilesComboBox::setEditEnabled(bool editable) { - if (!editable) + qDebug() << "called"; + if (isEditable() == editable) + return; + + if (!editable) { + disconnect(lineEdit(), SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); + disconnect(lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString))); return setEditable(false); + } // Reset the completer and validator setEditable(true); setValidator(mValidator); + + ComboBoxLineEdit *edit = new ComboBoxLineEdit(this); + setLineEdit(edit); setCompleter(0); + + connect(lineEdit(), SIGNAL(editingFinished()), this, + SLOT(slotEditingFinished())); + + connect(lineEdit(), SIGNAL(textChanged(QString)), this, + SLOT(slotTextChanged(QString))); } -void ProfilesComboBox::slotReturnPressed() +void ProfilesComboBox::slotTextChanged(const QString &text) { + QString previous = itemText(currentIndex()); +// lineEdit()->setPalette(QApplication::palette()); + + if (text.isEmpty()) + return; + + if (text == previous) + return; + + qDebug() << "textChanged"; + if (findText(text) != -1) { + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Text,Qt::red); + lineEdit()->setPalette(*palette); + } +} + +void ProfilesComboBox::slotEditingFinished() +{ + qDebug() << "returnpressed"; QString current = currentText(); QString previous = itemText(currentIndex()); + if (current.isEmpty()) + return; + + if (current == previous) + return; + if (findText(current) != -1) return; - setItemText(currentIndex(), current); - emit(profileRenamed(previous, current)); + + if (currentIndex() == -1) { + addItem(currentText()); + } else { + setItemText(currentIndex(), current); + emit(profileRenamed(previous, current)); + } } void ProfilesComboBox::slotIndexChanged(int index) diff --git a/apps/launcher/utils/profilescombobox.hpp b/apps/launcher/utils/profilescombobox.hpp index c7da60d2a..08ead9a7a 100644 --- a/apps/launcher/utils/profilescombobox.hpp +++ b/apps/launcher/utils/profilescombobox.hpp @@ -4,7 +4,6 @@ #include class QString; - class QRegExpValidator; class ProfilesComboBox : public QComboBox @@ -19,8 +18,9 @@ signals: void profileRenamed(const QString &oldName, const QString &newName); private slots: - void slotReturnPressed(); + void slotEditingFinished(); void slotIndexChanged(int index); + void slotTextChanged(const QString &text); private: QString mOldProfile; From d213ff680ff5e71874ef33065d38f1285d68e67a Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 12 Feb 2013 20:55:45 +0100 Subject: [PATCH 034/151] Disabled terrain LOD --- apps/openmw/mwrender/terrain.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 2c2e9e6fc..df8d34e74 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -40,9 +40,9 @@ namespace MWRender ->getActiveProfile(); mActiveProfile = static_cast(activeProfile); - //The pixel error should be as high as possible without it being noticed - //as it governs how fast mesh quality decreases. - mTerrainGlobals->setMaxPixelError(8); + // We don't want any pixel error at all. Really, LOD makes no sense here - morrowind uses 65x65 verts in one cell, + // so applying LOD is most certainly slower than doing no LOD at all. + mTerrainGlobals->setMaxPixelError(0); mTerrainGlobals->setLayerBlendMapSize(32); From de90b911c9d729fc4abe856fed525d565beb1c71 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 12 Feb 2013 20:56:00 +0100 Subject: [PATCH 035/151] Near clip plane corrections --- apps/openmw/mwrender/refraction.cpp | 36 ++++++++++++++++++++++++++--- apps/openmw/mwrender/refraction.hpp | 11 ++++++++- apps/openmw/mwrender/water.cpp | 9 ++++++-- apps/openmw/mwrender/water.hpp | 1 + 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index 85642bc08..05229da1d 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "renderconst.hpp" @@ -14,9 +15,13 @@ namespace MWRender Refraction::Refraction(Ogre::Camera *parentCamera) : mParentCamera(parentCamera) + , mRenderActive(false) + , mIsUnderwater(false) { mCamera = mParentCamera->getSceneManager()->createCamera("RefractionCamera"); + mParentCamera->getSceneManager()->addRenderQueueListener(this); + Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual("WaterRefraction", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); @@ -24,7 +29,7 @@ namespace MWRender Ogre::Viewport* vp = mRenderTarget->addViewport(mCamera); vp->setOverlaysEnabled(false); vp->setShadowsEnabled(false); - vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain); + vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Sky); vp->setMaterialScheme("water_reflection"); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); @@ -47,17 +52,42 @@ namespace MWRender mCamera->setAspectRatio(mParentCamera->getAspectRatio()); mCamera->setFOVy(mParentCamera->getFOVy()); - mCamera->enableCustomNearClipPlane(mNearClipPlane); + mRenderActive = true; } void Refraction::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { - + mRenderActive = false; } void Refraction::setHeight(float height) { mNearClipPlane = Ogre::Plane( -Ogre::Vector3(0,1,0), -(height + 5)); + mNearClipPlaneUnderwater = Ogre::Plane( Ogre::Vector3(0,1,0), height - 5); + } + + void Refraction::setViewportBackground (Ogre::ColourValue colour) + { + mRenderTarget->getViewport (0)->setBackgroundColour (colour); + } + + void Refraction::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) + { + // We don't want the sky to get clipped by custom near clip plane (the water plane) + if (queueGroupId < 20 && mRenderActive) + { + mCamera->disableCustomNearClipPlane(); + Ogre::Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + } + } + + void Refraction::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) + { + if (queueGroupId < 20 && mRenderActive) + { + mCamera->enableCustomNearClipPlane(mIsUnderwater ? mNearClipPlaneUnderwater : mNearClipPlane); + Ogre::Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + } } } diff --git a/apps/openmw/mwrender/refraction.hpp b/apps/openmw/mwrender/refraction.hpp index e3777d9cf..6b3c487c1 100644 --- a/apps/openmw/mwrender/refraction.hpp +++ b/apps/openmw/mwrender/refraction.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace Ogre { @@ -13,7 +14,7 @@ namespace Ogre namespace MWRender { - class Refraction : public Ogre::RenderTargetListener + class Refraction : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener { public: @@ -23,12 +24,20 @@ namespace MWRender void setHeight (float height); void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + void setViewportBackground(Ogre::ColourValue colour); + void setUnderwater(bool underwater) {mIsUnderwater = underwater;} + + void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); + void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); private: Ogre::Camera* mParentCamera; Ogre::Camera* mCamera; Ogre::RenderTarget* mRenderTarget; Ogre::Plane mNearClipPlane; + Ogre::Plane mNearClipPlaneUnderwater; + bool mRenderActive; + bool mIsUnderwater; }; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 867829564..f31dca08c 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -124,8 +124,8 @@ void PlaneReflection::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::St { if (queueGroupId < 20 && mRenderActive) { - if (!mIsUnderwater) - mCamera->enableCustomNearClipPlane(mErrorPlane); + // this trick does not seem to work well for extreme angles + mCamera->enableCustomNearClipPlane(mIsUnderwater ? mErrorPlaneUnderwater : mErrorPlane); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); } } @@ -159,6 +159,7 @@ void PlaneReflection::setHeight (float height) { mWaterPlane = Plane(Ogre::Vector3(0,1,0), height); mErrorPlane = Plane(Ogre::Vector3(0,1,0), height - 5); + mErrorPlaneUnderwater = Plane(Ogre::Vector3(0,-1,0), -height - 5); } void PlaneReflection::setActive (bool active) @@ -348,6 +349,8 @@ Water::updateUnderwater(bool underwater) if (mReflection) mReflection->setUnderwater (mIsUnderwater); + if (mRefraction) + mRefraction->setUnderwater (mIsUnderwater); updateVisible(); } @@ -377,6 +380,8 @@ void Water::setViewportBackground(const ColourValue& bg) { if (mReflection) mReflection->setViewportBackground(bg); + if (mRefraction) + mRefraction->setViewportBackground(bg); } void Water::updateVisible() diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index cf181674a..9aa18f008 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -89,6 +89,7 @@ namespace MWRender { SkyManager* mSky; Ogre::Plane mWaterPlane; Ogre::Plane mErrorPlane; + Ogre::Plane mErrorPlaneUnderwater; bool mRenderActive; }; From 6a49ea9b4fd5726f07c17db95c620a1059f78d1f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 13 Feb 2013 18:39:36 +0100 Subject: [PATCH 036/151] Cleaning out some old bits --- apps/openmw/mwbase/inputmanager.hpp | 3 -- apps/openmw/mwgui/settingswindow.cpp | 6 +++ apps/openmw/mwinput/inputmanagerimp.cpp | 17 ++------- apps/openmw/mwinput/inputmanagerimp.hpp | 4 -- apps/openmw/mwrender/refraction.cpp | 6 +-- apps/openmw/mwrender/refraction.hpp | 1 - apps/openmw/mwrender/renderingmanager.cpp | 45 +++-------------------- apps/openmw/mwrender/renderingmanager.hpp | 2 - apps/openmw/mwrender/water.cpp | 2 - 9 files changed, 16 insertions(+), 70 deletions(-) diff --git a/apps/openmw/mwbase/inputmanager.hpp b/apps/openmw/mwbase/inputmanager.hpp index f69e1a152..8293cbfa7 100644 --- a/apps/openmw/mwbase/inputmanager.hpp +++ b/apps/openmw/mwbase/inputmanager.hpp @@ -39,9 +39,6 @@ namespace MWBase virtual int getNumActions() = 0; virtual void enableDetectingBindingMode (int action) = 0; virtual void resetToDefaultBindings() = 0; - - virtual void create () = 0; - virtual void destroy () = 0; }; } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index eaea022c0..73f2f6c8a 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -370,6 +370,12 @@ namespace MWGui apply(); } } + else if (_sender == mVSyncButton) + { + Settings::Manager::setBool("vsync", "Video", newState); + MWBase::Environment::get().getWindowManager()-> + messageBox("VSync will be applied after a restart", std::vector()); + } else { if (_sender == mVSyncButton) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 00849503c..0934d8763 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -53,14 +53,6 @@ namespace MWInput , mUIYMultiplier (Settings::Manager::getFloat("ui y multiplier", "Input")) , mPreviewPOVDelay(0.f) , mTimeIdle(0.f) - { - create(); - - changeInputMode(false); - } - - - void InputManager::create() { Ogre::RenderWindow* window = mOgre.getWindow (); size_t windowHnd; @@ -139,9 +131,11 @@ namespace MWInput mControlSwitch["playermagic"] = true; mControlSwitch["playerviewswitch"] = true; mControlSwitch["vanitymode"] = true; + + changeInputMode(false); } - void InputManager::destroy() + InputManager::~InputManager() { mInputCtrl->save (mUserFile); @@ -152,11 +146,6 @@ namespace MWInput OIS::InputManager::destroyInputSystem(mInputManager); } - InputManager::~InputManager() - { - destroy(); - } - void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue) { if (mDragDrop) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 7be35ee0b..3be669621 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -153,10 +153,6 @@ namespace MWInput std::map mControlSwitch; - public: - virtual void create(); - virtual void destroy(); - private: void adjustMouseRegion(int width, int height); diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index 05229da1d..e6b6e3baa 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -31,6 +31,7 @@ namespace MWRender vp->setShadowsEnabled(false); vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Sky); vp->setMaterialScheme("water_reflection"); + vp->setBackgroundColour (Ogre::ColourValue(0.0078, 0.0576, 0.150)); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); } @@ -66,11 +67,6 @@ namespace MWRender mNearClipPlaneUnderwater = Ogre::Plane( Ogre::Vector3(0,1,0), height - 5); } - void Refraction::setViewportBackground (Ogre::ColourValue colour) - { - mRenderTarget->getViewport (0)->setBackgroundColour (colour); - } - void Refraction::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) { // We don't want the sky to get clipped by custom near clip plane (the water plane) diff --git a/apps/openmw/mwrender/refraction.hpp b/apps/openmw/mwrender/refraction.hpp index 6b3c487c1..de47d6e43 100644 --- a/apps/openmw/mwrender/refraction.hpp +++ b/apps/openmw/mwrender/refraction.hpp @@ -24,7 +24,6 @@ namespace MWRender void setHeight (float height); void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); - void setViewportBackground(Ogre::ColourValue colour); void setUnderwater(bool underwater) {mIsUnderwater = underwater;} void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index afbdbb06f..ce48284e0 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -46,8 +46,12 @@ namespace MWRender { RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine) - : mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine), - mRecreateWindowInNextFrame(false) + : mRendering(_rend) + , mObjects(mRendering) + , mActors(mRendering) + , mAmbientMode(0) + , mSunEnabled(0) + , mPhysicsEngine(engine) { // select best shader mode bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos); @@ -324,33 +328,6 @@ RenderingManager::moveObjectToCell( void RenderingManager::update (float duration, bool paused) { - if (mRecreateWindowInNextFrame) - { - mRecreateWindowInNextFrame = false; - - mRendering.removeWindowEventListener(this); - mRendering.getWindow()->removeListener(this); - MWBase::Environment::get().getInputManager()->destroy(); - - OEngine::Render::WindowSettings windowSettings; - windowSettings.fullscreen = Settings::Manager::getBool("fullscreen", "Video"); - windowSettings.window_x = Settings::Manager::getInt("resolution x", "Video"); - windowSettings.window_y = Settings::Manager::getInt("resolution y", "Video"); - windowSettings.vsync = Settings::Manager::getBool("vsync", "Video"); - std::string aa = Settings::Manager::getString("antialiasing", "Video"); - windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0"; - mRendering.recreateWindow("OpenMW", windowSettings); - - MWBase::Environment::get().getInputManager()->create(); - mRendering.setWindowEventListener (this); - mRendering.getWindow()->addListener(this); - - // this is necessary, otherwise it would just endlessly wait for the last query and it would never return - delete mOcclusionQuery; - mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); - } - - Ogre::Vector3 orig, dest; mPlayer->setCameraDistance(); if (!mPlayer->getPosition(orig, dest)) { @@ -784,7 +761,6 @@ Compositors* RenderingManager::getCompositors() void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) { bool changeRes = false; - bool recreateWindow = false; bool rebuild = false; // rebuild static geometry (necessary after any material changes) for (Settings::CategorySettingVector::const_iterator it=settings.begin(); it != settings.end(); ++it) @@ -803,8 +779,6 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec || it->second == "resolution y" || it->second == "fullscreen")) changeRes = true; - else if (it->first == "Video" && it->second == "vsync") - recreateWindow = true; else if (it->second == "field of view" && it->first == "General") mRendering.setFov(Settings::Manager::getFloat("field of view", "General")); else if ((it->second == "texture filtering" && it->first == "General") @@ -876,13 +850,6 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } - if (recreateWindow) - { - mRecreateWindowInNextFrame = true; - // We can not do this now, because this might get triggered from the input listener - // and destroying/recreating the input system at that point would cause a crash - } - if (mWater) mWater->processChangedSettings(settings); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 670f3dc85..71ac742c2 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -260,8 +260,6 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList MWRender::Compositors* mCompositors; VideoPlayer* mVideoPlayer; - - bool mRecreateWindowInNextFrame; }; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index f31dca08c..3b8705ac5 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -380,8 +380,6 @@ void Water::setViewportBackground(const ColourValue& bg) { if (mReflection) mReflection->setViewportBackground(bg); - if (mRefraction) - mRefraction->setViewportBackground(bg); } void Water::updateVisible() From 5d1bede9e50c13d72f548f23d3b5e8da60b79119 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Thu, 14 Feb 2013 11:20:47 +0100 Subject: [PATCH 037/151] Forgot to add two files --- apps/launcher/utils/comboboxlineedit.cpp | 35 ++++++++++++++++++++++++ apps/launcher/utils/comboboxlineedit.hpp | 35 ++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 apps/launcher/utils/comboboxlineedit.cpp create mode 100644 apps/launcher/utils/comboboxlineedit.hpp diff --git a/apps/launcher/utils/comboboxlineedit.cpp b/apps/launcher/utils/comboboxlineedit.cpp new file mode 100644 index 000000000..4d62e1399 --- /dev/null +++ b/apps/launcher/utils/comboboxlineedit.cpp @@ -0,0 +1,35 @@ +#include +#include + +#include "comboboxlineedit.hpp" + +ComboBoxLineEdit::ComboBoxLineEdit(QWidget *parent) + : QLineEdit(parent) +{ + mClearButton = new QToolButton(this); + QPixmap pixmap(":images/clear.png"); + mClearButton->setIcon(QIcon(pixmap)); + mClearButton->setIconSize(pixmap.size()); + mClearButton->setCursor(Qt::ArrowCursor); + mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); + mClearButton->hide(); + connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear())); + connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateClearButton(const QString&))); + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + + setObjectName(QString("ComboBoxLineEdit")); + setStyleSheet(QString("ComboBoxLineEdit { background-color: transparent; padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); +} + +void ComboBoxLineEdit::resizeEvent(QResizeEvent *) +{ + QSize sz = mClearButton->sizeHint(); + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + mClearButton->move(rect().right() - frameWidth - sz.width(), + (rect().bottom() + 1 - sz.height())/2); +} + +void ComboBoxLineEdit::updateClearButton(const QString& text) +{ + mClearButton->setVisible(!text.isEmpty()); +} diff --git a/apps/launcher/utils/comboboxlineedit.hpp b/apps/launcher/utils/comboboxlineedit.hpp new file mode 100644 index 000000000..ba10731ae --- /dev/null +++ b/apps/launcher/utils/comboboxlineedit.hpp @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (c) 2007 Trolltech ASA +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#ifndef LINEEDIT_H +#define LINEEDIT_H + +#include + +class QToolButton; + +class ComboBoxLineEdit : public QLineEdit +{ + Q_OBJECT + +public: + ComboBoxLineEdit(QWidget *parent = 0); + +protected: + void resizeEvent(QResizeEvent *); + +private slots: + void updateClearButton(const QString &text); + +private: + QToolButton *mClearButton; +}; + +#endif // LIENEDIT_H + From 492e0f2ccfbf9b069346e738f9145359a036335e Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Feb 2013 19:45:07 +0100 Subject: [PATCH 038/151] Switched objects shaders to vertex lighting, to accomodate badly placed lights in morrowind. Fixed a very obvious land <-> water seam. --- files/materials/objects.shader | 83 +++++++++++++++++++++++++++++++--- files/materials/terrain.shader | 13 ++---- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 1e9c4a334..af596b779 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -22,6 +22,8 @@ #define HAS_VERTEXCOLOR @shPropertyBool(has_vertex_colour) +#define VERTEX_LIGHTING 1 + #ifdef SH_VERTEX_SHADER // ------------------------------------- VERTEX --------------------------------------- @@ -42,8 +44,24 @@ #if HAS_VERTEXCOLOR shColourInput(float4) +#if !VERTEX_LIGHTING shOutput(float4, colourPassthrough) #endif +#endif + +#if VERTEX_LIGHTING + shUniform(float, lightCount) @shAutoConstant(lightCount, light_count) + shUniform(float4, lightPosition[8]) @shAutoConstant(lightPosition, light_position_object_space_array, 8) + shUniform(float4, lightDiffuse[8]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, 8) + shUniform(float4, lightAttenuation[8]) @shAutoConstant(lightAttenuation, light_attenuation_array, 8) + shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) +#if !HAS_VERTEXCOLOUR + shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour) +#endif + shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) + shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) + +#endif #if SHADOWS shOutput(float4, lightSpacePos0) @@ -58,6 +76,11 @@ @shEndForeach shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) #endif + +#if VERTEX_LIGHTING + shOutput(float3, lightResult) + shOutput(float3, directionalResult) +#endif SH_START_PROGRAM { shOutputPosition = shMatrixMult(wvp, shInputPosition); @@ -74,7 +97,7 @@ objSpacePositionPassthrough = shInputPosition.xyz; #endif -#if HAS_VERTEXCOLOR +#if HAS_VERTEXCOLOR && !VERTEX_LIGHTING colourPassthrough = colour; #endif @@ -86,6 +109,36 @@ @shForeach(3) lightSpacePos@shIterator = shMatrixMult(texViewProjMatrix@shIterator, wPos); @shEndForeach +#endif + + +#if VERTEX_LIGHTING + float3 lightDir; + float d; + + @shForeach(@shGlobalSettingString(num_lights)) + lightDir = lightPosition[@shIterator].xyz - (shInputPosition.xyz * lightPosition[@shIterator].w); + d = length(lightDir); + lightDir = normalize(lightDir); + + lightResult += materialDiffuse.xyz * lightDiffuse[@shIterator].xyz + * (1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) + * max(dot(normalize(normal.xyz), normalize(lightDir)), 0); + +#if @shIterator == 0 + directionalResult = lightResult; +#endif + + @shEndForeach + +#if HAS_VERTEXCOLOR + // ambient vertex colour tracking, FFP behaviour + lightResult += lightAmbient.xyz * colour.xyz + materialEmissive.xyz; + +#else + lightResult += lightAmbient.xyz * materialAmbient.xyz + materialEmissive.xyz; +#endif + #endif } @@ -115,25 +168,29 @@ #if LIGHTING shInput(float3, normalPassthrough) shInput(float3, objSpacePositionPassthrough) - shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) #if !HAS_VERTEXCOLOR shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour) #endif shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) + shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) +#if !VERTEX_LIGHTING + @shForeach(@shGlobalSettingString(num_lights)) shUniform(float4, lightPosObjSpace@shIterator) @shAutoConstant(lightPosObjSpace@shIterator, light_position_object_space, @shIterator) shUniform(float4, lightAttenuation@shIterator) @shAutoConstant(lightAttenuation@shIterator, light_attenuation, @shIterator) shUniform(float4, lightDiffuse@shIterator) @shAutoConstant(lightDiffuse@shIterator, light_diffuse_colour, @shIterator) @shEndForeach #endif + +#endif #if FOG shUniform(float3, fogColour) @shAutoConstant(fogColour, fog_colour) shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) #endif -#if HAS_VERTEXCOLOR +#if HAS_VERTEXCOLOR && !VERTEX_LIGHTING shInput(float4, colourPassthrough) #endif @@ -175,6 +232,11 @@ shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) #endif +#if VERTEX_LIGHTING + shInput(float3, lightResult) + shInput(float3, directionalResult) +#endif + SH_START_PROGRAM { shOutputColour(0) = shSample(diffuseMap, UV); @@ -187,9 +249,9 @@ #if HAS_VERTEXCOLOR // ambient vertex colour tracking, FFP behaviour - float3 ambient = colourPassthrough.xyz * lightAmbient.xyz; + //float3 ambient = colourPassthrough.xyz * lightAmbient.xyz; #else - float3 ambient = materialAmbient.xyz * lightAmbient.xyz; + //float3 ambient = materialAmbient.xyz * lightAmbient.xyz; #endif // shadows only for the first (directional) light @@ -228,6 +290,7 @@ caustics = float3(1,1,1); #endif +#if !VERTEX_LIGHTING @shForeach(@shGlobalSettingString(num_lights)) @@ -253,9 +316,16 @@ @shEndForeach - shOutputColour(0).xyz *= (ambient + diffuse + materialEmissive.xyz); + lightResult = (ambient + diffuse + materialEmissive.xyz); #endif +#if SHADOWS + shOutputColour(0).xyz *= (lightResult - directionalResult * (1.0-shadow)); +#else + shOutputColour(0).xyz *= (lightResult); +#endif + +#endif // IF LIGHTING #if HAS_VERTEXCOLOR && !LIGHTING shOutputColour(0).xyz *= colourPassthrough.xyz; @@ -303,7 +373,6 @@ #if MRT shOutputColour(1) = float4(depthPassthrough / far,1,1,1); #endif - } #endif diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 9b891e1e8..d62bb4035 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -32,7 +32,7 @@ @shAllocatePassthrough(2, UV) #if LIGHTING -@shAllocatePassthrough(3, objSpacePosition) +@shAllocatePassthrough(3, worldPos) #endif #if SHADOWS @@ -101,7 +101,7 @@ @shPassthroughAssign(UV, uv0); #if LIGHTING - @shPassthroughAssign(objSpacePosition, shInputPosition.xyz); + @shPassthroughAssign(worldPos, worldPos.xyz); #endif #if SHADOWS @@ -162,7 +162,7 @@ #if LIGHTING shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) @shForeach(@shGlobalSettingString(terrain_num_lights)) - shUniform(float4, lightPosObjSpace@shIterator) @shAutoConstant(lightPosObjSpace@shIterator, light_position_object_space, @shIterator) + shUniform(float4, lightPosObjSpace@shIterator) @shAutoConstant(lightPosObjSpace@shIterator, light_position, @shIterator) shUniform(float4, lightAttenuation@shIterator) @shAutoConstant(lightAttenuation@shIterator, light_attenuation, @shIterator) shUniform(float4, lightDiffuse@shIterator) @shAutoConstant(lightDiffuse@shIterator, light_diffuse_colour, @shIterator) @shEndForeach @@ -213,7 +213,7 @@ float2 UV = @shPassthroughReceive(UV); #if LIGHTING - float3 objSpacePosition = @shPassthroughReceive(objSpacePosition); + float3 worldPos = @shPassthroughReceive(worldPos); float3 normal = shSample(normalMap, UV).rgb * 2 - 1; normal = normalize(normal); @@ -222,9 +222,6 @@ float3 caustics = float3(1,1,1); -#if (UNDERWATER) || (FOG) - float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz; -#endif #if UNDERWATER @@ -306,7 +303,7 @@ @shForeach(@shGlobalSettingString(terrain_num_lights)) - lightDir = lightPosObjSpace@shIterator.xyz - (objSpacePosition.xyz * lightPosObjSpace@shIterator.w); + lightDir = lightPosObjSpace@shIterator.xyz - (worldPos.xyz * lightPosObjSpace@shIterator.w); d = length(lightDir); From 7604fb51b66a63a1f9b0256447982b1e65024b81 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Feb 2013 23:17:21 +0100 Subject: [PATCH 039/151] CG no longer listed in the settings if the plugin isn't loaded. --- apps/openmw/mwgui/settingswindow.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 73f2f6c8a..54c2ef197 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -77,6 +78,17 @@ namespace { return (Ogre::Root::getSingleton ().getRenderSystem ()->getName ().find("OpenGL") != std::string::npos) ? "glsl" : "hlsl"; } + + bool cgAvailable () + { + Ogre::Root::PluginInstanceList list = Ogre::Root::getSingleton ().getInstalledPlugins (); + for (Ogre::Root::PluginInstanceList::const_iterator it = list.begin(); it != list.end(); ++it) + { + if ((*it)->getName() == "Cg Program Manager") + return true; + } + return false; + } } namespace MWGui @@ -428,7 +440,7 @@ namespace MWGui { val = hlslGlsl(); } - else + else if (cgAvailable ()) val = "cg"; static_cast(_sender)->setCaption(val); From 1b9cf8c23fbcbc6591bcd45bd29fb6a34f5007c7 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 15 Feb 2013 01:20:48 +0100 Subject: [PATCH 040/151] More work on integrating the settings parser, profiles are handled correctly --- apps/launcher/datafilespage.cpp | 71 +++++++++++++++++---- apps/launcher/settings/launchersettings.cpp | 54 ++++++++++++++++ apps/launcher/settings/launchersettings.hpp | 3 + apps/launcher/settings/settingsbase.hpp | 16 +++-- apps/launcher/utils/profilescombobox.cpp | 28 ++++---- 5 files changed, 140 insertions(+), 32 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 12323b1f1..678f8cc3c 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -293,22 +293,77 @@ void DataFilesPage::setupDataFiles() mPluginsModel->addPlugins(dataLocal); } + QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); + QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + + mProfilesComboBox->addItems(profiles); + + // Add the current profile if empty + if (mProfilesComboBox->findText(profile) == -1) + mProfilesComboBox->addItem(profile); + + if (mProfilesComboBox->findText(QString("Default")) == -1) + mProfilesComboBox->addItem(QString("Default")); + + if (profile.isEmpty()) { + mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(QString("Default"))); + } else { + mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); + } + loadSettings(); } void DataFilesPage::loadSettings() { qDebug() << "load settings"; + QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + + qDebug() << mLauncherSettings.values(QString("Profiles/Default"), Qt::MatchStartsWith); + + + + if (profile.isEmpty()) + return; + + + mMastersModel->uncheckAll(); + mPluginsModel->uncheckAll(); + + QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly); + QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly); + qDebug() << "masters to check " << plugins; + + foreach (const QString &master, masters) { + QModelIndex index = mMastersModel->indexFromItem(mMastersModel->findItem(master)); + if (index.isValid()) + mMastersModel->setCheckState(index, Qt::Checked); + } + + foreach (const QString &plugin, plugins) { + QModelIndex index = mPluginsModel->indexFromItem(mPluginsModel->findItem(plugin)); + if (index.isValid()) + mPluginsModel->setCheckState(index, Qt::Checked); + } } void DataFilesPage::saveSettings() { QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + + if (profile.isEmpty()) { + profile = mProfilesComboBox->currentText(); + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), profile); + } + qDebug() << "save settings" << profile; + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); QStringList items = mMastersModel->checkedItems(); foreach(const QString &master, items) { + qDebug() << "setting " << master; mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), master); } @@ -482,17 +537,11 @@ void DataFilesPage::writeConfig(QString profile) void DataFilesPage::newProfile() { -// if (mNewProfileDialog->exec() == QDialog::Accepted) { - -// const QString text = mNewProfileDialog->lineEdit()->text(); -// mProfilesComboBox->addItem(text); -// mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(text)); -// } - - mDeleteProfileAction->setEnabled(false); - mProfilesComboBox->setCurrentIndex(-1); - mProfilesComboBox->setEditEnabled(true); - mProfilesComboBox->lineEdit()->setFocus(); + if (mNewProfileDialog->exec() == QDialog::Accepted) { + QString profile = mNewProfileDialog->lineEdit()->text(); + mProfilesComboBox->addItem(profile); + mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); + } } void DataFilesPage::updateOkButton(const QString &text) diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index c189c282f..07502ea02 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -13,6 +13,60 @@ LauncherSettings::~LauncherSettings() { } +QStringList LauncherSettings::values(const QString &key, Qt::MatchFlags flags) +{ + QMap settings = SettingsBase::getSettings(); + + if (flags == Qt::MatchExactly) + return settings.values(key); + + QStringList result; + + if (flags == Qt::MatchStartsWith) { + QStringList keys = settings.keys(); + + foreach (const QString ¤tKey, keys) { + qDebug() << "key is: " << currentKey << "value: " << settings.value(currentKey); + if (currentKey.startsWith(key)) + result.append(settings.value(currentKey)); + } + } + + return result; +} + +QStringList LauncherSettings::subKeys(const QString &key) +{ + QMap settings = SettingsBase::getSettings(); + QStringList keys = settings.keys(); + + QRegExp keyRe("(.+)/"); + + QStringList result; + + foreach (const QString ¤tKey, keys) { + qDebug() << "key is: " << currentKey; + if (keyRe.indexIn(currentKey) != -1) { + qDebug() << "text: " << keyRe.cap(1) << keyRe.cap(2); + + QString prefixedKey = keyRe.cap(1); + if(prefixedKey.startsWith(key)) { + + QString subKey = prefixedKey.remove(key); + if (!subKey.isEmpty()) + result.append(subKey); + //qDebug() << keyRe.cap(2).simplified(); + } + } else { + qDebug() << "no match"; + } + } + + result.removeDuplicates(); + qDebug() << result; + + return result; +} bool LauncherSettings::writeFile(QTextStream &stream) { diff --git a/apps/launcher/settings/launchersettings.hpp b/apps/launcher/settings/launchersettings.hpp index cf4dd4c9f..d78a75d45 100644 --- a/apps/launcher/settings/launchersettings.hpp +++ b/apps/launcher/settings/launchersettings.hpp @@ -9,6 +9,9 @@ public: LauncherSettings(); ~LauncherSettings(); + QStringList subKeys(const QString &key); + QStringList values(const QString &key, Qt::MatchFlags flags = Qt::MatchExactly); + bool writeFile(QTextStream &stream); }; diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index e09ea6203..361884da6 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -24,12 +24,20 @@ public: inline void setValue(const QString &key, const QString &value) { - mSettings.insert(key, value); + QStringList values = mSettings.values(key); + if (!values.contains(value)) + mSettings.insert(key, value); } inline void setMultiValue(const QString &key, const QString &value) { - mSettings.insertMulti(key, value); + QStringList values = mSettings.values(key); + if (!values.contains(value)) { + qDebug() << "inserting " << value; + mSettings.insertMulti(key, value); + } else { + qDebug() << "not inserting " << value; + } } @@ -73,13 +81,11 @@ public: QStringList values = mCache.values(key); if (!values.contains(value)) { // QMap will replace the value if key exists, QMultiMap creates a new one - mCache.insert(key, value); + mCache.insertMulti(key, value); } } } - qDebug() << "HI THERE! " << mCache; - if (mSettings.isEmpty()) { mSettings = mCache; // This is the first time we read a file return true; diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index 3a75ba417..a2c8668cb 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "profilescombobox.hpp" #include "comboboxlineedit.hpp" @@ -18,12 +19,11 @@ ProfilesComboBox::ProfilesComboBox(QWidget *parent) : connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(slotIndexChanged(int))); - + setInsertPolicy(QComboBox::NoInsert); } void ProfilesComboBox::setEditEnabled(bool editable) { - qDebug() << "called"; if (isEditable() == editable) return; @@ -50,29 +50,25 @@ void ProfilesComboBox::setEditEnabled(bool editable) void ProfilesComboBox::slotTextChanged(const QString &text) { - QString previous = itemText(currentIndex()); -// lineEdit()->setPalette(QApplication::palette()); + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Text,Qt::red); - if (text.isEmpty()) - return; + int index = findText(text); - if (text == previous) - return; - - qDebug() << "textChanged"; - if (findText(text) != -1) { - QPalette *palette = new QPalette(); - palette->setColor(QPalette::Text,Qt::red); + if (text.isEmpty() || (index != -1 && index != currentIndex())) { lineEdit()->setPalette(*palette); + } else { + lineEdit()->setPalette(QApplication::palette()); } } void ProfilesComboBox::slotEditingFinished() { - qDebug() << "returnpressed"; QString current = currentText(); QString previous = itemText(currentIndex()); + qDebug() << current << previous; + if (current.isEmpty()) return; @@ -82,9 +78,9 @@ void ProfilesComboBox::slotEditingFinished() if (findText(current) != -1) return; - if (currentIndex() == -1) { - addItem(currentText()); + addItem(current); + setCurrentIndex(findText(current)); } else { setItemText(currentIndex(), current); emit(profileRenamed(previous, current)); From 990895fd2b9aab702c79a8e48fba2b6b6e3cf1c3 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 15 Feb 2013 14:12:25 +0100 Subject: [PATCH 041/151] Mainwindow size and position now gets saved/restored --- apps/launcher/maindialog.cpp | 14 ++++++++++++++ apps/launcher/utils/profilescombobox.cpp | 12 +++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index f48ea603b..7b453671c 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -169,6 +169,7 @@ bool MainDialog::setup() return false; } + loadSettings(); return true; } @@ -182,7 +183,14 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) void MainDialog::loadSettings() { + int width = mLauncherSettings.value(QString("General/MainWindow/width")).toInt(); + int height = mLauncherSettings.value(QString("General/MainWindow/height")).toInt(); + int posX = mLauncherSettings.value(QString("General/MainWindow/posx")).toInt(); + int posY = mLauncherSettings.value(QString("General/MainWindow/posy")).toInt(); + + resize(width, height); + move(posX, posY); } void MainDialog::saveSettings() @@ -193,6 +201,12 @@ void MainDialog::saveSettings() mLauncherSettings.setValue(QString("General/MainWindow/width"), width); mLauncherSettings.setValue(QString("General/MainWindow/height"), height); + QString posX = QString::number(this->pos().x()); + QString posY = QString::number(this->pos().y()); + + mLauncherSettings.setValue(QString("General/MainWindow/posx"), posX); + mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY); + qDebug() << "size: " << width << height; } diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index a2c8668cb..4c258dae6 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -69,6 +69,9 @@ void ProfilesComboBox::slotEditingFinished() qDebug() << current << previous; + if (currentIndex() == -1) + return; + if (current.isEmpty()) return; @@ -78,13 +81,8 @@ void ProfilesComboBox::slotEditingFinished() if (findText(current) != -1) return; - if (currentIndex() == -1) { - addItem(current); - setCurrentIndex(findText(current)); - } else { - setItemText(currentIndex(), current); - emit(profileRenamed(previous, current)); - } + setItemText(currentIndex(), current); + emit(profileRenamed(previous, current)); } void ProfilesComboBox::slotIndexChanged(int index) From 43e9ad87331d073d69c5d571acad50020263f849 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 15 Feb 2013 14:26:09 +0100 Subject: [PATCH 042/151] The text color of the profiles dialog now turns red on invalid names --- apps/launcher/utils/textinputdialog.cpp | 46 ++++++++++++++++--------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/apps/launcher/utils/textinputdialog.cpp b/apps/launcher/utils/textinputdialog.cpp index 16cadb661..ec72e5432 100644 --- a/apps/launcher/utils/textinputdialog.cpp +++ b/apps/launcher/utils/textinputdialog.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -17,9 +18,19 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid mButtonBox->addButton(QDialogButtonBox::Ok); mButtonBox->addButton(QDialogButtonBox::Cancel); - setMaximumHeight(height()); - setOkButtonEnabled(false); - setModal(true); + // Line edit + QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore + mLineEdit = new LineEdit(this); + mLineEdit->setValidator(validator); + mLineEdit->setCompleter(0); + + QLabel *label = new QLabel(this); + label->setText(text); + + QVBoxLayout *dialogLayout = new QVBoxLayout(this); + dialogLayout->addWidget(label); + dialogLayout->addWidget(mLineEdit); + dialogLayout->addWidget(mButtonBox); // Messageboxes on mac have no title #ifndef Q_OS_MAC @@ -28,22 +39,13 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid Q_UNUSED(title); #endif - QLabel *label = new QLabel(this); - label->setText(text); - - // Line edit - QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore - mLineEdit = new LineEdit(this); - mLineEdit->setValidator(validator); - mLineEdit->setCompleter(0); - - QVBoxLayout *dialogLayout = new QVBoxLayout(this); - dialogLayout->addWidget(label); - dialogLayout->addWidget(mLineEdit); - dialogLayout->addWidget(mButtonBox); + setMaximumHeight(height()); + setOkButtonEnabled(false); + setModal(true); connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject())); + } int TextInputDialog::exec() @@ -55,7 +57,17 @@ int TextInputDialog::exec() void TextInputDialog::setOkButtonEnabled(bool enabled) { - QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok); okButton->setEnabled(enabled); + + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Text,Qt::red); + + if (enabled) { + mLineEdit->setPalette(QApplication::palette()); + } else { + // Existing profile name, make the text red + mLineEdit->setPalette(*palette); + } + } From 7ffcfa36220cd3a53e168e12abab8b0afdeb6b8d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 16:23:55 +0100 Subject: [PATCH 043/151] Water and clouds no longer depend on timescale. --- apps/openmw/mwrender/renderingmanager.cpp | 2 -- apps/openmw/mwrender/sky.cpp | 2 +- apps/openmw/mwrender/water.cpp | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ce48284e0..fe8f3e99b 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -353,8 +353,6 @@ void RenderingManager::update (float duration, bool paused) Ogre::ControllerManager::getSingleton().setTimeFactor(0.f); return; } - Ogre::ControllerManager::getSingleton().setTimeFactor( - MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f); mPlayer->update(duration); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index ce8d82632..be989724a 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -361,7 +361,7 @@ void SkyManager::update(float duration) mRootNode->setPosition(mCamera->getDerivedPosition()); // UV Scroll the clouds - mCloudAnimationTimer += duration * mCloudSpeed * (MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f); + mCloudAnimationTimer += duration * mCloudSpeed; sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer", sh::makeProperty(new sh::FloatValue(mCloudAnimationTimer))); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 3b8705ac5..33159024e 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -399,7 +399,7 @@ void Water::update(float dt, Ogre::Vector3 player) mUnderwaterDome->setPosition (pos); */ - mWaterTimer += dt / 30.0 * MWBase::Environment::get().getWorld()->getTimeScaleFactor(); + mWaterTimer += dt; sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(mWaterTimer))); mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); From 791d16bbdb6ff95c1b4be0adfe04ab945601e4b4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 Feb 2013 18:12:38 +0100 Subject: [PATCH 044/151] Use infinite AAB for sky meshes to fix them from disappearing from underwater refraction, while still taking advantage of CPU culling for other meshes --- apps/openmw/mwrender/refraction.cpp | 4 ++++ apps/openmw/mwrender/sky.cpp | 6 ++++++ apps/openmw/mwrender/water.cpp | 4 +++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index e6b6e3baa..a924be7d7 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -41,6 +41,7 @@ namespace MWRender mRenderTarget->removeListener(this); Ogre::TextureManager::getSingleton().remove("WaterRefraction"); mParentCamera->getSceneManager()->destroyCamera(mCamera); + mParentCamera->getSceneManager()->removeRenderQueueListener(this); } void Refraction::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) @@ -53,6 +54,9 @@ namespace MWRender mCamera->setAspectRatio(mParentCamera->getAspectRatio()); mCamera->setFOVy(mParentCamera->getFOVy()); + // enable clip plane here to take advantage of CPU culling for overwater or underwater objects + mCamera->enableCustomNearClipPlane(mIsUnderwater ? mNearClipPlaneUnderwater : mNearClipPlane); + mRenderActive = true; } diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index be989724a..3b02ca412 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -280,6 +280,9 @@ void SkyManager::create() mSunGlare->setRenderQueue(RQG_SkiesLate); mSunGlare->setVisibilityFlags(RV_NoReflection); + Ogre::AxisAlignedBox aabInf; + aabInf.setInfinite (); + // Stars mAtmosphereNight = mRootNode->createChildSceneNode(); NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mAtmosphereNight, NULL, "meshes\\sky_night_01.nif"); @@ -289,6 +292,7 @@ void SkyManager::create() night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); night1_ent->setVisibilityFlags(RV_Sky); night1_ent->setCastShadows(false); + night1_ent->getMesh()->_setBounds (aabInf); for (unsigned int j=0; jgetNumSubEntities(); ++j) { @@ -315,6 +319,7 @@ void SkyManager::create() atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly); atmosphere_ent->setVisibilityFlags(RV_Sky); atmosphere_ent->getSubEntity (0)->setMaterialName ("openmw_atmosphere"); + atmosphere_ent->getMesh()->_setBounds (aabInf); } @@ -328,6 +333,7 @@ void SkyManager::create() clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); clouds_ent->getSubEntity(0)->setMaterialName ("openmw_clouds"); clouds_ent->setCastShadows(false); + clouds_ent->getMesh()->_setBounds (aabInf); } mCreated = true; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 33159024e..b006059a9 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -124,7 +124,6 @@ void PlaneReflection::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::St { if (queueGroupId < 20 && mRenderActive) { - // this trick does not seem to work well for extreme angles mCamera->enableCustomNearClipPlane(mIsUnderwater ? mErrorPlaneUnderwater : mErrorPlane); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); } @@ -145,6 +144,9 @@ void PlaneReflection::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) pos.y = (mWaterPlane).d*2 - pos.y; mSky->setSkyPosition(pos); mCamera->enableReflection(mWaterPlane); + + // enable clip plane here to take advantage of CPU culling for overwater or underwater objects + mCamera->enableCustomNearClipPlane(mIsUnderwater ? mErrorPlaneUnderwater : mErrorPlane); } void PlaneReflection::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) From 42883ec64bdfbabb32735757230ad79790bc4ed7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 18 Feb 2013 02:33:53 +0100 Subject: [PATCH 045/151] cleanup --- apps/openmw/engine.cpp | 1 - apps/openmw/mwrender/localmap.cpp | 2 - apps/openmw/mwrender/renderingmanager.cpp | 21 ------ apps/openmw/mwrender/renderingmanager.hpp | 2 - apps/openmw/mwrender/water.cpp | 20 ----- apps/openmw/mwrender/water.hpp | 2 - files/CMakeLists.txt | 7 -- files/gbuffer/gbuffer.compositor | 91 ----------------------- files/materials/atmosphere.shader | 9 --- files/materials/clouds.shader | 9 --- files/materials/moon.shader | 10 --- files/materials/objects.shader | 20 +---- files/materials/openmw.configuration | 2 - files/materials/quad.mat | 13 ---- files/materials/quad.shaderset | 16 ---- files/materials/quad2.shader | 23 ------ files/materials/stars.shader | 10 --- files/materials/sun.shader | 10 --- files/materials/terrain.shader | 12 +-- files/materials/water.shader | 13 +--- 20 files changed, 6 insertions(+), 287 deletions(-) delete mode 100644 files/gbuffer/gbuffer.compositor delete mode 100644 files/materials/quad2.shader diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 340e1d381..d65a5a78c 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -319,7 +319,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) addResourcesDirectory(mResDir / "mygui"); addResourcesDirectory(mResDir / "water"); - addResourcesDirectory(mResDir / "gbuffer"); addResourcesDirectory(mResDir / "shadows"); addZipResource(mResDir / "mygui" / "Obliviontt.zip"); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index e0b7d9a11..de36dcbbf 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -236,8 +236,6 @@ void LocalMap::render(const float x, const float y, vp->setShadowsEnabled(false); vp->setBackgroundColour(ColourValue(0, 0, 0)); vp->setVisibilityMask(RV_Map); - - // use fallback techniques without shadows and without mrt vp->setMaterialScheme("local_map"); rtt->update(); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index fe8f3e99b..6c6c47417 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -126,7 +126,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); - sh::Factory::getInstance ().setGlobalSetting ("mrt_output", useMRT() ? "true" : "false"); sh::Factory::getInstance ().setGlobalSetting ("fog", "true"); sh::Factory::getInstance ().setGlobalSetting ("lighting", "true"); sh::Factory::getInstance ().setGlobalSetting ("num_lights", Settings::Manager::getString ("num lights", "Objects")); @@ -690,11 +689,6 @@ void RenderingManager::enableLights(bool sun) sunEnable(sun); } -const bool RenderingManager::useMRT() -{ - return Settings::Manager::getBool("shader", "Water"); -} - Shadows* RenderingManager::getShadows() { return mShadows; @@ -795,7 +789,6 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec else if (it->second == "shader" && it->first == "Water") { applyCompositors(); - sh::Factory::getInstance ().setGlobalSetting ("mrt_output", useMRT() ? "true" : "false"); sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true"); rebuild = true; mRendering.getViewport ()->setClearEveryFrame (true); @@ -873,7 +866,6 @@ void RenderingManager::windowResized(Ogre::RenderWindow* rw) mRendering.adjustViewport(); mCompositors->recreate(); - mWater->assignTextures(); mVideoPlayer->setResolution (rw->getWidth(), rw->getHeight()); @@ -897,19 +889,6 @@ bool RenderingManager::waterShaderSupported() void RenderingManager::applyCompositors() { - mCompositors->removeAll(); - if (useMRT()) - { - /* - mCompositors->addCompositor("gbuffer", 0); - mCompositors->setCompositorEnabled("gbuffer", true); - mCompositors->addCompositor("gbufferFinalizer", 2); - mCompositors->setCompositorEnabled("gbufferFinalizer", true); - */ - } - - //if (mWater) - //mWater->assignTextures(); } void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned int &batches) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 71ac742c2..e42c6e06f 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -104,8 +104,6 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void removeWater(); - static const bool useMRT(); - void preCellChange (MWWorld::CellStore* store); ///< this event is fired immediately before changing cell diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index b006059a9..f71431a27 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -93,7 +93,6 @@ PlaneReflection::PlaneReflection(Ogre::SceneManager* sceneManager, SkyManager* s vp->setOverlaysEnabled(false); vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); vp->setShadowsEnabled(false); - // use fallback techniques without shadows and without mrt vp->setMaterialScheme("water_reflection"); mRenderTarget->addListener(this); mRenderTarget->setActive(true); @@ -232,8 +231,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel underwaterDome->setMaterialName("Underwater_Dome"); */ - assignTextures(); - setHeight(mTop); sh::MaterialInstance* m = sh::Factory::getInstance ().getMaterialInstance ("Water"); @@ -362,22 +359,6 @@ Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY) return Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), mTop, -gridY * CELL_SIZE - (CELL_SIZE / 2)); } -void Water::assignTextures() -{ - if (Settings::Manager::getBool("shader", "Water")) - { -/* - CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer"); - - TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0); - sh::Factory::getInstance ().setTextureAlias ("WaterRefraction", colorTexture->getName()); - - TexturePtr depthTexture = compositor->getTextureInstance("mrt_output", 1); - sh::Factory::getInstance ().setTextureAlias ("SceneDepth", depthTexture->getName()); - */ - } -} - void Water::setViewportBackground(const ColourValue& bg) { if (mReflection) @@ -483,7 +464,6 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin applyRTT(); applyVisibilityMask(); mWater->setMaterial(mMaterial); - assignTextures(); } if (applyVisMask) applyVisibilityMask(); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 9aa18f008..6100b7cfd 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -146,8 +146,6 @@ namespace MWRender { void toggle(); void update(float dt, Ogre::Vector3 player); - void assignTextures(); - void setViewportBackground(const Ogre::ColourValue& bg); void processChangedSettings(const Settings::CategorySettingVector& settings); diff --git a/files/CMakeLists.txt b/files/CMakeLists.txt index 65ebc31a2..c29d917b8 100644 --- a/files/CMakeLists.txt +++ b/files/CMakeLists.txt @@ -6,10 +6,6 @@ set(WATER_FILES circle.png ) -set(GBUFFER_FILES - gbuffer.compositor -) - set(MATERIAL_FILES atmosphere.shader atmosphere.shaderset @@ -22,7 +18,6 @@ set(MATERIAL_FILES objects.shader objects.shaderset openmw.configuration - quad2.shader quad.mat quad.shader quad.shaderset @@ -54,6 +49,4 @@ set(MATERIAL_FILES copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}") -copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer "${OpenMW_BINARY_DIR}/resources/gbuffer/" "${GBUFFER_FILES}") - copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/materials "${OpenMW_BINARY_DIR}/resources/materials/" "${MATERIAL_FILES}") diff --git a/files/gbuffer/gbuffer.compositor b/files/gbuffer/gbuffer.compositor deleted file mode 100644 index 0a0675fa0..000000000 --- a/files/gbuffer/gbuffer.compositor +++ /dev/null @@ -1,91 +0,0 @@ -// Compositor that just controls output to the MRT textures -compositor gbuffer -{ - technique - { - // MRT output. Currently this is a color texture plus a depth texture - texture mrt_output target_width target_height PF_FLOAT16_RGBA PF_FLOAT16_RGBA chain_scope depth_pool 2 - - target mrt_output - { - input none - - pass clear - { - colour_value 0 0 0 1 - } - pass render_quad - { - // this makes sure the depth for background is set to 1 - material openmw_viewport_init - } - pass render_scene - { - // Renders everything except water - first_render_queue 0 - last_render_queue 50 - } - - } - - target_output - { - input none - - pass render_quad - { - material quad - input 0 mrt_output 0 - } - } - } -} - -// Finalizer compositor to render objects that we don't want in the MRT textures (ex. water) -// NB the water has to be rendered in a seperate compositor anyway, because it -// accesses the MRT textures which can't be done while they are still being rendered to. -compositor gbufferFinalizer -{ - technique - { - texture no_mrt_output target_width target_height PF_R8G8B8A8 depth_pool 2 no_fsaa - texture previousscene target_width target_height PF_R8G8B8A8 - - target previousscene - { - input previous - } - target no_mrt_output - { - input none - shadows off - pass clear - { - buffers colour - colour_value 0 0 0 0 - } - pass render_quad - { - material quad_noDepthWrite - input 0 previousscene - } - pass render_scene - { - first_render_queue 51 - last_render_queue 105 - } - } - target_output - { - input none - pass clear - { - } - pass render_quad - { - material quad_noDepthWrite - input 0 no_mrt_output - } - } - } -} diff --git a/files/materials/atmosphere.shader b/files/materials/atmosphere.shader index 16edc78c5..5d71d7c32 100644 --- a/files/materials/atmosphere.shader +++ b/files/materials/atmosphere.shader @@ -1,7 +1,5 @@ #include "core.h" -#define MRT @shGlobalSettingBool(mrt_output) - #ifdef SH_VERTEX_SHADER SH_BEGIN_PROGRAM @@ -19,18 +17,11 @@ SH_BEGIN_PROGRAM shInput(float, alphaFade) -#if MRT - shDeclareMrtOutput(1) -#endif shUniform(float4, atmosphereColour) @shSharedParameter(atmosphereColour) SH_START_PROGRAM { shOutputColour(0) = atmosphereColour * float4(1,1,1,alphaFade); - -#if MRT - shOutputColour(1) = float4(1,1,1,1); -#endif } #endif diff --git a/files/materials/clouds.shader b/files/materials/clouds.shader index 4b1868fb4..e60026d3b 100644 --- a/files/materials/clouds.shader +++ b/files/materials/clouds.shader @@ -1,7 +1,5 @@ #include "core.h" -#define MRT @shGlobalSettingBool(mrt_output) - #ifdef SH_VERTEX_SHADER SH_BEGIN_PROGRAM @@ -22,9 +20,6 @@ SH_BEGIN_PROGRAM shInput(float2, UV) shInput(float, alphaFade) -#if MRT - shDeclareMrtOutput(1) -#endif shSampler2D(diffuseMap1) shSampler2D(diffuseMap2) @@ -42,10 +37,6 @@ float4 albedo = shSample(diffuseMap1, scrolledUV) * (1-cloudBlendFactor) + shSample(diffuseMap2, scrolledUV) * cloudBlendFactor; shOutputColour(0) = float4(cloudColour, 1) * albedo * float4(1,1,1, cloudOpacity * alphaFade); - -#if MRT - shOutputColour(1) = float4(1,1,1,1); -#endif } #endif diff --git a/files/materials/moon.shader b/files/materials/moon.shader index 02f3d8001..231f60ba0 100644 --- a/files/materials/moon.shader +++ b/files/materials/moon.shader @@ -1,8 +1,5 @@ #include "core.h" -#define MRT @shGlobalSettingBool(mrt_output) - - #ifdef SH_VERTEX_SHADER SH_BEGIN_PROGRAM @@ -22,9 +19,6 @@ shSampler2D(diffuseMap) shSampler2D(alphaMap) shInput(float2, UV) -#if MRT - shDeclareMrtOutput(1) -#endif shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) @@ -42,10 +36,6 @@ shOutputColour(0).rgb += (1-tex.a) * shOutputColour(0).a * atmosphereColour.rgb; //fill dark side of moon with atmosphereColour shOutputColour(0).rgb += (1-materialDiffuse.a) * atmosphereColour.rgb; //fade bump -#if MRT - shOutputColour(1) = float4(1,1,1,1); -#endif - } #endif diff --git a/files/materials/objects.shader b/files/materials/objects.shader index af596b779..3f5aa418f 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -2,7 +2,6 @@ #define FOG @shGlobalSettingBool(fog) -#define MRT @shPropertyNotBool(is_transparent) && @shGlobalSettingBool(mrt_output) #define LIGHTING @shGlobalSettingBool(lighting) #define SHADOWS_PSSM LIGHTING && @shGlobalSettingBool(shadows_pssm) @@ -12,7 +11,7 @@ #include "shadows.h" #endif -#if FOG || MRT || SHADOWS_PSSM +#if FOG || SHADOWS_PSSM #define NEED_DEPTH #endif @@ -51,9 +50,9 @@ #if VERTEX_LIGHTING shUniform(float, lightCount) @shAutoConstant(lightCount, light_count) - shUniform(float4, lightPosition[8]) @shAutoConstant(lightPosition, light_position_object_space_array, 8) - shUniform(float4, lightDiffuse[8]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, 8) - shUniform(float4, lightAttenuation[8]) @shAutoConstant(lightAttenuation, light_attenuation_array, 8) + shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_object_space_array, @shGlobalSettingString(num_lights)) + shUniform(float4, lightDiffuse[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, @shGlobalSettingString(num_lights)) + shUniform(float4, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) #if !HAS_VERTEXCOLOUR shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour) @@ -153,18 +152,11 @@ SH_BEGIN_PROGRAM shSampler2D(diffuseMap) shInput(float2, UV) -#if MRT - shDeclareMrtOutput(1) -#endif #ifdef NEED_DEPTH shInput(float, depthPassthrough) #endif -#if MRT - shUniform(float, far) @shAutoConstant(far, far_clip_distance) -#endif - #if LIGHTING shInput(float3, normalPassthrough) shInput(float3, objSpacePositionPassthrough) @@ -369,10 +361,6 @@ float isUnderwater = (worldPos.y < waterLevel) ? 1.0 : 0.0; shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater * waterEnabled); #endif - -#if MRT - shOutputColour(1) = float4(depthPassthrough / far,1,1,1); -#endif } #endif diff --git a/files/materials/openmw.configuration b/files/materials/openmw.configuration index db3693dd6..870c96728 100644 --- a/files/materials/openmw.configuration +++ b/files/materials/openmw.configuration @@ -3,13 +3,11 @@ configuration water_reflection fog false shadows false shadows_pssm false - mrt_output false } configuration local_map { fog false - mrt_output false shadows false shadows_pssm false simple_water true diff --git a/files/materials/quad.mat b/files/materials/quad.mat index a484d7f28..77a2c0c34 100644 --- a/files/materials/quad.mat +++ b/files/materials/quad.mat @@ -20,16 +20,3 @@ material quad_noDepthWrite parent quad depth_write off } - -material openmw_viewport_init -{ - pass - { - vertex_program viewport_init_vertex - fragment_program viewport_init_fragment - - depth_write off - depth_check off - scene_blend add - } -} diff --git a/files/materials/quad.shaderset b/files/materials/quad.shaderset index ee230a303..71fd82da4 100644 --- a/files/materials/quad.shaderset +++ b/files/materials/quad.shaderset @@ -13,19 +13,3 @@ shader_set quad_fragment profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1 profiles_hlsl ps_2_0 } - -shader_set viewport_init_vertex -{ - source quad2.shader - type vertex - profiles_cg vs_2_0 vp40 arbvp1 - profiles_hlsl vs_2_0 -} - -shader_set viewport_init_fragment -{ - source quad2.shader - type fragment - profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1 - profiles_hlsl ps_2_0 -} diff --git a/files/materials/quad2.shader b/files/materials/quad2.shader deleted file mode 100644 index e54d83ef4..000000000 --- a/files/materials/quad2.shader +++ /dev/null @@ -1,23 +0,0 @@ -#include "core.h" - -#ifdef SH_VERTEX_SHADER - - SH_BEGIN_PROGRAM - shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) - SH_START_PROGRAM - { - shOutputPosition = shMatrixMult(wvp, shInputPosition); - } - -#else - - SH_BEGIN_PROGRAM - shUniform(float3, viewportBackground) @shSharedParameter(viewportBackground) - shDeclareMrtOutput(1) - SH_START_PROGRAM - { - shOutputColour(0) = float4(viewportBackground, 1); - shOutputColour(1) = float4(1,1,1,1); - } - -#endif diff --git a/files/materials/stars.shader b/files/materials/stars.shader index 5a55d171e..fea007424 100644 --- a/files/materials/stars.shader +++ b/files/materials/stars.shader @@ -1,7 +1,5 @@ #include "core.h" -#define MRT @shGlobalSettingBool(mrt_output) - #ifdef SH_VERTEX_SHADER SH_BEGIN_PROGRAM @@ -22,9 +20,6 @@ #else SH_BEGIN_PROGRAM -#if MRT - shDeclareMrtOutput(1) -#endif shInput(float2, UV) shInput(float, fade) @@ -36,11 +31,6 @@ SH_START_PROGRAM { shOutputColour(0) = shSample(diffuseMap, UV) * float4(1,1,1, nightFade * fade); - - -#if MRT - shOutputColour(1) = float4(1,1,1,1); -#endif } #endif diff --git a/files/materials/sun.shader b/files/materials/sun.shader index 45cd2f24b..7954f417c 100644 --- a/files/materials/sun.shader +++ b/files/materials/sun.shader @@ -1,8 +1,5 @@ #include "core.h" -#define MRT @shGlobalSettingBool(mrt_output) - - #ifdef SH_VERTEX_SHADER SH_BEGIN_PROGRAM @@ -21,19 +18,12 @@ SH_BEGIN_PROGRAM shSampler2D(diffuseMap) shInput(float2, UV) -#if MRT - shDeclareMrtOutput(1) -#endif shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) //shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) SH_START_PROGRAM { shOutputColour(0) = float4(1,1,1,materialDiffuse.a) * shSample(diffuseMap, UV); - -#if MRT - shOutputColour(1) = float4(1,1,1,1); -#endif } #endif diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index d62bb4035..497463f8e 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -3,7 +3,6 @@ #define IS_FIRST_PASS 1 #define FOG @shGlobalSettingBool(fog) -#define MRT @shGlobalSettingBool(mrt_output) #define LIGHTING @shGlobalSettingBool(lighting) @@ -18,7 +17,7 @@ #define NUM_LAYERS @shPropertyString(num_layers) -#if MRT || FOG || SHADOWS_PSSM +#if FOG || SHADOWS_PSSM #define NEED_DEPTH 1 #endif @@ -152,11 +151,6 @@ #endif @shPassthroughFragmentInputs - -#if MRT - shDeclareMrtOutput(1) - shUniform(float, far) @shAutoConstant(far, far_clip_distance) -#endif #if LIGHTING @@ -370,10 +364,6 @@ float isUnderwater = (worldPos.y < waterLevel) ? 1.0 : 0.0; shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); #endif - -#if MRT - shOutputColour(1) = float4(depth / far,1,1,1); -#endif } #endif diff --git a/files/materials/water.shader b/files/materials/water.shader index 400fbefb2..ac6b81240 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -5,11 +5,7 @@ #if SIMPLE_WATER - // --------------------------------------- SIMPLE WATER --------------------------------------------------- - - - #define MRT @shGlobalSettingBool(mrt_output) - + // --------------------------------------- SIMPLE WATER --------------------------------------------------- #ifdef SH_VERTEX_SHADER @@ -32,9 +28,6 @@ shSampler2D(animatedTexture) shInput(float2, UV) shInput(float, depth) -#if MRT - shDeclareMrtOutput(1) -#endif shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour) shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) @@ -47,10 +40,6 @@ float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); - -#if MRT - shOutputColour(1) = float4(1,1,1,1); -#endif } #endif From 178cf2154e1d33d24ddd649387beab13c0696a0d Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 18 Feb 2013 17:59:08 +0100 Subject: [PATCH 046/151] Made checking/unchecking work with the new datafiles model --- apps/launcher/datafilespage.cpp | 333 +++++------------- apps/launcher/datafilespage.hpp | 6 +- apps/launcher/settings/gamesettings.cpp | 2 + .../fileorderlist/model/datafilesmodel.cpp | 9 +- 4 files changed, 95 insertions(+), 255 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index fe6c6f424..ed24f881b 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -56,12 +56,25 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam , QWidget(parent) { // Models - mMastersModel = new DataFilesModel(this); - mPluginsModel = new DataFilesModel(this); + mDataFilesModel = new DataFilesModel(this); + mDataFilesModel->setObjectName(QString("mDataFilesModel")); + + mMastersProxyModel = new QSortFilterProxyModel(); + mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm")); + mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + mMastersProxyModel->setSourceModel(mDataFilesModel); mPluginsProxyModel = new QSortFilterProxyModel(); - mPluginsProxyModel->setDynamicSortFilter(true); - mPluginsProxyModel->setSourceModel(mPluginsModel); + mPluginsProxyModel->setObjectName(QString("mPluginsProxyModel")); + mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp")); + mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + mPluginsProxyModel->setSourceModel(mDataFilesModel); + + mFilterProxyModel = new QSortFilterProxyModel(); + mFilterProxyModel->setObjectName(QString("mFilterProxyModel")); + + mFilterProxyModel->setDynamicSortFilter(true); + mFilterProxyModel->setSourceModel(mPluginsProxyModel); // Filter toolbar QLabel *filterLabel = new QLabel(tr("&Filter:"), this); @@ -86,7 +99,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam unsigned int height = checkBox.sizeHint().height() + 4; mMastersTable = new QTableView(this); - mMastersTable->setModel(mMastersModel); + mMastersTable->setModel(mMastersProxyModel); mMastersTable->setObjectName("MastersTable"); mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection); @@ -109,7 +122,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersTable->setColumnHidden(8, true); mPluginsTable = new QTableView(this); - mPluginsTable->setModel(mPluginsProxyModel); + mPluginsTable->setModel(mFilterProxyModel); mPluginsTable->setObjectName("PluginsTable"); mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -172,7 +185,14 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); + + connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + + connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); + connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); @@ -219,69 +239,20 @@ void DataFilesPage::createActions() mContextMenu->addAction(mUncheckAction); } -void DataFilesPage::readConfig() -{ -// // Don't read the config if no masters are found -// if (mMastersModel->rowCount() < 1) -// return; - -// QString profile = mProfilesComboBox->currentText(); - -// // Make sure we have no groups open -// while (!mLauncherConfig->group().isEmpty()) { -// mLauncherConfig->endGroup(); -// } - -// mLauncherConfig->beginGroup("Profiles"); -// mLauncherConfig->beginGroup(profile); - -// QStringList childKeys = mLauncherConfig->childKeys(); -// QStringList plugins; - -// // Sort the child keys numerical instead of alphabetically -// // i.e. Plugin1, Plugin2 instead of Plugin1, Plugin10 -// qSort(childKeys.begin(), childKeys.end(), naturalSortLessThanCI); - -// foreach (const QString &key, childKeys) { -// const QString keyValue = mLauncherConfig->value(key).toString(); - -// if (key.startsWith("Plugin")) { -// //QStringList checked = mPluginsModel->checkedItems(); -// EsmFile *file = mPluginsModel->findItem(keyValue); -// QModelIndex index = mPluginsModel->indexFromItem(file); - -// mPluginsModel->setCheckState(index, Qt::Checked); -// // Move the row to the top of te view -// //mPluginsModel->moveRow(index.row(), checked.count()); -// plugins << keyValue; -// } - -// if (key.startsWith("Master")) { -// EsmFile *file = mMastersModel->findItem(keyValue); -// mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked); -// } -// } - -// qDebug() << plugins; -} - void DataFilesPage::setupDataFiles() { // Set the encoding to the one found in openmw.cfg or the default - mMastersModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); - mPluginsModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); + mDataFilesModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); QStringList paths = mGameSettings.getDataDirs(); foreach (const QString &path, paths) { - mMastersModel->addMasters(path); - mPluginsModel->addPlugins(path); + mDataFilesModel->addFiles(path); } QString dataLocal = mGameSettings.getDataLocal(); if (!dataLocal.isEmpty()) { - mMastersModel->addMasters(dataLocal); - mPluginsModel->addPlugins(dataLocal); + mDataFilesModel->addFiles(dataLocal); } QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); @@ -313,29 +284,26 @@ void DataFilesPage::loadSettings() qDebug() << mLauncherSettings.values(QString("Profiles/Default"), Qt::MatchStartsWith); - - if (profile.isEmpty()) return; - mMastersModel->uncheckAll(); - mPluginsModel->uncheckAll(); + mDataFilesModel->uncheckAll(); QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly); QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly); qDebug() << "masters to check " << plugins; foreach (const QString &master, masters) { - QModelIndex index = mMastersModel->indexFromItem(mMastersModel->findItem(master)); + QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(master)); if (index.isValid()) - mMastersModel->setCheckState(index, Qt::Checked); + mDataFilesModel->setCheckState(index, Qt::Checked); } foreach (const QString &plugin, plugins) { - QModelIndex index = mPluginsModel->indexFromItem(mPluginsModel->findItem(plugin)); + QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(plugin)); if (index.isValid()) - mPluginsModel->setCheckState(index, Qt::Checked); + mDataFilesModel->setCheckState(index, Qt::Checked); } } @@ -352,178 +320,22 @@ void DataFilesPage::saveSettings() mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); - QStringList items = mMastersModel->checkedItems(); + QStringList items = mDataFilesModel->checkedItems(); - foreach(const QString &master, items) { - qDebug() << "setting " << master; - mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), master); - } + foreach(const QString &item, items) { - items.clear(); - items = mPluginsModel->checkedItems(); + if (item.endsWith(QString(".esm"), Qt::CaseInsensitive)) { + qDebug() << "setting " << item; + mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item); - qDebug() << items.size(); - - foreach(const QString &plugin, items) { - qDebug() << "setting " << plugin; - mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), plugin); + } else if (item.endsWith(QString(".esp"), Qt::CaseInsensitive)) { + qDebug() << "setting " << item; + mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item); + } } } -void DataFilesPage::writeConfig(QString profile) -{ - -// // Don't overwrite the config if no masters are found -// if (mMastersModel->rowCount() < 1) -// return; - -// QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string()); -// QDir userPath(pathStr); - -// if (!userPath.exists()) { -// if (!userPath.mkpath(pathStr)) { -// QMessageBox msgBox; -// msgBox.setWindowTitle("Error creating OpenMW configuration directory"); -// msgBox.setIcon(QMessageBox::Critical); -// msgBox.setStandardButtons(QMessageBox::Ok); -// msgBox.setText(tr("
Could not create %0

\ -// Please make sure you have the right permissions and try again.
").arg(pathStr)); -// msgBox.exec(); - -// qApp->quit(); -// return; -// } -// } -// // Open the OpenMW config as a QFile -// QFile file(pathStr.append("openmw.cfg")); - -// if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { -// // File cannot be opened or created -// QMessageBox msgBox; -// msgBox.setWindowTitle("Error writing OpenMW configuration file"); -// msgBox.setIcon(QMessageBox::Critical); -// msgBox.setStandardButtons(QMessageBox::Ok); -// msgBox.setText(tr("
Could not open or create %0

\ -// Please make sure you have the right permissions and try again.
").arg(file.fileName())); -// msgBox.exec(); - -// qApp->quit(); -// return; -// } - -// QTextStream in(&file); -// QByteArray buffer; - -// // Remove all previous entries from config -// while (!in.atEnd()) { -// QString line = in.readLine(); -// if (!line.startsWith("master") && -// !line.startsWith("plugin") && -// !line.startsWith("data") && -// !line.startsWith("data-local")) -// { -// buffer += line += "\n"; -// } -// } - -// file.close(); - -// // Now we write back the other config entries -// if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { -// QMessageBox msgBox; -// msgBox.setWindowTitle("Error writing OpenMW configuration file"); -// msgBox.setIcon(QMessageBox::Critical); -// msgBox.setStandardButtons(QMessageBox::Ok); -// msgBox.setText(tr("
Could not write to %0

\ -// Please make sure you have the right permissions and try again.
").arg(file.fileName())); -// msgBox.exec(); - -// qApp->quit(); -// return; -// } - -// if (!buffer.isEmpty()) { -// file.write(buffer); -// } - -// QTextStream gameConfig(&file); - - -// 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(); -// } - -// mLauncherConfig->beginGroup("Profiles"); -// mLauncherConfig->setValue("CurrentProfile", profile); - -// // Open the profile-name subgroup -// mLauncherConfig->beginGroup(profile); -// mLauncherConfig->remove(""); // Clear the subgroup - -// // Now write the masters to the configs -// const QStringList masters = mMastersModel->checkedItems(); - -// // We don't use foreach because we need i -// for (int i = 0; i < masters.size(); ++i) { -// const QString currentMaster = masters.at(i); - -// mLauncherConfig->setValue(QString("Master%0").arg(i), currentMaster); -// gameConfig << "master=" << currentMaster << endl; - -// } - -// // And finally write all checked plugins -// const QStringList plugins = mPluginsModel->checkedItems(); - -// 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; -// } - -// file.close(); -// mLauncherConfig->endGroup(); -// mLauncherConfig->endGroup(); -// mLauncherConfig->sync(); -} - - void DataFilesPage::newProfile() { if (mNewProfileDialog->exec() == QDialog::Accepted) { @@ -599,7 +411,13 @@ void DataFilesPage::check() if (!index.isValid()) return; - mPluginsModel->setCheckState(index, Qt::Checked); + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); } } @@ -619,13 +437,19 @@ void DataFilesPage::uncheck() if (!index.isValid()) return; - mPluginsModel->setCheckState(index, Qt::Unchecked); + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked); } } void DataFilesPage::refresh() { - mPluginsModel->sort(0); + mDataFilesModel->sort(0); // Refresh the plugins table mPluginsTable->scrollToTop(); @@ -643,28 +467,35 @@ void DataFilesPage::setCheckState(QModelIndex index) if (!object) return; - if (object->objectName() == QLatin1String("PluginsTable")) { - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(index); - (mPluginsModel->checkState(sourceIndex) == Qt::Checked) - ? mPluginsModel->setCheckState(sourceIndex, Qt::Unchecked) - : mPluginsModel->setCheckState(sourceIndex, Qt::Checked); + if (object->objectName() == QLatin1String("PluginsTable")) { + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (sourceIndex.isValid()) { + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); + } } if (object->objectName() == QLatin1String("MastersTable")) { - (mMastersModel->checkState(index) == Qt::Checked) - ? mMastersModel->setCheckState(index, Qt::Unchecked) - : mMastersModel->setCheckState(index, Qt::Checked); + QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index); + + if (sourceIndex.isValid()) { + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); + } } return; - } void DataFilesPage::filterChanged(const QString filter) { QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString); - mPluginsProxyModel->setFilterRegExp(regExp); + mFilterProxyModel->setFilterRegExp(regExp); } void DataFilesPage::profileChanged(const QString &previous, const QString ¤t) @@ -690,8 +521,7 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre saveSettings(); mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); - mMastersModel->uncheckAll(); - mPluginsModel->uncheckAll(); + mDataFilesModel->uncheckAll(); loadSettings(); } @@ -712,8 +542,7 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre // Remove the profile from the combobox mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); - mMastersModel->uncheckAll(); - mPluginsModel->uncheckAll(); + mDataFilesModel->uncheckAll(); loadSettings(); } @@ -737,7 +566,13 @@ void DataFilesPage::showContextMenu(const QPoint &point) if (!index.isValid()) return; - (mPluginsModel->checkState(index) == Qt::Checked) + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) ? mUncheckAction->setEnabled(true) : mCheckAction->setEnabled(true); } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index ef03e4ad4..e6b4194bd 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -56,10 +56,12 @@ public slots: void refresh(); private: - DataFilesModel *mMastersModel; - DataFilesModel *mPluginsModel; + DataFilesModel *mDataFilesModel; QSortFilterProxyModel *mPluginsProxyModel; + QSortFilterProxyModel *mMastersProxyModel; + + QSortFilterProxyModel *mFilterProxyModel; QTableView *mMastersTable; QTableView *mPluginsTable; diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 5f0fb77bc..f87937228 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -155,4 +155,6 @@ bool GameSettings::writeFile(QTextStream &stream) } } + + return true; } diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 09cffad7a..036394800 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -204,13 +204,14 @@ bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, in return false; if (role == Qt::CheckStateRole) { - - emit layoutAboutToBeChanged(); - QString name = item(index.row())->fileName(); mCheckStates[name] = static_cast(value.toInt()); - emit layoutChanged(); + // Force a redraw of the view since unchecking one item can affect another + QModelIndex firstIndex = indexFromItem(mFiles.first()); + QModelIndex lastIndex = indexFromItem(mFiles.last()); + + emit dataChanged(firstIndex, lastIndex); return true; } From bcf4f962098a5e48eb3662b045d8692b50cf0eda Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 18 Feb 2013 23:10:50 +0100 Subject: [PATCH 047/151] Added writing masters/plugins to openmw.cfg --- apps/launcher/datafilespage.cpp | 21 +++++---------------- apps/launcher/settings/gamesettings.hpp | 12 ++++++++++++ apps/launcher/settings/settingsbase.hpp | 7 +------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index ed24f881b..e0ebefa58 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -57,7 +57,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam { // Models mDataFilesModel = new DataFilesModel(this); - mDataFilesModel->setObjectName(QString("mDataFilesModel")); mMastersProxyModel = new QSortFilterProxyModel(); mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm")); @@ -65,14 +64,11 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersProxyModel->setSourceModel(mDataFilesModel); mPluginsProxyModel = new QSortFilterProxyModel(); - mPluginsProxyModel->setObjectName(QString("mPluginsProxyModel")); mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp")); mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mPluginsProxyModel->setSourceModel(mDataFilesModel); mFilterProxyModel = new QSortFilterProxyModel(); - mFilterProxyModel->setObjectName(QString("mFilterProxyModel")); - mFilterProxyModel->setDynamicSortFilter(true); mFilterProxyModel->setSourceModel(mPluginsProxyModel); @@ -155,7 +151,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam QList sizeList; sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt(); sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt(); - qDebug() << sizeList; mSplitter->setSizes(sizeList); @@ -279,20 +274,15 @@ void DataFilesPage::setupDataFiles() void DataFilesPage::loadSettings() { - qDebug() << "load settings"; QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); - qDebug() << mLauncherSettings.values(QString("Profiles/Default"), Qt::MatchStartsWith); - if (profile.isEmpty()) return; - mDataFilesModel->uncheckAll(); QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly); QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly); - qDebug() << "masters to check " << plugins; foreach (const QString &master, masters) { QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(master)); @@ -316,21 +306,23 @@ void DataFilesPage::saveSettings() mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), profile); } - qDebug() << "save settings" << profile; mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); + mGameSettings.remove(QString("master")); + mGameSettings.remove(QString("plugin")); + QStringList items = mDataFilesModel->checkedItems(); foreach(const QString &item, items) { if (item.endsWith(QString(".esm"), Qt::CaseInsensitive)) { - qDebug() << "setting " << item; mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item); + mGameSettings.setMultiValue(QString("master"), item); } else if (item.endsWith(QString(".esp"), Qt::CaseInsensitive)) { - qDebug() << "setting " << item; mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item); + mGameSettings.setMultiValue(QString("plugin"), item); } } @@ -500,7 +492,6 @@ void DataFilesPage::filterChanged(const QString filter) void DataFilesPage::profileChanged(const QString &previous, const QString ¤t) { - qDebug() << "Profile is changed from: " << previous << " to " << current; // Prevent the deletion of the default profile if (current == QLatin1String("Default")) { mDeleteProfileAction->setEnabled(false); @@ -527,7 +518,6 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre void DataFilesPage::profileRenamed(const QString &previous, const QString ¤t) { - qDebug() << "rename"; if (previous.isEmpty()) return; @@ -577,7 +567,6 @@ void DataFilesPage::showContextMenu(const QPoint &point) : mCheckAction->setEnabled(true); } - // Show menu mContextMenu->exec(globalPos); diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index 717ce6e87..8aac1552d 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -29,6 +29,18 @@ public: mSettings.insert(key, value); } + inline void setMultiValue(const QString &key, const QString &value) + { + QStringList values = mSettings.values(key); + if (!values.contains(value)) + mSettings.insertMulti(key, value); + } + + inline void remove(const QString &key) + { + mSettings.remove(key); + } + inline QStringList getDataDirs() { return mDataDirs; } inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); } inline QString getDataLocal() {return mDataLocal; } diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index 361884da6..e70bc0d72 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -32,15 +32,10 @@ public: inline void setMultiValue(const QString &key, const QString &value) { QStringList values = mSettings.values(key); - if (!values.contains(value)) { - qDebug() << "inserting " << value; + if (!values.contains(value)) mSettings.insertMulti(key, value); - } else { - qDebug() << "not inserting " << value; - } } - inline void remove(const QString &key) { mSettings.remove(key); From 6cceb04adf93e3328c478127a635d13b3b605e93 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 19 Feb 2013 03:08:00 +0100 Subject: [PATCH 048/151] When a custom near clip plane is used, we need to fix up a second viewproj matrix manually to get proper depth values in the vertex shader. This fixes fog on reflections. --- apps/openmw/mwrender/refraction.cpp | 11 +++++++- apps/openmw/mwrender/renderingmanager.cpp | 2 ++ apps/openmw/mwrender/water.cpp | 6 +++++ files/materials/objects.shader | 33 +++++++++++++++++++++-- files/materials/openmw.configuration | 7 ++++- files/materials/terrain.shader | 24 +++++++++++++++++ 6 files changed, 79 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index a924be7d7..67fe9e340 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include "renderconst.hpp" namespace MWRender @@ -30,7 +32,7 @@ namespace MWRender vp->setOverlaysEnabled(false); vp->setShadowsEnabled(false); vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Sky); - vp->setMaterialScheme("water_reflection"); + vp->setMaterialScheme("water_refraction"); vp->setBackgroundColour (Ogre::ColourValue(0.0078, 0.0576, 0.150)); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); @@ -54,6 +56,12 @@ namespace MWRender mCamera->setAspectRatio(mParentCamera->getAspectRatio()); mCamera->setFOVy(mParentCamera->getFOVy()); + // for depth calculation, we want the original viewproj matrix _without_ the custom near clip plane. + // since all we are interested in is depth, we only need the third row of the matrix. + Ogre::Matrix4 projMatrix = mCamera->getProjectionMatrixWithRSDepth () * mCamera->getViewMatrix (); + sh::Vector4* row3 = new sh::Vector4(projMatrix[2][0], projMatrix[2][1], projMatrix[2][2], projMatrix[2][3]); + sh::Factory::getInstance ().setSharedParameter ("vpRow2Fix", sh::makeProperty (row3)); + // enable clip plane here to take advantage of CPU culling for overwater or underwater objects mCamera->enableCustomNearClipPlane(mIsUnderwater ? mNearClipPlaneUnderwater : mNearClipPlane); @@ -62,6 +70,7 @@ namespace MWRender void Refraction::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { + mCamera->disableCustomNearClipPlane (); mRenderActive = false; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 6c6c47417..c4f2d99cb 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -140,6 +140,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty(new sh::Vector3(0.5, -0.8, 0.2))); sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(1, 0.6))); sh::Factory::getInstance ().setGlobalSetting ("refraction", Settings::Manager::getBool("refraction", "Water") ? "true" : "false"); + sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false"); + sh::Factory::getInstance ().setSharedParameter ("vpRow2Fix", sh::makeProperty (new sh::Vector4(0,0,0,0))); applyCompositors(); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index f71431a27..a76b0d1d3 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -144,6 +144,12 @@ void PlaneReflection::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) mSky->setSkyPosition(pos); mCamera->enableReflection(mWaterPlane); + // for depth calculation, we want the original viewproj matrix _without_ the custom near clip plane. + // since all we are interested in is depth, we only need the third row of the matrix. + Ogre::Matrix4 projMatrix = mCamera->getProjectionMatrixWithRSDepth () * mCamera->getViewMatrix (); + sh::Vector4* row3 = new sh::Vector4(projMatrix[2][0], projMatrix[2][1], projMatrix[2][2], projMatrix[2][3]); + sh::Factory::getInstance ().setSharedParameter ("vpRow2Fix", sh::makeProperty (row3)); + // enable clip plane here to take advantage of CPU culling for overwater or underwater objects mCamera->enableCustomNearClipPlane(mIsUnderwater ? mErrorPlaneUnderwater : mErrorPlane); } diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 3f5aa418f..fad8c1ac8 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -23,12 +23,21 @@ #define VERTEX_LIGHTING 1 +#define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix) + #ifdef SH_VERTEX_SHADER // ------------------------------------- VERTEX --------------------------------------- SH_BEGIN_PROGRAM shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + +#if VIEWPROJ_FIX + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) + shUniform(float4, vpRow2Fix) @shSharedParameter(vpRow2Fix, vpRow2Fix) + shUniform(float4x4, vpMatrix) @shAutoConstant(vpMatrix, viewproj_matrix) +#endif + shVertexInput(float2, uv0) shOutput(float2, UV) shNormalInput(float4) @@ -65,7 +74,6 @@ #if SHADOWS shOutput(float4, lightSpacePos0) shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix) - shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) #endif #if SHADOWS_PSSM @@ -73,7 +81,9 @@ shOutput(float4, lightSpacePos@shIterator) shUniform(float4x4, texViewProjMatrix@shIterator) @shAutoConstant(texViewProjMatrix@shIterator, texture_viewproj_matrix, @shIterator) @shEndForeach - shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) +#if !VIEWPROJ_FIX + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) +#endif #endif #if VERTEX_LIGHTING @@ -89,9 +99,28 @@ #endif #ifdef NEED_DEPTH + + +#if VIEWPROJ_FIX + float4x4 vpFixed = vpMatrix; +#if !SH_GLSL + vpFixed[2] = vpRow2Fix; +#else + vpFixed[0][2] = vpRow2Fix.x; + vpFixed[1][2] = vpRow2Fix.y; + vpFixed[2][2] = vpRow2Fix.z; + vpFixed[3][2] = vpRow2Fix.w; +#endif + + float4x4 fixedWVP = shMatrixMult(vpFixed, worldMatrix); + + depthPassthrough = shMatrixMult(fixedWVP, shInputPosition).z; +#else depthPassthrough = shOutputPosition.z; #endif +#endif + #if LIGHTING objSpacePositionPassthrough = shInputPosition.xyz; #endif diff --git a/files/materials/openmw.configuration b/files/materials/openmw.configuration index 870c96728..21ac9416b 100644 --- a/files/materials/openmw.configuration +++ b/files/materials/openmw.configuration @@ -1,8 +1,13 @@ configuration water_reflection { - fog false shadows false shadows_pssm false + viewproj_fix true +} + +configuration water_refraction +{ + viewproj_fix true } configuration local_map diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 497463f8e..b7ee15e8d 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -23,6 +23,8 @@ #define UNDERWATER @shGlobalSettingBool(underwater_effects) && LIGHTING +#define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix) + #if NEED_DEPTH @shAllocatePassthrough(1, depth) @@ -51,6 +53,10 @@ shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) shUniform(float4x4, viewProjMatrix) @shAutoConstant(viewProjMatrix, viewproj_matrix) +#if VIEWPROJ_FIX + shUniform(float4, vpRow2Fix) @shSharedParameter(vpRow2Fix, vpRow2Fix) +#endif + shUniform(float2, lodMorph) @shAutoConstant(lodMorph, custom, 1001) shVertexInput(float2, uv0) @@ -94,7 +100,25 @@ shOutputPosition = shMatrixMult(viewProjMatrix, worldPos); #if NEED_DEPTH +#if VIEWPROJ_FIX + float4x4 vpFixed = viewProjMatrix; +#if !SH_GLSL + vpFixed[2] = vpRow2Fix; +#else + vpFixed[0][2] = vpRow2Fix.x; + vpFixed[1][2] = vpRow2Fix.y; + vpFixed[2][2] = vpRow2Fix.z; + vpFixed[3][2] = vpRow2Fix.w; +#endif + + float4x4 fixedWVP = shMatrixMult(vpFixed, worldMatrix); + + float depth = shMatrixMult(fixedWVP, shInputPosition).z; + @shPassthroughAssign(depth, depth); +#else @shPassthroughAssign(depth, shOutputPosition.z); +#endif + #endif @shPassthroughAssign(UV, uv0); From 427152c518aa9c4ffef873772dcc254a9fb44204 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 19 Feb 2013 03:15:31 +0100 Subject: [PATCH 049/151] Disabled ripples until we can properly trigger them from the new character controller. --- apps/openmw/mwrender/water.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index a76b0d1d3..f0680f208 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -393,10 +393,9 @@ void Water::update(float dt, Ogre::Vector3 player) mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); - /// \todo player.y is the scene node position (which is above the head) and not the feet position //if (player.y <= mTop) { - mSimulation->addImpulse(Ogre::Vector2(player.x, player.z)); + //mSimulation->addImpulse(Ogre::Vector2(player.x, player.z)); } mSimulation->update(dt, Ogre::Vector2(player.x, player.z)); From 35b68a3c400ed79762338835ef77b48b5bde95b0 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 19 Feb 2013 15:58:01 +0100 Subject: [PATCH 050/151] Fixed accidental profile deletion and added sorting by date --- apps/launcher/CMakeLists.txt | 6 ++ apps/launcher/datafilespage.cpp | 71 +++++++++++-------- apps/launcher/datafilespage.hpp | 4 +- apps/launcher/maindialog.cpp | 2 - apps/launcher/model/pluginsproxymodel.cpp | 17 +++++ apps/launcher/model/pluginsproxymodel.hpp | 18 +++++ apps/launcher/settings/gamesettings.cpp | 55 ++++++++------ apps/launcher/settings/launchersettings.cpp | 17 ++--- apps/launcher/settings/settingsbase.hpp | 2 - .../fileorderlist/model/datafilesmodel.cpp | 21 +++++- 10 files changed, 146 insertions(+), 67 deletions(-) create mode 100644 apps/launcher/model/pluginsproxymodel.cpp create mode 100644 apps/launcher/model/pluginsproxymodel.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 2c17e06b4..59cccad5f 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -5,6 +5,8 @@ set(LAUNCHER maindialog.cpp playpage.cpp + model/pluginsproxymodel.cpp + settings/gamesettings.cpp settings/graphicssettings.cpp settings/launchersettings.cpp @@ -22,6 +24,8 @@ set(LAUNCHER_HEADER maindialog.hpp playpage.hpp + model/pluginsproxymodel.hpp + settings/gamesettings.hpp settings/graphicssettings.hpp settings/launchersettings.hpp @@ -39,6 +43,8 @@ set(LAUNCHER_HEADER_MOC maindialog.hpp playpage.hpp + model/pluginsproxymodel.hpp + utils/comboboxlineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index e0ebefa58..4ecb67e4e 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -9,6 +9,8 @@ #include #include +#include "model/pluginsproxymodel.hpp" + #include "settings/gamesettings.hpp" #include "settings/launchersettings.hpp" @@ -63,7 +65,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mMastersProxyModel->setSourceModel(mDataFilesModel); - mPluginsProxyModel = new QSortFilterProxyModel(); + mPluginsProxyModel = new PluginsProxyModel(); mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp")); mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mPluginsProxyModel->setSourceModel(mDataFilesModel); @@ -97,6 +99,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersTable = new QTableView(this); mMastersTable->setModel(mMastersProxyModel); mMastersTable->setObjectName("MastersTable"); + mMastersTable->setSortingEnabled(false); mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection); mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -108,19 +111,12 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersTable->verticalHeader()->setDefaultSectionSize(height); mMastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); mMastersTable->verticalHeader()->hide(); - mMastersTable->setColumnHidden(1, true); - mMastersTable->setColumnHidden(2, true); - mMastersTable->setColumnHidden(3, true); - mMastersTable->setColumnHidden(4, true); - mMastersTable->setColumnHidden(5, true); - mMastersTable->setColumnHidden(6, true); - mMastersTable->setColumnHidden(7, true); - mMastersTable->setColumnHidden(8, true); mPluginsTable = new QTableView(this); mPluginsTable->setModel(mFilterProxyModel); mPluginsTable->setObjectName("PluginsTable"); mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); + mPluginsTable->setSortingEnabled(false); mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); mPluginsTable->setSelectionMode(QAbstractItemView::SingleSelection); mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -131,14 +127,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mPluginsTable->verticalHeader()->setDefaultSectionSize(height); mPluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - mPluginsTable->setColumnHidden(1, true); - mPluginsTable->setColumnHidden(2, true); - mPluginsTable->setColumnHidden(3, true); - mPluginsTable->setColumnHidden(4, true); - mPluginsTable->setColumnHidden(5, true); - mPluginsTable->setColumnHidden(6, true); - mPluginsTable->setColumnHidden(7, true); - mPluginsTable->setColumnHidden(8, true); // Add both tables to a splitter mSplitter = new QSplitter(this); @@ -185,12 +173,11 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + + connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); - connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); - connect(mSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter())); createActions(); @@ -250,9 +237,13 @@ void DataFilesPage::setupDataFiles() mDataFilesModel->addFiles(dataLocal); } + // Sort by date accessed for now + mDataFilesModel->sort(3); + QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + mProfilesComboBox->setCurrentIndex(-1); mProfilesComboBox->addItems(profiles); // Add the current profile if empty @@ -262,12 +253,18 @@ void DataFilesPage::setupDataFiles() if (mProfilesComboBox->findText(QString("Default")) == -1) mProfilesComboBox->addItem(QString("Default")); - if (profile.isEmpty()) { + + if (profile.isEmpty() || profile == QLatin1String("Default")) { mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(QString("Default"))); } else { + mProfilesComboBox->setEditEnabled(true); mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); } + // We do this here to prevent deletion of profiles when initializing the combobox + connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); + connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); + loadSettings(); } @@ -301,10 +298,8 @@ void DataFilesPage::saveSettings() { QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); - if (profile.isEmpty()) { - profile = mProfilesComboBox->currentText(); - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), profile); - } + if (profile.isEmpty()) + return; mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); @@ -360,6 +355,28 @@ void DataFilesPage::updateSplitter() mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1))); } +void DataFilesPage::updateViews() +{ + // Ensure the columns are hidden because sort() re-enables them + mMastersTable->setColumnHidden(1, true); + mMastersTable->setColumnHidden(2, true); + mMastersTable->setColumnHidden(3, true); + mMastersTable->setColumnHidden(4, true); + mMastersTable->setColumnHidden(5, true); + mMastersTable->setColumnHidden(6, true); + mMastersTable->setColumnHidden(7, true); + mMastersTable->setColumnHidden(8, true); + + mPluginsTable->setColumnHidden(1, true); + mPluginsTable->setColumnHidden(2, true); + mPluginsTable->setColumnHidden(3, true); + mPluginsTable->setColumnHidden(4, true); + mPluginsTable->setColumnHidden(5, true); + mPluginsTable->setColumnHidden(6, true); + mPluginsTable->setColumnHidden(7, true); + mPluginsTable->setColumnHidden(8, true); +} + void DataFilesPage::deleteProfile() { QString profile = mProfilesComboBox->currentText(); @@ -441,7 +458,7 @@ void DataFilesPage::uncheck() void DataFilesPage::refresh() { - mDataFilesModel->sort(0); +// mDataFilesModel->sort(0); // Refresh the plugins table mPluginsTable->scrollToTop(); @@ -512,7 +529,6 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre saveSettings(); mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); - mDataFilesModel->uncheckAll(); loadSettings(); } @@ -532,7 +548,6 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre // Remove the profile from the combobox mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); - mDataFilesModel->uncheckAll(); loadSettings(); } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index e6b4194bd..2561aa3d1 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -18,6 +18,7 @@ class TextInputDialog; class ProfilesComboBox; class GameSettings; class LauncherSettings; +class PluginsProxyModel; namespace Files { struct ConfigurationManager; } @@ -43,6 +44,7 @@ public slots: void profileRenamed(const QString &previous, const QString ¤t); void updateOkButton(const QString &text); void updateSplitter(); + void updateViews(); // Action slots void newProfile(); @@ -58,7 +60,7 @@ public slots: private: DataFilesModel *mDataFilesModel; - QSortFilterProxyModel *mPluginsProxyModel; + PluginsProxyModel *mPluginsProxyModel; QSortFilterProxyModel *mMastersProxyModel; QSortFilterProxyModel *mFilterProxyModel; diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 7b453671c..15f2690da 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -206,8 +206,6 @@ void MainDialog::saveSettings() mLauncherSettings.setValue(QString("General/MainWindow/posx"), posX); mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY); - - qDebug() << "size: " << width << height; } void MainDialog::writeSettings() diff --git a/apps/launcher/model/pluginsproxymodel.cpp b/apps/launcher/model/pluginsproxymodel.cpp new file mode 100644 index 000000000..6be152b55 --- /dev/null +++ b/apps/launcher/model/pluginsproxymodel.cpp @@ -0,0 +1,17 @@ +#include "pluginsproxymodel.hpp" + +PluginsProxyModel::PluginsProxyModel(QObject *parent) : + QSortFilterProxyModel(parent) +{ +} + +PluginsProxyModel::~PluginsProxyModel() +{ +} + +QVariant PluginsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Vertical || role != Qt::DisplayRole) + return QSortFilterProxyModel::headerData(section, orientation, role); + return section + 1; +} diff --git a/apps/launcher/model/pluginsproxymodel.hpp b/apps/launcher/model/pluginsproxymodel.hpp new file mode 100644 index 000000000..8fde73236 --- /dev/null +++ b/apps/launcher/model/pluginsproxymodel.hpp @@ -0,0 +1,18 @@ +#ifndef PLUGINSPROXYMODEL_HPP +#define PLUGINSPROXYMODEL_HPP + +#include + +class QVariant; + +class PluginsProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit PluginsProxyModel(QObject *parent = 0); + ~PluginsProxyModel(); + + QVariant headerData(int section, Qt::Orientation orientation, int role) const; +}; + +#endif // PLUGINSPROXYMODEL_HPP diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index f87937228..fcf6f8b8a 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -21,8 +21,6 @@ GameSettings::~GameSettings() void GameSettings::validatePaths() { - qDebug() << "validate paths!"; - if (mSettings.isEmpty()) return; @@ -35,9 +33,6 @@ void GameSettings::validatePaths() // Parse the data dirs to convert the tokenized paths mCfgMgr.processPaths(dataDirs); - -// // Replace the existing data paths with valid untokenized ones -// mSettings.remove(QString("data")); mDataDirs.clear(); for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { @@ -59,7 +54,6 @@ void GameSettings::validatePaths() dataDirs.push_back(Files::PathContainer::value_type(local.toStdString())); mCfgMgr.processPaths(dataDirs); -// mSettings.remove(QString("data-local")); if (!dataDirs.empty()) { QString path = QString::fromStdString(dataDirs.front().string()); @@ -92,23 +86,21 @@ bool GameSettings::readFile(QTextStream &stream) if (line.isEmpty() || line.startsWith("#")) continue; - qDebug() << "line: " << line; if (keyRe.indexIn(line) != -1) { QString key = keyRe.cap(1).simplified(); QString value = keyRe.cap(2).simplified(); - qDebug() << "key: " << key; - // There can be multiple data keys - if (key == QLatin1String("data")) { + // There can be multiple keys + if (key == QLatin1String("data") || + key == QLatin1String("master") || + key == QLatin1String("plugin")) + { // Remove keys from previous config and overwrite them mSettings.remove(key); QStringList values = cache.values(key); - if (!values.contains(value)) { - // Do not insert duplicate values - qDebug() << "values does not contain: " << value << values; + if (!values.contains(value)) // Do not insert duplicate values cache.insertMulti(key, value); - } } else { cache.insert(key, value); } @@ -137,23 +129,42 @@ bool GameSettings::readFile(QTextStream &stream) // Merge the changed keys with those which didn't mSettings.unite(cache); validatePaths(); - qDebug() << mSettings; + return true; } bool GameSettings::writeFile(QTextStream &stream) { + // Iterate in reverse order to preserve insertion order QMapIterator i(mSettings); - while (i.hasNext()) { - i.next(); + i.toBack(); - // Quote values with spaces - if (i.value().contains(" ")) { - stream << i.key() << "=\"" << i.value() << "\"\n"; - } else { - stream << i.key() << "=" << i.value() << "\n"; + while (i.hasPrevious()) { + i.previous(); + + if (i.key() == QLatin1String("master") || i.key() == QLatin1String("plugin")) + continue; + + // Quote paths with spaces + if (i.key() == QLatin1String("data") || i.key() == QLatin1String("data")) { + if (i.value().contains(" ")) { + stream << i.key() << "=\"" << i.value() << "\"\n"; + continue; + } } + stream << i.key() << "=" << i.value() << "\n"; + + } + + QStringList masters = mSettings.values(QString("master")); + for (int i = masters.count(); i--;) { + stream << "master=" << masters.at(i) << "\n"; + } + + QStringList plugins = mSettings.values(QString("plugin")); + for (int i = plugins.count(); i--;) { + stream << "plugin=" << plugins.at(i) << "\n"; } return true; diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index 07502ea02..e9730c235 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -26,7 +26,6 @@ QStringList LauncherSettings::values(const QString &key, Qt::MatchFlags flags) QStringList keys = settings.keys(); foreach (const QString ¤tKey, keys) { - qDebug() << "key is: " << currentKey << "value: " << settings.value(currentKey); if (currentKey.startsWith(key)) result.append(settings.value(currentKey)); } @@ -38,16 +37,15 @@ QStringList LauncherSettings::values(const QString &key, Qt::MatchFlags flags) QStringList LauncherSettings::subKeys(const QString &key) { QMap settings = SettingsBase::getSettings(); - QStringList keys = settings.keys(); + QStringList keys = settings.uniqueKeys(); QRegExp keyRe("(.+)/"); QStringList result; foreach (const QString ¤tKey, keys) { - qDebug() << "key is: " << currentKey; + if (keyRe.indexIn(currentKey) != -1) { - qDebug() << "text: " << keyRe.cap(1) << keyRe.cap(2); QString prefixedKey = keyRe.cap(1); if(prefixedKey.startsWith(key)) { @@ -55,16 +53,11 @@ QStringList LauncherSettings::subKeys(const QString &key) QString subKey = prefixedKey.remove(key); if (!subKey.isEmpty()) result.append(subKey); - //qDebug() << keyRe.cap(2).simplified(); } - } else { - qDebug() << "no match"; } } result.removeDuplicates(); - qDebug() << result; - return result; } @@ -75,8 +68,10 @@ bool LauncherSettings::writeFile(QTextStream &stream) QMap settings = SettingsBase::getSettings(); QMapIterator i(settings); - while (i.hasNext()) { - i.next(); + i.toBack(); + + while (i.hasPrevious()) { + i.previous(); QString prefix; QString key; diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index e70bc0d72..321426eed 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -75,7 +75,6 @@ public: QStringList values = mCache.values(key); if (!values.contains(value)) { - // QMap will replace the value if key exists, QMultiMap creates a new one mCache.insertMulti(key, value); } } @@ -96,7 +95,6 @@ public: // Merge the changed keys with those which didn't mSettings.unite(mCache); - qDebug() << mSettings; return true; } diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 036394800..4e9b69dc2 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -229,10 +229,29 @@ bool lessThanEsmFile(const EsmFile *e1, const EsmFile *e2) return e1->fileName().toLower() < e2->fileName().toLower(); } +bool lessThanDate(const EsmFile *e1, const EsmFile *e2) +{ + if (e1->modified().toString(Qt::ISODate) < e2->modified().toString(Qt::ISODate)) { + return true; + } 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) { emit layoutAboutToBeChanged(); - qSort(mFiles.begin(), mFiles.end(), lessThanEsmFile); + + if (column == 3) { + qSort(mFiles.begin(), mFiles.end(), lessThanDate); + } else { + qSort(mFiles.begin(), mFiles.end(), lessThanEsmFile); + } + emit layoutChanged(); } From 2172fb42298a4faddc7a0ae2a37a04aa3a4e15b1 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 19 Feb 2013 16:41:33 +0100 Subject: [PATCH 051/151] Added checkable message box class --- apps/launcher/CMakeLists.txt | 5 +- apps/launcher/utils/checkablemessagebox.cpp | 243 ++++++++++++++++++++ apps/launcher/utils/checkablemessagebox.hpp | 71 ++++++ 3 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 apps/launcher/utils/checkablemessagebox.cpp create mode 100644 apps/launcher/utils/checkablemessagebox.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 59cccad5f..b2e6c7009 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -11,6 +11,7 @@ set(LAUNCHER settings/graphicssettings.cpp settings/launchersettings.cpp + utils/checkablemessagebox.cpp utils/comboboxlineedit.cpp utils/profilescombobox.cpp utils/textinputdialog.cpp @@ -31,7 +32,8 @@ set(LAUNCHER_HEADER settings/launchersettings.hpp settings/settingsbase.hpp - utils/comboboxlineedit.cpp + utils/checkablemessagebox.hpp + utils/comboboxlineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp ) @@ -45,6 +47,7 @@ set(LAUNCHER_HEADER_MOC model/pluginsproxymodel.hpp + utils/checkablemessagebox.hpp utils/comboboxlineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp diff --git a/apps/launcher/utils/checkablemessagebox.cpp b/apps/launcher/utils/checkablemessagebox.cpp new file mode 100644 index 000000000..8aa01d101 --- /dev/null +++ b/apps/launcher/utils/checkablemessagebox.cpp @@ -0,0 +1,243 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "checkablemessagebox.hpp" + + +/* + class CheckableMessageBox + Modified from the one used in Qt Creator + + A messagebox suitable for questions with a + "Do not ask me again" checkbox. + + Emulates the QMessageBox API with + static conveniences. The message label can open external URLs. +*/ + + +class CheckableMessageBoxPrivate +{ +public: + CheckableMessageBoxPrivate(QDialog *q) + : clickedButton(0) + { + QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + + pixmapLabel = new QLabel(q); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth()); + pixmapLabel->setSizePolicy(sizePolicy); + pixmapLabel->setVisible(false); + + QSpacerItem *pixmapSpacer = + new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); + + messageLabel = new QLabel(q); + messageLabel->setMinimumSize(QSize(300, 0)); + messageLabel->setWordWrap(true); + messageLabel->setOpenExternalLinks(true); + messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse); + + QSpacerItem *checkBoxRightSpacer = + new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum); + QSpacerItem *buttonSpacer = + new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum); + + checkBox = new QCheckBox(q); + checkBox->setText(CheckableMessageBox::tr("Do not ask again")); + + buttonBox = new QDialogButtonBox(q); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + QVBoxLayout *verticalLayout = new QVBoxLayout(); + verticalLayout->addWidget(pixmapLabel); + verticalLayout->addItem(pixmapSpacer); + + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->addLayout(verticalLayout); + horizontalLayout_2->addWidget(messageLabel); + + QHBoxLayout *horizontalLayout = new QHBoxLayout(); + horizontalLayout->addWidget(checkBox); + horizontalLayout->addItem(checkBoxRightSpacer); + + QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q); + verticalLayout_2->addLayout(horizontalLayout_2); + verticalLayout_2->addLayout(horizontalLayout); + verticalLayout_2->addItem(buttonSpacer); + verticalLayout_2->addWidget(buttonBox); + } + + QLabel *pixmapLabel; + QLabel *messageLabel; + QCheckBox *checkBox; + QDialogButtonBox *buttonBox; + QAbstractButton *clickedButton; +}; + +CheckableMessageBox::CheckableMessageBox(QWidget *parent) : + QDialog(parent), + d(new CheckableMessageBoxPrivate(this)) +{ + setModal(true); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + connect(d->buttonBox, SIGNAL(accepted()), SLOT(accept())); + connect(d->buttonBox, SIGNAL(rejected()), SLOT(reject())); + connect(d->buttonBox, SIGNAL(clicked(QAbstractButton*)), + SLOT(slotClicked(QAbstractButton*))); +} + +CheckableMessageBox::~CheckableMessageBox() +{ + delete d; +} + +void CheckableMessageBox::slotClicked(QAbstractButton *b) +{ + d->clickedButton = b; +} + +QAbstractButton *CheckableMessageBox::clickedButton() const +{ + return d->clickedButton; +} + +QDialogButtonBox::StandardButton CheckableMessageBox::clickedStandardButton() const +{ + if (d->clickedButton) + return d->buttonBox->standardButton(d->clickedButton); + return QDialogButtonBox::NoButton; +} + +QString CheckableMessageBox::text() const +{ + return d->messageLabel->text(); +} + +void CheckableMessageBox::setText(const QString &t) +{ + d->messageLabel->setText(t); +} + +QPixmap CheckableMessageBox::iconPixmap() const +{ + if (const QPixmap *p = d->pixmapLabel->pixmap()) + return QPixmap(*p); + return QPixmap(); +} + +void CheckableMessageBox::setIconPixmap(const QPixmap &p) +{ + d->pixmapLabel->setPixmap(p); + d->pixmapLabel->setVisible(!p.isNull()); +} + +bool CheckableMessageBox::isChecked() const +{ + return d->checkBox->isChecked(); +} + +void CheckableMessageBox::setChecked(bool s) +{ + d->checkBox->setChecked(s); +} + +QString CheckableMessageBox::checkBoxText() const +{ + return d->checkBox->text(); +} + +void CheckableMessageBox::setCheckBoxText(const QString &t) +{ + d->checkBox->setText(t); +} + +bool CheckableMessageBox::isCheckBoxVisible() const +{ + return d->checkBox->isVisible(); +} + +void CheckableMessageBox::setCheckBoxVisible(bool v) +{ + d->checkBox->setVisible(v); +} + +QDialogButtonBox::StandardButtons CheckableMessageBox::standardButtons() const +{ + return d->buttonBox->standardButtons(); +} + +void CheckableMessageBox::setStandardButtons(QDialogButtonBox::StandardButtons s) +{ + d->buttonBox->setStandardButtons(s); +} + +QPushButton *CheckableMessageBox::button(QDialogButtonBox::StandardButton b) const +{ + return d->buttonBox->button(b); +} + +QPushButton *CheckableMessageBox::addButton(const QString &text, QDialogButtonBox::ButtonRole role) +{ + return d->buttonBox->addButton(text, role); +} + +QDialogButtonBox::StandardButton CheckableMessageBox::defaultButton() const +{ + foreach (QAbstractButton *b, d->buttonBox->buttons()) + if (QPushButton *pb = qobject_cast(b)) + if (pb->isDefault()) + return d->buttonBox->standardButton(pb); + return QDialogButtonBox::NoButton; +} + +void CheckableMessageBox::setDefaultButton(QDialogButtonBox::StandardButton s) +{ + if (QPushButton *b = d->buttonBox->button(s)) { + b->setDefault(true); + b->setFocus(); + } +} + +QDialogButtonBox::StandardButton +CheckableMessageBox::question(QWidget *parent, + const QString &title, + const QString &question, + const QString &checkBoxText, + bool *checkBoxSetting, + QDialogButtonBox::StandardButtons buttons, + QDialogButtonBox::StandardButton defaultButton) +{ + CheckableMessageBox mb(parent); + mb.setWindowTitle(title); + mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question)); + mb.setText(question); + mb.setCheckBoxText(checkBoxText); + mb.setChecked(*checkBoxSetting); + mb.setStandardButtons(buttons); + mb.setDefaultButton(defaultButton); + mb.exec(); + *checkBoxSetting = mb.isChecked(); + return mb.clickedStandardButton(); +} + +QMessageBox::StandardButton CheckableMessageBox::dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton db) +{ + return static_cast(int(db)); +} diff --git a/apps/launcher/utils/checkablemessagebox.hpp b/apps/launcher/utils/checkablemessagebox.hpp new file mode 100644 index 000000000..ceb437d4d --- /dev/null +++ b/apps/launcher/utils/checkablemessagebox.hpp @@ -0,0 +1,71 @@ +#ifndef CHECKABLEMESSAGEBOX_HPP +#define CHECKABLEMESSAGEBOX_HPP + +#include +#include +#include + +class CheckableMessageBoxPrivate; + +class CheckableMessageBox : public QDialog +{ + Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap) + Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked) + Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText) + Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons) + Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton) + +public: + explicit CheckableMessageBox(QWidget *parent); + virtual ~CheckableMessageBox(); + + static QDialogButtonBox::StandardButton + question(QWidget *parent, + const QString &title, + const QString &question, + const QString &checkBoxText, + bool *checkBoxSetting, + QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No, + QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No); + + QString text() const; + void setText(const QString &); + + bool isChecked() const; + void setChecked(bool s); + + QString checkBoxText() const; + void setCheckBoxText(const QString &); + + bool isCheckBoxVisible() const; + void setCheckBoxVisible(bool); + + QDialogButtonBox::StandardButtons standardButtons() const; + void setStandardButtons(QDialogButtonBox::StandardButtons s); + QPushButton *button(QDialogButtonBox::StandardButton b) const; + QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role); + + QDialogButtonBox::StandardButton defaultButton() const; + void setDefaultButton(QDialogButtonBox::StandardButton s); + + // See static QMessageBox::standardPixmap() + QPixmap iconPixmap() const; + void setIconPixmap (const QPixmap &p); + + // Query the result + QAbstractButton *clickedButton() const; + QDialogButtonBox::StandardButton clickedStandardButton() const; + + // Conversion convenience + static QMessageBox::StandardButton dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton); + +private slots: + void slotClicked(QAbstractButton *b); + +private: + CheckableMessageBoxPrivate *d; +}; + +#endif // CHECKABLEMESSAGEBOX_HPP From 18d01cd65a585abbaf1b7f197d2af283f922c7a8 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 20 Feb 2013 19:27:04 +0100 Subject: [PATCH 052/151] Implemented a first-run dialog to import Morrowind.ini settings --- apps/launcher/main.cpp | 166 +------- apps/launcher/maindialog.cpp | 427 +++++++++++++++++--- apps/launcher/maindialog.hpp | 31 +- apps/launcher/settings/gamesettings.cpp | 34 +- apps/launcher/settings/gamesettings.hpp | 5 + apps/launcher/utils/checkablemessagebox.cpp | 43 +- apps/launcher/utils/checkablemessagebox.hpp | 43 +- 7 files changed, 493 insertions(+), 256 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index ba84518c1..5d57dce55 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,23 +1,6 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include #include "maindialog.hpp" -#include "settings/gamesettings.hpp" -#include "settings/graphicssettings.hpp" -#include "settings/launchersettings.hpp" - int main(int argc, char *argv[]) { @@ -45,154 +28,7 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - // Create setting file handlers - - Files::ConfigurationManager cfgMgr; - QString userPath = QString::fromStdString(cfgMgr.getUserPath().string()); - QString globalPath = QString::fromStdString(cfgMgr.getGlobalPath().string()); - - GameSettings gameSettings(cfgMgr); - GraphicsSettings graphicsSettings; - LauncherSettings launcherSettings; - - QStringList paths; - paths.append(userPath + QString("openmw.cfg")); - paths.append(QString("openmw.cfg")); - paths.append(globalPath + QString("openmw.cfg")); - - foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; - QFile file(path); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error opening OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not open %0 for reading

\ - Please make sure you have the right permissions \ - and try again.
").arg(file.fileName())); - msgBox.exec(); - return 0; - } - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - - gameSettings.readFile(stream); - } - file.close(); - } - - if (gameSettings.getDataDirs().isEmpty()) - { - QMessageBox msgBox; - msgBox.setWindowTitle("Error detecting Morrowind installation"); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setStandardButtons(QMessageBox::Cancel); - msgBox.setText(QObject::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(QObject::tr("B&rowse..."), QMessageBox::ActionRole); - - msgBox.exec(); - - QString selectedFile; - if (msgBox.clickedButton() == dirSelectButton) { - selectedFile = QFileDialog::getOpenFileName( - NULL, - QObject::tr("Select master file"), - QDir::currentPath(), - QString("Morrowind master file (*.esm)")); - } - - if (selectedFile.isEmpty()) - return 0; // Cancel was clicked; - - qDebug() << selectedFile; - QFileInfo info(selectedFile); - - // Add the new dir to the settings file and to the data dir container - gameSettings.setValue(QString("data"), info.absolutePath()); - gameSettings.addDataDir(info.absolutePath()); - - } - - // On to the graphics settings - QFile localDefault(QString("settings-default.cfg")); - QFile globalDefault(globalPath + QString("settings-default.cfg")); - - if (!localDefault.exists() && !globalDefault.exists()) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error reading OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not find settings-default.cfg

\ - The problem may be due to an incomplete installation of OpenMW.
\ - Reinstalling OpenMW may resolve the problem.")); - msgBox.exec(); - return 0; - } - - paths.clear(); - paths.append(globalPath + QString("settings-default.cfg")); - paths.append(QString("settings-default.cfg")); - paths.append(userPath + QString("settings.cfg")); - - foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; - QFile file(path); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error opening OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not open %0 for reading

\ - Please make sure you have the right permissions \ - and try again.
").arg(file.fileName())); - msgBox.exec(); - return 0; - } - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - - graphicsSettings.readFile(stream); - } - file.close(); - } - - // Now the launcher settings - paths.clear(); - paths.append(QString("launcher.cfg")); - paths.append(userPath + QString("launcher.cfg")); - - foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; - QFile file(path); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error opening OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not open %0 for reading

\ - Please make sure you have the right permissions \ - and try again.
").arg(file.fileName())); - msgBox.exec(); - return 0; - } - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - - launcherSettings.readFile(stream); - } - file.close(); - } - - - MainDialog mainWin(gameSettings, graphicsSettings, launcherSettings); + MainDialog mainWin; if (mainWin.setup()) { mainWin.show(); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 15f2690da..77526677b 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -1,9 +1,6 @@ #include -#include "settings/gamesettings.hpp" -#include "settings/graphicssettings.hpp" -#include "settings/launchersettings.hpp" - +#include "utils/checkablemessagebox.hpp" #include "utils/profilescombobox.hpp" #include "maindialog.hpp" @@ -11,13 +8,8 @@ #include "graphicspage.hpp" #include "datafilespage.hpp" -MainDialog::MainDialog(GameSettings &gameSettings, - GraphicsSettings &graphicsSettings, - LauncherSettings &launcherSettings) - : mGameSettings(gameSettings) - , mGraphicsSettings(graphicsSettings) - , mLauncherSettings(launcherSettings) - +MainDialog::MainDialog() + : mGameSettings(mCfgMgr) { QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); @@ -95,7 +87,6 @@ MainDialog::MainDialog(GameSettings &gameSettings, connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); createIcons(); - createPages(); } void MainDialog::createIcons() @@ -161,14 +152,148 @@ void MainDialog::createPages() } +bool MainDialog::showFirstRunDialog() +{ + CheckableMessageBox msgBox(this); + msgBox.setWindowTitle(tr("Morrowind installation detected")); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion); + 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 = + msgBox.addButton(tr("Skip"), QDialogButtonBox::RejectRole); + + 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.setCheckBoxText(tr("Include selected masters and plugins (creates a new profile)")); + msgBox.exec(); + + + if (msgBox.clickedButton() == importerButton) { + + QString iniPath; + + 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"))) + iniPath = dir.absoluteFilePath(QString("Morrowind.ini")); + } + + if (iniPath.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; + } + + // Create the file if it doesn't already exist, else the importer will fail + QString path = QString::fromStdString(mCfgMgr.getUserPath().string()) + QString("openmw.cfg"); + QFile file(path); + + if (!file.exists()) { + if (!file.open(QIODevice::ReadWrite)) { + // File cannot be created + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not open or create %0 for writing

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return false; + } + + file.close(); + } + + // Construct the arguments to run the importer + QStringList arguments; + + if (msgBox.isChecked()) + arguments.append(QString("-g")); + + arguments.append(iniPath); + arguments.append(path); + + if (!startProgram(QString("mwiniimport"), arguments, false)) + return false; + + // Re-read the game settings + mGameSettings.clear(); + + if (!setupGameSettings()) + return false; + + // Add a new profile + if (msgBox.isChecked()) { + qDebug() << "add a new profile"; + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), QString("Imported")); + + mLauncherSettings.remove(QString("Profiles/Imported/master")); + mLauncherSettings.remove(QString("Profiles/Imported/plugin")); + + QStringList masters = mGameSettings.values(QString("master")); + QStringList plugins = mGameSettings.values(QString("plugin")); + + foreach (const QString &master, masters) { + mLauncherSettings.setMultiValue(QString("Profiles/Imported/master"), master); + } + + foreach (const QString &plugin, plugins) { + mLauncherSettings.setMultiValue(QString("Profiles/Imported/plugin"), plugin); + } + } + + } + + return true; +} bool MainDialog::setup() { - // Call this so we can exit on Ogre errors before mainwindow is shown - if (!mGraphicsPage->setupOgre()) { + if (!setupLauncherSettings()) return false; + + if (!setupGameSettings()) + return false; + + if (!setupGraphicsSettings()) + return false; + + // Check if we need to show the importer + if (mLauncherSettings.value(QString("General/firstrun"), QString("true")) == QLatin1String("true")) + { + if (!showFirstRunDialog()) + return false; } + // Now create the pages as they need the settings + createPages(); + + // Call this so we can exit on Ogre errors before mainwindow is shown + if (!mGraphicsPage->setupOgre()) + return false; + loadSettings(); return true; } @@ -181,6 +306,164 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) mPagesWidget->setCurrentIndex(mIconWidget->row(current)); } +bool MainDialog::setupLauncherSettings() +{ + QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); + + QStringList paths; + paths.append(QString("launcher.cfg")); + paths.append(userPath + QString("launcher.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error opening OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return false; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mLauncherSettings.readFile(stream); + } + file.close(); + } + + return true; +} + +bool MainDialog::setupGameSettings() +{ + QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); + QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string()); + + QStringList paths; + paths.append(userPath + QString("openmw.cfg")); + paths.append(QString("openmw.cfg")); + paths.append(globalPath + QString("openmw.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error opening OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return false; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mGameSettings.readFile(stream); + } + file.close(); + } + + if (mGameSettings.getDataDirs().isEmpty()) + { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error detecting Morrowind installation")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Cancel); + msgBox.setText(QObject::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(QObject::tr("B&rowse..."), QMessageBox::ActionRole); + + msgBox.exec(); + + QString selectedFile; + if (msgBox.clickedButton() == dirSelectButton) { + selectedFile = QFileDialog::getOpenFileName( + NULL, + QObject::tr("Select master file"), + QDir::currentPath(), + QString(tr("Morrowind master file (*.esm)"))); + } + + if (selectedFile.isEmpty()) + return false; // Cancel was clicked; + + qDebug() << selectedFile; + QFileInfo info(selectedFile); + + // Add the new dir to the settings file and to the data dir container + mGameSettings.setValue(QString("data"), info.absolutePath()); + mGameSettings.addDataDir(info.absolutePath()); + + } + + return true; +} + +bool MainDialog::setupGraphicsSettings() +{ + QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); + QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string()); + + QFile localDefault(QString("settings-default.cfg")); + QFile globalDefault(globalPath + QString("settings-default.cfg")); + + if (!localDefault.exists() && !globalDefault.exists()) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error reading OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not find settings-default.cfg

\ + The problem may be due to an incomplete installation of OpenMW.
\ + Reinstalling OpenMW may resolve the problem.")); + msgBox.exec(); + return false; + } + + + QStringList paths; + paths.append(globalPath + QString("settings-default.cfg")); + paths.append(QString("settings-default.cfg")); + paths.append(userPath + QString("settings.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error opening OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return false; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mGraphicsSettings.readFile(stream); + } + file.close(); + } + + return true; +} + void MainDialog::loadSettings() { int width = mLauncherSettings.value(QString("General/MainWindow/width")).toInt(); @@ -206,6 +489,9 @@ void MainDialog::saveSettings() mLauncherSettings.setValue(QString("General/MainWindow/posx"), posX); mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY); + + mLauncherSettings.setValue(QString("General/firstrun"), QString("false")); + } void MainDialog::writeSettings() @@ -221,7 +507,7 @@ void MainDialog::writeSettings() if (!dir.exists()) { if (!dir.mkpath(userPath)) { QMessageBox msgBox; - msgBox.setWindowTitle("Error creating OpenMW configuration directory"); + msgBox.setWindowTitle(tr("Error creating OpenMW configuration directory")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not create %0

\ @@ -238,7 +524,7 @@ void MainDialog::writeSettings() if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created QMessageBox msgBox; - msgBox.setWindowTitle("Error writing OpenMW configuration file"); + msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not open or create %0 for writing

\ @@ -260,7 +546,7 @@ void MainDialog::writeSettings() if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created QMessageBox msgBox; - msgBox.setWindowTitle("Error writing OpenMW configuration file"); + msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not open or create %0 for writing

\ @@ -282,7 +568,7 @@ void MainDialog::writeSettings() if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created QMessageBox msgBox; - msgBox.setWindowTitle("Error writing Launcher configuration file"); + msgBox.setWindowTitle(tr("Error writing Launcher configuration file")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not open or create %0 for writing

\ @@ -308,69 +594,108 @@ void MainDialog::closeEvent(QCloseEvent *event) void MainDialog::play() { - // First do a write of all the configs, just to be sure - //mDataFilesPage->writeConfig(); - //mGraphicsPage->writeConfig(); saveSettings(); writeSettings(); + // Launch the game detached + startProgram(QString("openmw"), true); + qApp->quit(); +} + +bool MainDialog::startProgram(const QString &name, const QStringList &arguments, bool detached) +{ + QString path = name; #ifdef Q_OS_WIN - QString game = "./openmw.exe"; - QFile file(game); + path.append(QString(".exe")); #elif defined(Q_OS_MAC) QDir dir(QCoreApplication::applicationDirPath()); - QString game = dir.absoluteFilePath("openmw"); - QFile file(game); - game = "\"" + game + "\""; + path = dir.absoluteFilePath(name); #else - QString game = "./openmw"; - QFile file(game); + path.prepend(QString("./")); #endif + QFile file(path); + QProcess process; QFileInfo info(file); if (!file.exists()) { QMessageBox msgBox; - msgBox.setWindowTitle("Error starting OpenMW"); + msgBox.setWindowTitle(tr("Error starting executable")); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not find OpenMW

\ - The OpenMW application is not found.
\ - Please make sure OpenMW is installed correctly and try again.
")); + msgBox.setText(tr("
Could not find %1

\ + The application is not found.
\ + Please make sure OpenMW is installed correctly and try again.
").arg(info.fileName())); msgBox.exec(); - return; + return false; } if (!info.isExecutable()) { QMessageBox msgBox; - msgBox.setWindowTitle("Error starting OpenMW"); + msgBox.setWindowTitle(tr("Error starting executable")); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not start OpenMW

\ - The OpenMW application is not executable.
\ - Please make sure you have the right permissions and try again.
")); + msgBox.setText(tr("
Could not start %1

\ + The application is not executable.
\ + Please make sure you have the right permissions and try again.
").arg(info.fileName())); msgBox.exec(); - return; + return false; } - // Start the game - if (!process.startDetached(game)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error starting OpenMW"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not start OpenMW

\ - An error occurred while starting OpenMW.

\ - Press \"Show Details...\" for more information.
")); - msgBox.setDetailedText(process.errorString()); - msgBox.exec(); + // Start the executable + if (detached) { + if (!process.startDetached(path, arguments)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error starting executable")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not start %1

\ + An error occurred while starting %1.

\ + Press \"Show Details...\" for more information.
").arg(info.fileName())); + msgBox.setDetailedText(process.errorString()); + msgBox.exec(); - return; + return false; + } } else { - qApp->quit(); + process.start(path, arguments); + if (!process.waitForFinished()) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error starting executable")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not start %1

\ + An error occurred while starting %1.

\ + Press \"Show Details...\" for more information.
").arg(info.fileName())); + msgBox.setDetailedText(process.errorString()); + msgBox.exec(); + + return false; + } + + if (process.exitCode() != 0) { + QString error(process.readAllStandardError()); + error.append(tr("\nArguments:\n")); + error.append(arguments.join(" ")); + + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error running executable")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Executable %1 returned an error

\ + An error occurred while running %1.

\ + Press \"Show Details...\" for more information.
").arg(info.fileName())); + msgBox.setDetailedText(error); + msgBox.exec(); + + return false; + } } + + return true; + } diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 7167d101d..f221bd5e6 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -5,6 +5,10 @@ #include +#include "settings/gamesettings.hpp" +#include "settings/graphicssettings.hpp" +#include "settings/launchersettings.hpp" + class QListWidget; class QListWidgetItem; class QStackedWidget; @@ -16,20 +20,20 @@ class PlayPage; class GraphicsPage; class DataFilesPage; -class GameSettings; -class GraphicsSettings; -class LauncherSettings; - class MainDialog : public QMainWindow { Q_OBJECT public: - MainDialog(GameSettings &gameSettings, - GraphicsSettings &GraphicsSettings, - LauncherSettings &launcherSettings); + MainDialog(); + + +// GameSettings &gameSettings, +// GraphicsSettings &GraphicsSettings, +// LauncherSettings &launcherSettings); bool setup(); + bool showFirstRunDialog(); public slots: void changePage(QListWidgetItem *current, QListWidgetItem *previous); @@ -39,10 +43,17 @@ private: void createIcons(); void createPages(); + bool setupLauncherSettings(); + bool setupGameSettings(); + bool setupGraphicsSettings(); + void loadSettings(); void saveSettings(); void writeSettings(); + inline bool startProgram(const QString &name, bool detached = false) { return startProgram(name, QStringList(), detached); } + bool startProgram(const QString &name, const QStringList &arguments, bool detached = false); + void closeEvent(QCloseEvent *event); QListWidget *mIconWidget; @@ -54,9 +65,9 @@ private: Files::ConfigurationManager mCfgMgr; - GameSettings &mGameSettings; - GraphicsSettings &mGraphicsSettings; - LauncherSettings &mLauncherSettings; + GameSettings mGameSettings; + GraphicsSettings mGraphicsSettings; + LauncherSettings mLauncherSettings; }; diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index fcf6f8b8a..20ccebc97 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -25,6 +25,7 @@ void GameSettings::validatePaths() return; QStringList paths = mSettings.values(QString("data")); + qDebug() << "paths " << paths; Files::PathContainer dataDirs; foreach (const QString &path, paths) { @@ -63,9 +64,6 @@ void GameSettings::validatePaths() if (dir.exists()) mDataLocal = path; } - qDebug() << mSettings; - - } QStringList GameSettings::values(const QString &key, const QStringList &defaultValues) @@ -91,18 +89,24 @@ bool GameSettings::readFile(QTextStream &stream) QString key = keyRe.cap(1).simplified(); QString value = keyRe.cap(2).simplified(); - // There can be multiple keys - if (key == QLatin1String("data") || - key == QLatin1String("master") || - key == QLatin1String("plugin")) - { - // Remove keys from previous config and overwrite them - mSettings.remove(key); - QStringList values = cache.values(key); - if (!values.contains(value)) // Do not insert duplicate values - cache.insertMulti(key, value); - } else { - cache.insert(key, value); +// // There can be multiple keys +// if (key == QLatin1String("data") || +// key == QLatin1String("master") || +// key == QLatin1String("plugin")) +// { +// // Remove keys from previous config and overwrite them +// mSettings.remove(key); +// QStringList values = cache.values(key); +// if (!values.contains(value)) // Do not insert duplicate values +// cache.insertMulti(key, value); +// } else { +// cache.insert(key, value); +// } + mSettings.remove(key); + + QStringList values = cache.values(key); + if (!values.contains(value)) { + cache.insertMulti(key, value); } } } diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index 8aac1552d..fa62872b0 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -41,6 +41,11 @@ public: mSettings.remove(key); } + inline void clear() + { + mSettings.clear(); + } + inline QStringList getDataDirs() { return mDataDirs; } inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); } inline QString getDataLocal() {return mDataLocal; } diff --git a/apps/launcher/utils/checkablemessagebox.cpp b/apps/launcher/utils/checkablemessagebox.cpp index 8aa01d101..990835594 100644 --- a/apps/launcher/utils/checkablemessagebox.cpp +++ b/apps/launcher/utils/checkablemessagebox.cpp @@ -1,3 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "checkablemessagebox.hpp" + #include #include @@ -14,21 +45,17 @@ #include #include -#include "checkablemessagebox.hpp" +/*! + \class Utils::CheckableMessageBox -/* - class CheckableMessageBox - Modified from the one used in Qt Creator - - A messagebox suitable for questions with a - "Do not ask me again" checkbox. + \brief A messagebox suitable for questions with a + "Do not ask me again" checkbox. Emulates the QMessageBox API with static conveniences. The message label can open external URLs. */ - class CheckableMessageBoxPrivate { public: diff --git a/apps/launcher/utils/checkablemessagebox.hpp b/apps/launcher/utils/checkablemessagebox.hpp index ceb437d4d..93fd43fe1 100644 --- a/apps/launcher/utils/checkablemessagebox.hpp +++ b/apps/launcher/utils/checkablemessagebox.hpp @@ -1,3 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + #ifndef CHECKABLEMESSAGEBOX_HPP #define CHECKABLEMESSAGEBOX_HPP @@ -22,13 +51,13 @@ public: virtual ~CheckableMessageBox(); static QDialogButtonBox::StandardButton - question(QWidget *parent, - const QString &title, - const QString &question, - const QString &checkBoxText, - bool *checkBoxSetting, - QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No, - QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No); + question(QWidget *parent, + const QString &title, + const QString &question, + const QString &checkBoxText, + bool *checkBoxSetting, + QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No, + QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No); QString text() const; void setText(const QString &); From 63a13cf9cac94f8b642d61b2c9c11f193c8098ad Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 20 Feb 2013 19:29:12 +0100 Subject: [PATCH 053/151] Whoops, removed an include --- apps/launcher/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 5d57dce55..a5c6e30a5 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,4 +1,5 @@ #include +#include #include "maindialog.hpp" From 5b099393faa2c3cfe4cd4df051f93b452b8a36c7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 23 Feb 2013 04:43:51 +0100 Subject: [PATCH 054/151] Fix time factor --- apps/openmw/mwrender/refraction.cpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index 67fe9e340..64234cc57 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -33,7 +33,7 @@ namespace MWRender vp->setShadowsEnabled(false); vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Sky); vp->setMaterialScheme("water_refraction"); - vp->setBackgroundColour (Ogre::ColourValue(0.0078, 0.0576, 0.150)); + vp->setBackgroundColour (Ogre::ColourValue(0.180, 0.235, 0.22352)); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c4f2d99cb..5baa8e7cc 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -349,9 +349,10 @@ void RenderingManager::update (float duration, bool paused) mRendering.update(duration); + Ogre::ControllerManager::getSingleton().setTimeFactor(paused ? 0.f : 1.f); + if(paused) { - Ogre::ControllerManager::getSingleton().setTimeFactor(0.f); return; } @@ -520,8 +521,8 @@ void RenderingManager::configureFog(MWWorld::Ptr::CellStore &mCell) configureFog(mCell.mCell->mAmbi.mFogDensity, color); - if (mWater) - mWater->setViewportBackground (Ogre::ColourValue(0.8f, 0.9f, 1.0f)); + //if (mWater) + // mWater->setViewportBackground (Ogre::ColourValue(0.8f, 0.9f, 1.0f)); } void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour) From 01102f9c73b9e28e1fc23928f5123cd2409831f7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 23 Feb 2013 05:53:20 +0100 Subject: [PATCH 055/151] Don't emit if there wasn't enough movement --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- apps/openmw/mwrender/ripplesimulation.cpp | 13 +++++++++++-- apps/openmw/mwrender/ripplesimulation.hpp | 4 +++- apps/openmw/mwrender/water.cpp | 6 ++++++ apps/openmw/mwrender/water.hpp | 2 ++ files/materials/watersim_heightmap.shader | 2 +- 6 files changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 5baa8e7cc..c9f7603be 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -376,7 +376,7 @@ void RenderingManager::update (float duration, bool paused) float *fpos = data.getPosition().pos; // only for LocalMap::updatePlayer() - Ogre::Vector3 pos(fpos[0], -fpos[2], -fpos[1]); + Ogre::Vector3 pos(fpos[0], fpos[2], -fpos[1]); Ogre::SceneNode *node = data.getBaseNode(); Ogre::Quaternion orient = diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index 249397005..6c9264b60 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -21,7 +21,8 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) mRippleAreaLength(1000), mImpulseSize(20), mTexelOffset(0,0), - mFirstUpdate(true) + mFirstUpdate(true), + mLastPos(0,0) { Ogre::AxisAlignedBox aabInf; aabInf.setInfinite(); @@ -141,8 +142,16 @@ void RippleSimulation::update(float dt, Ogre::Vector2 position) new sh::Vector3(mRippleCenter.x + mTexelOffset.x, mRippleCenter.y + mTexelOffset.y, 0))); } -void RippleSimulation::addImpulse(Ogre::Vector2 position) +void RippleSimulation::addImpulse(Ogre::Vector2 position, float scale, float force) { + // don't emit if there wasn't enough movement + /// \todo this should be done somewhere else, otherwise multiple emitters cannot be supported + if ((position - mLastPos).length () <= 2) + return; + + mLastPos = position; + + /// \todo scale, force mImpulses.push(position); } diff --git a/apps/openmw/mwrender/ripplesimulation.hpp b/apps/openmw/mwrender/ripplesimulation.hpp index c792a3214..2f8cae24f 100644 --- a/apps/openmw/mwrender/ripplesimulation.hpp +++ b/apps/openmw/mwrender/ripplesimulation.hpp @@ -24,7 +24,7 @@ public: void update(float dt, Ogre::Vector2 position); - void addImpulse (Ogre::Vector2 position); + void addImpulse (Ogre::Vector2 position, float scale = 1.f, float force = 1.f); private: Ogre::RenderTexture* mRenderTargets[4]; @@ -34,6 +34,8 @@ private: float mRippleAreaLength; float mImpulseSize; + Ogre::Vector2 mLastPos; + bool mFirstUpdate; Ogre::Camera* mCamera; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index f0680f208..33b6733ba 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -499,4 +499,10 @@ void Water::createdConfiguration (sh::MaterialInstance* m, const std::string& co } } +void Water::addImpulse (Vector2 position, float scale, float force) +{ + if (mSimulation) + mSimulation->addImpulse (position, scale, force); +} + } // namespace diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 6100b7cfd..eb7d98f5d 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -146,6 +146,8 @@ namespace MWRender { void toggle(); void update(float dt, Ogre::Vector3 player); + void addImpulse (Ogre::Vector2 position, float scale = 1.f, float force = 1.f); + void setViewportBackground(const Ogre::ColourValue& bg); void processChangedSettings(const Settings::CategorySettingVector& settings); diff --git a/files/materials/watersim_heightmap.shader b/files/materials/watersim_heightmap.shader index e19270d39..50d375efe 100644 --- a/files/materials/watersim_heightmap.shader +++ b/files/materials/watersim_heightmap.shader @@ -1,6 +1,6 @@ #include "core.h" -#define DAMPING 0.92 +#define DAMPING 0.95 #include "watersim_common.h" From 7046e7ae3def07d41d314bbbdb034c45a3e12f64 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 23 Feb 2013 09:02:05 +0100 Subject: [PATCH 056/151] Water fog fix --- files/materials/water.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/materials/water.shader b/files/materials/water.shader index ac6b81240..09788d45b 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -295,7 +295,7 @@ } else { - float fogValue = shSaturate((length(cameraPos.xyz-position.xyz) - fogParams.y) * fogParams.w); + float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); } From 150d4a7a7292bd1d6cc86bcd4d3177635111e146 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sat, 23 Feb 2013 23:18:42 +0100 Subject: [PATCH 057/151] Added support for multiple ini files --- apps/launcher/maindialog.cpp | 23 +++++++++++++++++++---- apps/launcher/settings/gamesettings.cpp | 18 ++---------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 77526677b..c03a31fd5 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -180,7 +180,7 @@ bool MainDialog::showFirstRunDialog() if (msgBox.clickedButton() == importerButton) { - QString iniPath; + QStringList iniPaths; foreach (const QString &path, mGameSettings.getDataDirs()) { QDir dir(path); @@ -190,10 +190,10 @@ bool MainDialog::showFirstRunDialog() continue; // Cannot move from Data Files if (dir.exists(QString("Morrowind.ini"))) - iniPath = dir.absoluteFilePath(QString("Morrowind.ini")); + iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini"))); } - if (iniPath.isEmpty()) { + if (iniPaths.isEmpty()) { QMessageBox msgBox; msgBox.setWindowTitle(tr("Error reading Morrowind configuration file")); msgBox.setIcon(QMessageBox::Warning); @@ -205,6 +205,21 @@ bool MainDialog::showFirstRunDialog() return false; } + if (iniPaths.count() > 1) { + // Multiple Morrowind.ini files found + bool ok; + 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; + } + } + // Create the file if it doesn't already exist, else the importer will fail QString path = QString::fromStdString(mCfgMgr.getUserPath().string()) + QString("openmw.cfg"); QFile file(path); @@ -232,7 +247,7 @@ bool MainDialog::showFirstRunDialog() if (msgBox.isChecked()) arguments.append(QString("-g")); - arguments.append(iniPath); + arguments.append(iniPaths.first()); arguments.append(path); if (!startProgram(QString("mwiniimport"), arguments, false)) diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 20ccebc97..6b46a5160 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -21,11 +21,10 @@ GameSettings::~GameSettings() void GameSettings::validatePaths() { - if (mSettings.isEmpty()) - return; + if (mSettings.isEmpty() || !mDataDirs.isEmpty()) + return; // Don't re-validate paths if they are already parsed QStringList paths = mSettings.values(QString("data")); - qDebug() << "paths " << paths; Files::PathContainer dataDirs; foreach (const QString &path, paths) { @@ -89,19 +88,6 @@ bool GameSettings::readFile(QTextStream &stream) QString key = keyRe.cap(1).simplified(); QString value = keyRe.cap(2).simplified(); -// // There can be multiple keys -// if (key == QLatin1String("data") || -// key == QLatin1String("master") || -// key == QLatin1String("plugin")) -// { -// // Remove keys from previous config and overwrite them -// mSettings.remove(key); -// QStringList values = cache.values(key); -// if (!values.contains(value)) // Do not insert duplicate values -// cache.insertMulti(key, value); -// } else { -// cache.insert(key, value); -// } mSettings.remove(key); QStringList values = cache.values(key); From 9198afeefb3a50bcefe3ff4f4f56d22e63f73b90 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 24 Feb 2013 03:10:27 +0100 Subject: [PATCH 058/151] Improved context menu, added context menu for masters and added multi-selection support --- apps/launcher/datafilespage.cpp | 186 ++++++++++++++++++++------------ apps/launcher/datafilespage.hpp | 9 +- 2 files changed, 119 insertions(+), 76 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 4ecb67e4e..60e377afb 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -99,9 +99,10 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersTable = new QTableView(this); mMastersTable->setModel(mMastersProxyModel); mMastersTable->setObjectName("MastersTable"); + mMastersTable->setContextMenuPolicy(Qt::CustomContextMenu); mMastersTable->setSortingEnabled(false); mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection); + mMastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection); mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); mMastersTable->setAlternatingRowColors(true); mMastersTable->horizontalHeader()->setStretchLastSection(true); @@ -118,7 +119,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); mPluginsTable->setSortingEnabled(false); mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mPluginsTable->setSelectionMode(QAbstractItemView::SingleSelection); + mPluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); mPluginsTable->setAlternatingRowColors(true); mPluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); @@ -173,6 +174,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + connect(mMastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); @@ -208,15 +210,13 @@ void DataFilesPage::createActions() mProfileToolBar->addAction(mDeleteProfileAction); // Context menu actions - mCheckAction = new QAction(tr("Check selected"), this); + mCheckAction = new QAction(tr("Check Selection"), this); connect(mCheckAction, SIGNAL(triggered()), this, SLOT(check())); - mUncheckAction = new QAction(tr("Uncheck selected"), this); + mUncheckAction = new QAction(tr("Uncheck Selection"), this); connect(mUncheckAction, SIGNAL(triggered()), this, SLOT(uncheck())); - // Context menu for the plugins table mContextMenu = new QMenu(this); - mContextMenu->addAction(mCheckAction); mContextMenu->addAction(mUncheckAction); } @@ -296,6 +296,9 @@ void DataFilesPage::loadSettings() void DataFilesPage::saveSettings() { + if (mDataFilesModel->rowCount() < 1) + return; + QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); if (profile.isEmpty()) @@ -406,54 +409,21 @@ void DataFilesPage::deleteProfile() void DataFilesPage::check() { - // Check the current selection - if (!mPluginsTable->selectionModel()->hasSelection()) { - return; - } + if (mPluginsTable->hasFocus()) + setPluginsCheckstates(Qt::Checked); - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + if (mMastersTable->hasFocus()) + setMastersCheckstates(Qt::Checked); - //sort selection ascending because selectedIndexes returns an unsorted list - //qSort(indexes.begin(), indexes.end(), rowSmallerThan); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( - mFilterProxyModel->mapToSource(index)); - - if (!sourceIndex.isValid()) - return; - - mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); - } } void DataFilesPage::uncheck() { - // uncheck the current selection - if (!mPluginsTable->selectionModel()->hasSelection()) { - return; - } + if (mPluginsTable->hasFocus()) + setPluginsCheckstates(Qt::Unchecked); - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); - - //sort selection ascending because selectedIndexes returns an unsorted list - //qSort(indexes.begin(), indexes.end(), rowSmallerThan); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( - mFilterProxyModel->mapToSource(index)); - - if (!sourceIndex.isValid()) - return; - - mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked); - } + if (mMastersTable->hasFocus()) + setMastersCheckstates(Qt::Unchecked); } void DataFilesPage::refresh() @@ -464,6 +434,50 @@ void DataFilesPage::refresh() mPluginsTable->scrollToTop(); } +void DataFilesPage::setMastersCheckstates(Qt::CheckState state) +{ + if (!mMastersTable->selectionModel()->hasSelection()) { + return; + } + + QModelIndexList indexes = mMastersTable->selectionModel()->selectedIndexes(); + + foreach (const QModelIndex &index, indexes) + { + if (!index.isValid()) + return; + + QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index); + + if (!sourceIndex.isValid()) + return; + + mDataFilesModel->setCheckState(sourceIndex, state); + } +} + +void DataFilesPage::setPluginsCheckstates(Qt::CheckState state) +{ + if (!mPluginsTable->selectionModel()->hasSelection()) { + return; + } + + QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + + foreach (const QModelIndex &index, indexes) + { + if (!index.isValid()) + return; + + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + mDataFilesModel->setCheckState(sourceIndex, state); + } +} void DataFilesPage::setCheckState(QModelIndex index) { @@ -554,35 +568,69 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre void DataFilesPage::showContextMenu(const QPoint &point) { - // Make sure there are plugins in the view - if (!mPluginsTable->selectionModel()->hasSelection()) { + QObject *object = QObject::sender(); + + // Not a signal-slot call + if (!object) return; - } - QPoint globalPos = mPluginsTable->mapToGlobal(point); - - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); - - // Show the check/uncheck actions depending on the state of the selected items - mUncheckAction->setEnabled(false); - mCheckAction->setEnabled(false); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) + if (object->objectName() == QLatin1String("PluginsTable")) { + if (!mPluginsTable->selectionModel()->hasSelection()) return; - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( - mFilterProxyModel->mapToSource(index)); + QPoint globalPos = mPluginsTable->mapToGlobal(point); + QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); - if (!sourceIndex.isValid()) - return; + // Show the check/uncheck actions depending on the state of the selected items + mUncheckAction->setEnabled(false); + mCheckAction->setEnabled(false); - (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) - ? mUncheckAction->setEnabled(true) - : mCheckAction->setEnabled(true); + foreach (const QModelIndex &index, indexes) + { + if (!index.isValid()) + return; + + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mUncheckAction->setEnabled(true) + : mCheckAction->setEnabled(true); + } + + // Show menu + mContextMenu->exec(globalPos); } - // Show menu - mContextMenu->exec(globalPos); + if (object->objectName() == QLatin1String("MastersTable")) { + if (!mMastersTable->selectionModel()->hasSelection()) + return; + QPoint globalPos = mMastersTable->mapToGlobal(point); + QModelIndexList indexes = mMastersTable->selectionModel()->selectedIndexes(); + + // Show the check/uncheck actions depending on the state of the selected items + mUncheckAction->setEnabled(false); + mCheckAction->setEnabled(false); + + foreach (const QModelIndex &index, indexes) + { + if (!index.isValid()) + return; + + QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index); + + if (!sourceIndex.isValid()) + return; + + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mUncheckAction->setEnabled(true) + : mCheckAction->setEnabled(true); + } + + mContextMenu->exec(globalPos); + } } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 2561aa3d1..dd69d7489 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -37,7 +37,6 @@ public: public slots: void setCheckState(QModelIndex index); - void filterChanged(const QString filter); void showContextMenu(const QPoint &point); void profileChanged(const QString &previous, const QString ¤t); @@ -49,10 +48,6 @@ public slots: // Action slots void newProfile(); void deleteProfile(); -// void moveUp(); -// void moveDown(); -// void moveTop(); -// void moveBottom(); void check(); void uncheck(); void refresh(); @@ -90,8 +85,8 @@ private: TextInputDialog *mNewProfileDialog; -// const QStringList checkedPlugins(); -// const QStringList selectedMasters(); + void setMastersCheckstates(Qt::CheckState state); + void setPluginsCheckstates(Qt::CheckState state); void createActions(); void setupDataFiles(); From be43fa334f88a4271d1201cd392d5f000f81aede Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 24 Feb 2013 03:14:19 +0100 Subject: [PATCH 059/151] Added support for non-latin characters, fixes Bug #515 --- apps/launcher/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index a5c6e30a5..09da1d615 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "maindialog.hpp" @@ -29,6 +30,9 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); + // Support non-latin characters + QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); + MainDialog mainWin; if (mainWin.setup()) { From 4737b20e4cf46f0bb7165fb4a1e1d2d013aedde0 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 24 Feb 2013 04:00:22 +0100 Subject: [PATCH 060/151] Fixed a bug in the combobox popup font size, items overlapping --- apps/launcher/playpage.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp index cb993a8fa..1dbc1b9df 100644 --- a/apps/launcher/playpage.cpp +++ b/apps/launcher/playpage.cpp @@ -15,10 +15,15 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent) QLabel *profileLabel = new QLabel(tr("Current Profile:"), playWidget); profileLabel->setObjectName("ProfileLabel"); + // Hacks to get the stylesheet look properly on different platforms QPlastiqueStyle *style = new QPlastiqueStyle; + QFont font = QApplication::font(); + font.setPointSize(12); // Fixes problem with overlapping items + mProfilesComboBox = new QComboBox(playWidget); mProfilesComboBox->setObjectName("ProfilesComboBox"); mProfilesComboBox->setStyle(style); + mProfilesComboBox->setFont(font); QGridLayout *playLayout = new QGridLayout(playWidget); @@ -40,4 +45,4 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent) pageLayout->addWidget(playWidget); -} \ No newline at end of file +} From 919d1ee5728cd15527d73e38a5b875d84ffdc171 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 24 Feb 2013 04:14:18 +0100 Subject: [PATCH 061/151] Some fixes to the settings handlers --- apps/launcher/settings/gamesettings.cpp | 19 ++++--------------- apps/launcher/settings/settingsbase.hpp | 8 -------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 6b46a5160..c08179acc 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -88,7 +88,9 @@ bool GameSettings::readFile(QTextStream &stream) QString key = keyRe.cap(1).simplified(); QString value = keyRe.cap(2).simplified(); - mSettings.remove(key); + // Don't remove existing data entries + if (key != QLatin1String("data")) + mSettings.remove(key); QStringList values = cache.values(key); if (!values.contains(value)) { @@ -103,19 +105,6 @@ bool GameSettings::readFile(QTextStream &stream) return true; } - // Replace values from previous settings - QMapIterator i(cache); - while (i.hasNext()) { - i.next(); - - // Don't remove existing data entries - if (i.key() == QLatin1String("data")) - continue; - - if (mSettings.contains(i.key())) - mSettings.remove(i.key()); - } - // Merge the changed keys with those which didn't mSettings.unite(cache); validatePaths(); @@ -136,7 +125,7 @@ bool GameSettings::writeFile(QTextStream &stream) continue; // Quote paths with spaces - if (i.key() == QLatin1String("data") || i.key() == QLatin1String("data")) { + if (i.key() == QLatin1String("data")) { if (i.value().contains(" ")) { stream << i.key() << "=\"" << i.value() << "\"\n"; continue; diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index 321426eed..bbfad1fbb 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -85,14 +85,6 @@ public: return true; } - // Replace values from previous settings - QMapIterator i(mCache); - while (i.hasNext()) { - i.next(); - if (mSettings.contains(i.key())) - mSettings.remove(i.key()); - } - // Merge the changed keys with those which didn't mSettings.unite(mCache); return true; From 0d6a3367d3693adc7d760b77ec1766c7ee532fbd Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 24 Feb 2013 10:28:50 +0100 Subject: [PATCH 062/151] Water shader no longer depends on object shaders being enabled --- apps/openmw/mwgui/settingswindow.cpp | 35 +++++++++++----------------- files/materials/water.mat | 4 +++- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 54c2ef197..ebeb42ab2 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -264,16 +264,9 @@ namespace MWGui mRefractionButton->setCaptionWithReplacing (Settings::Manager::getBool("refraction", "Water") ? "#{sOn}" : "#{sOff}"); - if (!MWRender::RenderingManager::waterShaderSupported()) - { - mWaterShaderButton->setEnabled(false); - mReflectObjectsButton->setEnabled(false); - mReflectActorsButton->setEnabled(false); - mReflectTerrainButton->setEnabled(false); - } - if (!Settings::Manager::getBool("shaders", "Objects")) { + mRefractionButton->setEnabled(false); mUnderwaterButton->setEnabled (false); mShadowsEnabledButton->setEnabled(false); } @@ -466,15 +459,15 @@ namespace MWGui { Settings::Manager::setBool("shaders", "Objects", false); - // water shader not supported with object shaders off - mWaterShaderButton->setCaptionWithReplacing("#{sOff}"); mUnderwaterButton->setCaptionWithReplacing("#{sOff}"); - mWaterShaderButton->setEnabled(false); - mReflectObjectsButton->setEnabled(false); - mReflectActorsButton->setEnabled(false); - mReflectTerrainButton->setEnabled(false); + mUnderwaterButton->setEnabled(false); - Settings::Manager::setBool("shader", "Water", false); + + // refraction needs shaders to display underwater fog + mRefractionButton->setCaptionWithReplacing("#{sOff}"); + mRefractionButton->setEnabled(false); + + Settings::Manager::setBool("refraction", "Water", false); Settings::Manager::setBool("underwater effect", "Water", false); // shadows not supported @@ -487,13 +480,11 @@ namespace MWGui Settings::Manager::setBool("shaders", "Objects", true); // re-enable - if (MWRender::RenderingManager::waterShaderSupported()) - { - mWaterShaderButton->setEnabled(true); - mReflectObjectsButton->setEnabled(true); - mReflectActorsButton->setEnabled(true); - mReflectTerrainButton->setEnabled(true); - } + mReflectObjectsButton->setEnabled(true); + mReflectActorsButton->setEnabled(true); + mReflectTerrainButton->setEnabled(true); + mRefractionButton->setEnabled(true); + mUnderwaterButton->setEnabled(true); mShadowsEnabledButton->setEnabled(true); } diff --git a/files/materials/water.mat b/files/materials/water.mat index 7546606fc..372058f0a 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -1,5 +1,7 @@ material Water { + allow_fixed_function false + pass { emissive 1.0 1.0 1.0 @@ -44,7 +46,7 @@ material Water tex_address_mode border tex_border_colour 0.5 0.5 1.0 } - + // for simple_water texture_unit animatedTexture { From 2e6c63d9cd255f45a7e6ec8b1c78bc7a652954e1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 24 Feb 2013 17:18:22 +0100 Subject: [PATCH 063/151] Disable specular on NIF's --- components/nifogre/ogre_nif_loader.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index c3bbc141b..27926b7c4 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -575,9 +575,17 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String { ambient = m->data.ambient; diffuse = m->data.diffuse; - specular = m->data.specular; emissive = m->data.emissive; - glossiness = m->data.glossiness; + + + // Vanilla does not handle specular. TODO: Add an engine (or ESX file) configuration option + // to re-enable specular for future mods. Will also need to specify light specular colors somewhere. + // Also, not sure if glossiness value here is actually correct. OGRE expects 0-255 value, not sure what range this one is. + //glossiness = m->data.glossiness; + //specular = m->data.specular; + glossiness = 0; + specular = Ogre::Vector3(0,0,0); + alpha = m->data.alpha; } From 17a0a201dfe0281a8600fe30742bcd3e77ce9722 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 00:56:04 +0100 Subject: [PATCH 064/151] Various fixes and changes to the settings handling --- apps/launcher/datafilespage.cpp | 35 ++++++--------------- apps/launcher/graphicspage.cpp | 2 +- apps/launcher/settings/gamesettings.cpp | 32 +++++++++++++++++-- apps/launcher/settings/launchersettings.cpp | 8 +++++ 4 files changed, 48 insertions(+), 29 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 60e377afb..a0df2fb82 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -19,23 +19,6 @@ #include "datafilespage.hpp" -#include -/** - * Workaround for problems with whitespaces in paths in older versions of Boost library - */ -#if (BOOST_VERSION <= 104600) -namespace boost -{ - - template<> - inline boost::filesystem::path lexical_cast(const std::string& arg) - { - return boost::filesystem::path(arg); - } - -} /* namespace boost */ -#endif /* (BOOST_VERSION <= 104600) */ - using namespace ESM; using namespace std; @@ -241,7 +224,7 @@ void DataFilesPage::setupDataFiles() mDataFilesModel->sort(3); QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); - QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); mProfilesComboBox->setCurrentIndex(-1); mProfilesComboBox->addItems(profiles); @@ -271,7 +254,7 @@ void DataFilesPage::setupDataFiles() void DataFilesPage::loadSettings() { - QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); if (profile.isEmpty()) return; @@ -299,10 +282,12 @@ void DataFilesPage::saveSettings() if (mDataFilesModel->rowCount() < 1) return; - QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); - if (profile.isEmpty()) - return; + if (profile.isEmpty()) { + profile = mProfilesComboBox->currentText(); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile); + } mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); @@ -539,9 +524,9 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre return; // Profile was deleted // Store the previous profile - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), previous); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), previous); saveSettings(); - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), current); loadSettings(); } @@ -552,7 +537,7 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre return; // Save the new profile name - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), current); saveSettings(); // Remove the old one diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 49002e87e..b5a00b14c 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -196,7 +196,7 @@ void GraphicsPage::loadSettings() resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); - qDebug() << "resolution from file: " << resolution; + if (resIndex != -1) mResolutionComboBox->setCurrentIndex(resIndex); } diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index c08179acc..af78757b7 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -8,6 +8,23 @@ #include +#include +/** + * Workaround for problems with whitespaces in paths in older versions of Boost library + */ +#if (BOOST_VERSION <= 104600) +namespace boost +{ + + template<> + inline boost::filesystem::path lexical_cast(const std::string& arg) + { + return boost::filesystem::path(arg); + } + +} /* namespace boost */ +#endif /* (BOOST_VERSION <= 104600) */ + #include "gamesettings.hpp" GameSettings::GameSettings(Files::ConfigurationManager &cfg) @@ -93,6 +110,8 @@ bool GameSettings::readFile(QTextStream &stream) mSettings.remove(key); QStringList values = cache.values(key); + values.append(mSettings.values(key)); + if (!values.contains(value)) { cache.insertMulti(key, value); } @@ -125,9 +144,16 @@ bool GameSettings::writeFile(QTextStream &stream) continue; // Quote paths with spaces - if (i.key() == QLatin1String("data")) { - if (i.value().contains(" ")) { - stream << i.key() << "=\"" << i.value() << "\"\n"; + if (i.key() == QLatin1String("data") + || i.key() == QLatin1String("data-local") + || i.key() == QLatin1String("resources")) + { + if (i.value().contains(QChar(' '))) + { + QString stripped = i.value(); + stripped.remove(QChar('\"')); // Remove quotes + + stream << i.key() << "=\"" << stripped << "\"\n"; continue; } } diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index e9730c235..ee529d891 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -66,6 +66,7 @@ bool LauncherSettings::writeFile(QTextStream &stream) QString sectionPrefix; QRegExp sectionRe("([^/]+)/(.+)$"); QMap settings = SettingsBase::getSettings(); + qDebug() << "writing " << settings; QMapIterator i(settings); i.toBack(); @@ -81,6 +82,13 @@ bool LauncherSettings::writeFile(QTextStream &stream) key = sectionRe.cap(2); } + // Get rid of legacy settings + if (key.contains(QChar('\\'))) + continue; + + if (key == QLatin1String("CurrentProfile")) + continue; + if (sectionPrefix != prefix) { sectionPrefix = prefix; stream << "\n[" << prefix << "]\n"; From a0007325ad7a2d4eb1af4328fe7f185586340c62 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 01:22:14 +0100 Subject: [PATCH 065/151] Added a warning when stylesheet cannot be read and check if data paths contain masters/plugins --- apps/launcher/datafilespage.cpp | 4 +- apps/launcher/maindialog.cpp | 42 +++++++++++++++------ apps/launcher/settings/graphicssettings.cpp | 2 - apps/launcher/settings/launchersettings.cpp | 1 - apps/launcher/utils/checkablemessagebox.cpp | 1 - apps/launcher/utils/profilescombobox.cpp | 3 -- apps/launcher/utils/textinputdialog.cpp | 1 - 7 files changed, 33 insertions(+), 21 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index a0df2fb82..f8ccf3e83 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -226,8 +226,8 @@ void DataFilesPage::setupDataFiles() QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); - mProfilesComboBox->setCurrentIndex(-1); - mProfilesComboBox->addItems(profiles); + if (!profiles.isEmpty()) + mProfilesComboBox->addItems(profiles); // Add the current profile if empty if (mProfilesComboBox->findText(profile) == -1) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index c03a31fd5..c1e70bb3f 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -78,10 +78,20 @@ MainDialog::MainDialog() file.setFileName(QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.qss").string())); } - file.open(QFile::ReadOnly); - QString styleSheet = QLatin1String(file.readAll()); - qApp->setStyleSheet(styleSheet); - file.close(); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error opening Launcher stylesheet")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + } else { + QString styleSheet = QLatin1String(file.readAll()); + qApp->setStyleSheet(styleSheet); + file.close(); + } connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); @@ -261,7 +271,6 @@ bool MainDialog::showFirstRunDialog() // Add a new profile if (msgBox.isChecked()) { - qDebug() << "add a new profile"; mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), QString("Imported")); mLauncherSettings.remove(QString("Profiles/Imported/master")); @@ -330,7 +339,7 @@ bool MainDialog::setupLauncherSettings() paths.append(userPath + QString("launcher.cfg")); foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; + qDebug() << "Loading config file:" << qPrintable(path); QFile file(path); if (file.exists()) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -366,7 +375,8 @@ bool MainDialog::setupGameSettings() paths.append(globalPath + QString("openmw.cfg")); foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; + qDebug() << "Loading config file:" << qPrintable(path); + QFile file(path); if (file.exists()) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -388,7 +398,19 @@ bool MainDialog::setupGameSettings() file.close(); } - if (mGameSettings.getDataDirs().isEmpty()) + QStringList dataDirs; + + // Check if the paths actually contain data files + foreach (const QString path, mGameSettings.getDataDirs()) { + QDir dir(path); + QStringList filters; + filters << "*.esp" << "*.esm"; + + if (!dir.entryList(filters).isEmpty()) + dataDirs.append(path); + } + + if (dataDirs.isEmpty()) { QMessageBox msgBox; msgBox.setWindowTitle(tr("Error detecting Morrowind installation")); @@ -415,13 +437,11 @@ bool MainDialog::setupGameSettings() if (selectedFile.isEmpty()) return false; // Cancel was clicked; - qDebug() << selectedFile; QFileInfo info(selectedFile); // Add the new dir to the settings file and to the data dir container mGameSettings.setValue(QString("data"), info.absolutePath()); mGameSettings.addDataDir(info.absolutePath()); - } return true; @@ -454,7 +474,7 @@ bool MainDialog::setupGraphicsSettings() paths.append(userPath + QString("settings.cfg")); foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; + qDebug() << "Loading config file:" << qPrintable(path); QFile file(path); if (file.exists()) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { diff --git a/apps/launcher/settings/graphicssettings.cpp b/apps/launcher/settings/graphicssettings.cpp index fd70917b5..a92477ebb 100644 --- a/apps/launcher/settings/graphicssettings.cpp +++ b/apps/launcher/settings/graphicssettings.cpp @@ -3,8 +3,6 @@ #include #include -#include - #include "graphicssettings.hpp" GraphicsSettings::GraphicsSettings() diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index ee529d891..1101a80b9 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -66,7 +66,6 @@ bool LauncherSettings::writeFile(QTextStream &stream) QString sectionPrefix; QRegExp sectionRe("([^/]+)/(.+)$"); QMap settings = SettingsBase::getSettings(); - qDebug() << "writing " << settings; QMapIterator i(settings); i.toBack(); diff --git a/apps/launcher/utils/checkablemessagebox.cpp b/apps/launcher/utils/checkablemessagebox.cpp index 990835594..41207a8de 100644 --- a/apps/launcher/utils/checkablemessagebox.cpp +++ b/apps/launcher/utils/checkablemessagebox.cpp @@ -29,7 +29,6 @@ #include "checkablemessagebox.hpp" -#include #include #include diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index 4c258dae6..c3ff953ae 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -67,8 +66,6 @@ void ProfilesComboBox::slotEditingFinished() QString current = currentText(); QString previous = itemText(currentIndex()); - qDebug() << current << previous; - if (currentIndex() == -1) return; diff --git a/apps/launcher/utils/textinputdialog.cpp b/apps/launcher/utils/textinputdialog.cpp index 09b26ae75..011e51bf2 100644 --- a/apps/launcher/utils/textinputdialog.cpp +++ b/apps/launcher/utils/textinputdialog.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include From c4ebdc230c4ed65a6d6d6be7d212376ad4ba0ccf Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 01:28:13 +0100 Subject: [PATCH 066/151] Cleaned up strings and indentation --- apps/launcher/maindialog.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index c1e70bb3f..c91ffa070 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -60,22 +60,22 @@ MainDialog::MainDialog() // Check if the font is installed if (!fonts.contains("EB Garamond")) { - QString font = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/mygui/EBGaramond-Regular.ttf").string()); - file.setFileName(font); + QString font = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf"); + file.setFileName(font); - if (!file.exists()) { - font = QString::fromStdString((mCfgMgr.getLocalPath() / "resources/mygui/EBGaramond-Regular.ttf").string()); - } + if (!file.exists()) { + font = QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf"); + } - fontDatabase.addApplicationFont(font); + fontDatabase.addApplicationFont(font); } // Load the stylesheet - QString config = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/launcher.qss").string()); + QString config = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/launcher.qss"); file.setFileName(config); if (!file.exists()) { - file.setFileName(QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.qss").string())); + file.setFileName(QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("launcher.qss")); } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { From 8aff033a0cc8bc7921e681b7bc2bf5d2a7b30599 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 25 Feb 2013 18:29:11 +0100 Subject: [PATCH 067/151] Atmosphere no longer does "real" alpha blending to blend with the horizon, this is in preparation for proper underwater viewport BG / fog --- apps/openmw/mwrender/sky.cpp | 8 ++++++++ apps/openmw/mwrender/sky.hpp | 1 + files/materials/atmosphere.shader | 3 ++- files/materials/sky.mat | 1 - 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index ed34833e6..cda9ce6dd 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -255,6 +255,7 @@ void SkyManager::create() sh::Factory::getInstance().setSharedParameter ("nightFade", sh::makeProperty(new sh::FloatValue(0))); sh::Factory::getInstance().setSharedParameter ("atmosphereColour", sh::makeProperty(new sh::Vector4(0,0,0,1))); + sh::Factory::getInstance().setSharedParameter ("horizonColour", sh::makeProperty(new sh::Vector4(0,0,0,1))); sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", ""); sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", ""); @@ -488,6 +489,13 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) weather.mSkyColor.r, weather.mSkyColor.g, weather.mSkyColor.b, weather.mSkyColor.a))); } + if (mFogColour != weather.mFogColor) + { + mFogColour = weather.mFogColor; + sh::Factory::getInstance().setSharedParameter ("horizonColour", sh::makeProperty(new sh::Vector4( + weather.mFogColor.r, weather.mFogColor.g, weather.mFogColor.b, weather.mFogColor.a))); + } + mCloudSpeed = weather.mCloudSpeed; if (weather.mNight && mStarsOpacity != weather.mNightFade) diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 017eb4223..5a12b7ade 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -211,6 +211,7 @@ namespace MWRender float mStarsOpacity; Ogre::ColourValue mCloudColour; Ogre::ColourValue mSkyColour; + Ogre::ColourValue mFogColour; Ogre::Light* mLightning; diff --git a/files/materials/atmosphere.shader b/files/materials/atmosphere.shader index 5d71d7c32..eb05c3e18 100644 --- a/files/materials/atmosphere.shader +++ b/files/materials/atmosphere.shader @@ -18,10 +18,11 @@ SH_BEGIN_PROGRAM shInput(float, alphaFade) shUniform(float4, atmosphereColour) @shSharedParameter(atmosphereColour) + shUniform(float4, horizonColour) @shSharedParameter(horizonColour, horizonColour) SH_START_PROGRAM { - shOutputColour(0) = atmosphereColour * float4(1,1,1,alphaFade); + shOutputColour(0) = alphaFade * atmosphereColour + (1.f - alphaFade) * horizonColour; } #endif diff --git a/files/materials/sky.mat b/files/materials/sky.mat index 4af90a170..e50aa51d8 100644 --- a/files/materials/sky.mat +++ b/files/materials/sky.mat @@ -59,7 +59,6 @@ material openmw_atmosphere polygon_mode_overrideable off - scene_blend alpha_blend depth_write off } } From 9cd8dd39de31a902eafe118c9e293ee16f87218c Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 21:22:07 +0100 Subject: [PATCH 068/151] Make the launcher code conform to the coding standards and cleanup --- apps/launcher/datafilespage.cpp | 8 +++--- apps/launcher/graphicspage.cpp | 29 +++++++++++---------- apps/launcher/maindialog.cpp | 10 +++---- apps/launcher/playpage.cpp | 4 +-- apps/launcher/settings/gamesettings.cpp | 3 ++- apps/launcher/settings/graphicssettings.cpp | 4 +-- apps/launcher/settings/launchersettings.cpp | 4 +-- 7 files changed, 30 insertions(+), 32 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index f8ccf3e83..dd45c6602 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -1,3 +1,5 @@ +#include "datafilespage.hpp" + #include #include @@ -17,8 +19,6 @@ #include "utils/profilescombobox.hpp" #include "utils/textinputdialog.hpp" -#include "datafilespage.hpp" - using namespace ESM; using namespace std; @@ -216,9 +216,8 @@ void DataFilesPage::setupDataFiles() } QString dataLocal = mGameSettings.getDataLocal(); - if (!dataLocal.isEmpty()) { + if (!dataLocal.isEmpty()) mDataFilesModel->addFiles(dataLocal); - } // Sort by date accessed for now mDataFilesModel->sort(3); @@ -236,7 +235,6 @@ void DataFilesPage::setupDataFiles() if (mProfilesComboBox->findText(QString("Default")) == -1) mProfilesComboBox->addItem(QString("Default")); - if (profile.isEmpty() || profile == QLatin1String("Default")) { mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(QString("Default"))); } else { diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index b5a00b14c..741aacc9d 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -1,3 +1,5 @@ +#include "graphicspage.hpp" + #include #include @@ -10,7 +12,6 @@ #include #include "settings/graphicssettings.hpp" -#include "graphicspage.hpp" QString getAspect(int x, int y) { @@ -183,22 +184,22 @@ bool GraphicsPage::setupOgre() void GraphicsPage::loadSettings() { if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true")) - mVSyncCheckBox->setCheckState(Qt::Checked); + mVSyncCheckBox->setCheckState(Qt::Checked); - if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true")) - mFullScreenCheckBox->setCheckState(Qt::Checked); + if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true")) + mFullScreenCheckBox->setCheckState(Qt::Checked); - int aaIndex = mAntiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); - if (aaIndex != -1) - mAntiAliasingComboBox->setCurrentIndex(aaIndex); + int aaIndex = mAntiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); + if (aaIndex != -1) + mAntiAliasingComboBox->setCurrentIndex(aaIndex); - QString resolution = mGraphicsSettings.value(QString("Video/resolution x")); - resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); + QString resolution = mGraphicsSettings.value(QString("Video/resolution x")); + resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); - int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); + int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); - if (resIndex != -1) - mResolutionComboBox->setCurrentIndex(resIndex); + if (resIndex != -1) + mResolutionComboBox->setCurrentIndex(resIndex); } void GraphicsPage::saveSettings() @@ -215,8 +216,8 @@ void GraphicsPage::saveSettings() QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); if (resolutionRe.exactMatch(mResolutionComboBox->currentText().simplified())) { - mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); - mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); + mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); + mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); } } diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index c91ffa070..e69f134d2 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -1,9 +1,10 @@ +#include "maindialog.hpp" + #include #include "utils/checkablemessagebox.hpp" #include "utils/profilescombobox.hpp" -#include "maindialog.hpp" #include "playpage.hpp" #include "graphicspage.hpp" #include "datafilespage.hpp" @@ -74,9 +75,8 @@ MainDialog::MainDialog() QString config = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/launcher.qss"); file.setFileName(config); - if (!file.exists()) { + if (!file.exists()) file.setFileName(QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("launcher.qss")); - } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox msgBox; @@ -101,9 +101,8 @@ MainDialog::MainDialog() void MainDialog::createIcons() { - if (!QIcon::hasThemeIcon("document-new")) { + if (!QIcon::hasThemeIcon("document-new")) QIcon::setThemeName("tango"); - } // We create a fallback icon because the default fallback doesn't work QIcon graphicsIcon = QIcon(":/icons/tango/video-display.png"); @@ -733,4 +732,3 @@ bool MainDialog::startProgram(const QString &name, const QStringList &arguments, return true; } - diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp index 1dbc1b9df..b082e2e2c 100644 --- a/apps/launcher/playpage.cpp +++ b/apps/launcher/playpage.cpp @@ -1,7 +1,7 @@ -#include - #include "playpage.hpp" +#include + PlayPage::PlayPage(QWidget *parent) : QWidget(parent) { QWidget *playWidget = new QWidget(this); diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index af78757b7..56c08582f 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -1,3 +1,5 @@ +#include "gamesettings.hpp" + #include #include #include @@ -25,7 +27,6 @@ namespace boost } /* namespace boost */ #endif /* (BOOST_VERSION <= 104600) */ -#include "gamesettings.hpp" GameSettings::GameSettings(Files::ConfigurationManager &cfg) : mCfgMgr(cfg) diff --git a/apps/launcher/settings/graphicssettings.cpp b/apps/launcher/settings/graphicssettings.cpp index a92477ebb..0c5580091 100644 --- a/apps/launcher/settings/graphicssettings.cpp +++ b/apps/launcher/settings/graphicssettings.cpp @@ -1,10 +1,10 @@ +#include "graphicssettings.hpp" + #include #include #include #include -#include "graphicssettings.hpp" - GraphicsSettings::GraphicsSettings() { } diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index 1101a80b9..5d298e814 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -1,10 +1,10 @@ +#include "launchersettings.hpp" + #include #include #include #include -#include "launchersettings.hpp" - LauncherSettings::LauncherSettings() { } From b209b6a0e6cda392a3b7d78b12ecbdf7aa0838a9 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 22:00:51 +0100 Subject: [PATCH 069/151] Added missing includes --- apps/launcher/settings/gamesettings.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index fa62872b0..6c296711f 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -1,14 +1,13 @@ #ifndef GAMESETTINGS_HPP #define GAMESETTINGS_HPP +#include +#include +#include #include #include -class QTextStream; -class QStringList; -class QString; - namespace Files { typedef std::vector PathContainer; struct ConfigurationManager;} From a7102c143f2f44701c95e2824ab93a459bb5d162 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 26 Feb 2013 14:33:05 +0100 Subject: [PATCH 070/151] ESX variable type cleanup --- apps/openmw/mwworld/globals.cpp | 66 ++++++++++++++++----------------- components/esm/defs.hpp | 4 +- components/esm/loadglob.cpp | 4 +- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp index f010661b9..8742dd892 100644 --- a/apps/openmw/mwworld/globals.cpp +++ b/apps/openmw/mwworld/globals.cpp @@ -21,21 +21,21 @@ namespace MWWorld Globals::Collection::const_iterator Globals::find (const std::string& name) const { Collection::const_iterator iter = mVariables.find (name); - + if (iter==mVariables.end()) throw std::runtime_error ("unknown global variable: " + name); - - return iter; + + return iter; } Globals::Collection::iterator Globals::find (const std::string& name) { Collection::iterator iter = mVariables.find (name); - + if (iter==mVariables.end()) throw std::runtime_error ("unknown global variable: " + name); - - return iter; + + return iter; } Globals::Globals (const MWWorld::ESMStore& store) @@ -46,44 +46,44 @@ namespace MWWorld { char type = ' '; Data value; - + switch (iter->mType) { case ESM::VT_Short: - + type = 's'; value.mShort = *reinterpret_cast ( &iter->mValue); break; - - case ESM::VT_Int: - + + case ESM::VT_Long: + type = 'l'; value.mLong = *reinterpret_cast ( &iter->mValue); break; - + case ESM::VT_Float: - + type = 'f'; value.mFloat = *reinterpret_cast ( &iter->mValue); break; - + default: - + throw std::runtime_error ("unsupported global variable type"); - } + } mVariables.insert (std::make_pair (iter->mId, std::make_pair (type, value))); } - + if (mVariables.find ("dayspassed")==mVariables.end()) { // vanilla Morrowind does not define dayspassed. Data value; value.mLong = 0; - + mVariables.insert (std::make_pair ("dayspassed", std::make_pair ('l', value))); } } @@ -91,31 +91,31 @@ namespace MWWorld const Globals::Data& Globals::operator[] (const std::string& name) const { Collection::const_iterator iter = find (name); - + return iter->second.second; } Globals::Data& Globals::operator[] (const std::string& name) { Collection::iterator iter = find (name); - + return iter->second.second; } - + void Globals::setInt (const std::string& name, int value) { Collection::iterator iter = find (name); - + switch (iter->second.first) { case 's': iter->second.second.mShort = value; break; case 'l': iter->second.second.mLong = value; break; case 'f': iter->second.second.mFloat = value; break; - + default: throw std::runtime_error ("unsupported global variable type"); } } - + void Globals::setFloat (const std::string& name, float value) { Collection::iterator iter = find (name); @@ -127,9 +127,9 @@ namespace MWWorld case 'f': iter->second.second.mFloat = value; break; default: throw std::runtime_error ("unsupported global variable type"); - } + } } - + int Globals::getInt (const std::string& name) const { Collection::const_iterator iter = find (name); @@ -141,13 +141,13 @@ namespace MWWorld case 'f': return iter->second.second.mFloat; default: throw std::runtime_error ("unsupported global variable type"); - } + } } - + float Globals::getFloat (const std::string& name) const { Collection::const_iterator iter = find (name); - + switch (iter->second.first) { case 's': return iter->second.second.mShort; @@ -155,16 +155,16 @@ namespace MWWorld case 'f': return iter->second.second.mFloat; default: throw std::runtime_error ("unsupported global variable type"); - } + } } - + char Globals::getType (const std::string& name) const { Collection::const_iterator iter = mVariables.find (name); - + if (iter==mVariables.end()) return ' '; - + return iter->second.first; } } diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index aa870f925..143d90034 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -13,9 +13,9 @@ enum VarType { VT_Unknown, VT_None, - VT_Short, + VT_Short, // stored as a float, kinda VT_Int, - VT_Long, + VT_Long, // stored as a float VT_Float, VT_String, VT_Ignored diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index ceaa86948..429c6ff1d 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -12,7 +12,7 @@ void Global::load(ESMReader &esm) if (tmp == "s") mType = VT_Short; else if (tmp == "l") - mType = VT_Int; + mType = VT_Long; else if (tmp == "f") mType = VT_Float; else @@ -30,7 +30,7 @@ void Global::save(ESMWriter &esm) esm.writeHNString("FNAM", "s"); break; - case VT_Int: + case VT_Long: esm.writeHNString("FNAM", "l"); break; From 9b0ac4e2998facb18cd7b055d8371893c5588f89 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 27 Feb 2013 09:20:42 +0100 Subject: [PATCH 071/151] NPCs / creatures can now emit ripples --- apps/openmw/mwrender/actors.cpp | 9 ++ apps/openmw/mwrender/actors.hpp | 7 +- apps/openmw/mwrender/localmap.cpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 127 ++++++++++++---------- apps/openmw/mwrender/renderingmanager.hpp | 9 ++ apps/openmw/mwrender/ripplesimulation.cpp | 89 +++++++++++---- apps/openmw/mwrender/ripplesimulation.hpp | 22 +++- apps/openmw/mwrender/water.cpp | 26 +++-- apps/openmw/mwrender/water.hpp | 12 +- 9 files changed, 205 insertions(+), 98 deletions(-) diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index 83c07737c..644d3613b 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -6,6 +6,8 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/class.hpp" +#include "../mwrender/renderingmanager.hpp" + #include "animation.hpp" #include "activatoranimation.hpp" #include "creatureanimation.hpp" @@ -72,6 +74,7 @@ void Actors::insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv) NpcAnimation* anim = new NpcAnimation(ptr, ptr.getRefData().getBaseNode(), inv, RV_Actors); delete mAllActors[ptr]; mAllActors[ptr] = anim; + mRendering->addWaterRippleEmitter (ptr); } void Actors::insertCreature (const MWWorld::Ptr& ptr) { @@ -79,6 +82,7 @@ void Actors::insertCreature (const MWWorld::Ptr& ptr) CreatureAnimation* anim = new CreatureAnimation(ptr); delete mAllActors[ptr]; mAllActors[ptr] = anim; + mRendering->addWaterRippleEmitter (ptr); } void Actors::insertActivator (const MWWorld::Ptr& ptr) { @@ -90,6 +94,8 @@ void Actors::insertActivator (const MWWorld::Ptr& ptr) bool Actors::deleteObject (const MWWorld::Ptr& ptr) { + mRendering->removeWaterRippleEmitter (ptr); + delete mAllActors[ptr]; mAllActors.erase(ptr); @@ -120,6 +126,7 @@ void Actors::removeCell(MWWorld::Ptr::CellStore* store) { if(iter->first.getCell() == store) { + mRendering->removeWaterRippleEmitter (iter->first); delete iter->second; mAllActors.erase(iter++); } @@ -172,6 +179,8 @@ void Actors::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &cur) anim->updatePtr(cur); mAllActors[cur] = anim; } + + mRendering->updateWaterRippleEmitterPtr (old, cur); } } diff --git a/apps/openmw/mwrender/actors.hpp b/apps/openmw/mwrender/actors.hpp index 75a18ba91..bba2d945c 100644 --- a/apps/openmw/mwrender/actors.hpp +++ b/apps/openmw/mwrender/actors.hpp @@ -13,6 +13,7 @@ namespace MWWorld namespace MWRender { class Animation; + class RenderingManager; class Actors { @@ -20,13 +21,17 @@ namespace MWRender typedef std::map PtrAnimationMap; OEngine::Render::OgreRenderer &mRend; + MWRender::RenderingManager* mRendering; Ogre::SceneNode* mRootNode; CellSceneNodeMap mCellSceneNodes; PtrAnimationMap mAllActors; public: - Actors(OEngine::Render::OgreRenderer& _rend): mRend(_rend) {} + Actors(OEngine::Render::OgreRenderer& _rend, MWRender::RenderingManager* rendering) + : mRend(_rend) + , mRendering(rendering) + {} ~Actors(); void setRootNode(Ogre::SceneNode* root); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 8cf4ff123..8460d67aa 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -32,7 +32,7 @@ LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManag mLight = mRendering->getScene()->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); - mLight->setDirection (Ogre::Vector3(0.3, -0.7, 0.3)); + mLight->setDirection (Ogre::Vector3(0.3, 0.3, -0.7)); mLight->setVisible (false); mLight->setDiffuseColour (ColourValue(0.7,0.7,0.7)); } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 9ef705fde..943208a66 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -51,7 +51,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine) : mRendering(_rend) , mObjects(mRendering) - , mActors(mRendering) + , mActors(mRendering, this) , mAmbientMode(0) , mSunEnabled(0) , mPhysicsEngine(engine) @@ -136,7 +136,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water")); sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true"); - sh::Factory::getInstance ().setSharedParameter ("viewportBackground", sh::makeProperty (new sh::Vector3(0,0,0))); sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty (new sh::FloatValue(0.0))); sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(0))); sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(0))); @@ -173,6 +172,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mDebugging = new Debugging(mRootNode, engine); mLocalMap = new MWRender::LocalMap(&mRendering, this); + mWater = new MWRender::Water(mRendering.getCamera(), this); + setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } @@ -222,15 +223,12 @@ void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store) void RenderingManager::removeWater () { - if(mWater){ - mWater->setActive(false); - } + mWater->setActive(false); } void RenderingManager::toggleWater() { - if (mWater) - mWater->toggle(); + mWater->toggle(); } void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store) @@ -321,6 +319,20 @@ RenderingManager::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr & void RenderingManager::update (float duration, bool paused) { + MWBase::World *world = MWBase::Environment::get().getWorld(); + + // player position + MWWorld::RefData &data = + MWBase::Environment::get() + .getWorld() + ->getPlayer() + .getPlayer() + .getRefData(); + float *_playerPos = data.getPosition().pos; + Ogre::Vector3 playerPos(_playerPos[0], _playerPos[1], _playerPos[2]); + + Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); + Ogre::Vector3 orig, dest; mPlayer->setCameraDistance(); if (!mPlayer->getPosition(orig, dest)) { @@ -343,6 +355,17 @@ void RenderingManager::update (float duration, bool paused) Ogre::ControllerManager::getSingleton().setTimeFactor(paused ? 0.f : 1.f); + /* + if (world->isUnderwater (world->getPlayer().getPlayer().getCell(), cam)) + { + mFogColour = Ogre::ColourValue(0.18039, 0.23137, 0.25490); + mFogStart = 0; + mFogEnd = 1500; + } + */ + + applyFog(); + if(paused) { return; @@ -358,41 +381,21 @@ void RenderingManager::update (float duration, bool paused) mSkyManager->setGlare(mOcclusionQuery->getSunVisibility()); - MWWorld::RefData &data = - MWBase::Environment::get() - .getWorld() - ->getPlayer() - .getPlayer() - .getRefData(); - - float *fpos = data.getPosition().pos; - - // only for LocalMap::updatePlayer() - Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]); - Ogre::SceneNode *node = data.getBaseNode(); //Ogre::Quaternion orient = //node->convertLocalToWorldOrientation(node->_getDerivedOrientation()); Ogre::Quaternion orient = node->_getDerivedOrientation(); - mLocalMap->updatePlayer(pos, orient); + mLocalMap->updatePlayer(playerPos, orient); - if (mWater) { - Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); + mWater->updateUnderwater( + world->isUnderwater( + world->getPlayer().getPlayer().getCell(), + cam) + ); - MWBase::World *world = MWBase::Environment::get().getWorld(); - - mWater->updateUnderwater( - world->isUnderwater( - world->getPlayer().getPlayer().getCell(), - cam) - ); - - // MW to ogre coordinates - orig = Ogre::Vector3(orig.x, orig.z, -orig.y); - mWater->update(duration, orig); - } + mWater->update(duration, playerPos); } void RenderingManager::preRenderTargetUpdate(const RenderTargetEvent &evt) @@ -416,10 +419,7 @@ void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store) || ((store->mCell->isExterior()) && !lands.search(store->mCell->getGridX(),store->mCell->getGridY()) )) // always use water, if the cell does not have land. { - if(mWater == 0) - mWater = new MWRender::Water(mRendering.getCamera(), this, store->mCell); - else - mWater->changeCell(store->mCell); + mWater->changeCell(store->mCell); mWater->setActive(true); } else @@ -428,8 +428,7 @@ void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store) void RenderingManager::setWaterHeight(const float height) { - if (mWater) - mWater->setHeight(height); + mWater->setHeight(height); } void RenderingManager::skyEnable () @@ -521,24 +520,26 @@ void RenderingManager::configureFog(MWWorld::Ptr::CellStore &mCell) void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour) { + mFogColour = colour; float max = Settings::Manager::getFloat("max viewing distance", "Viewing distance"); - float low = max / (density) * Settings::Manager::getFloat("fog start factor", "Viewing distance"); - float high = max / (density) * Settings::Manager::getFloat("fog end factor", "Viewing distance"); - - mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high); - - mRendering.getCamera()->setFarClipDistance ( max / density ); - mRendering.getViewport()->setBackgroundColour (colour); - - if (mWater) - mWater->setViewportBackground (colour); - - sh::Factory::getInstance ().setSharedParameter ("viewportBackground", - sh::makeProperty (new sh::Vector3(colour.r, colour.g, colour.b))); + mFogStart = max / (density) * Settings::Manager::getFloat("fog start factor", "Viewing distance"); + mFogEnd = max / (density) * Settings::Manager::getFloat("fog end factor", "Viewing distance"); + mRendering.getCamera()->setFarClipDistance ( Settings::Manager::getFloat("max viewing distance", "Viewing distance") / density ); } +void RenderingManager::applyFog () +{ + mRendering.getScene()->setFog (FOG_LINEAR, mFogColour, 0, mFogStart, mFogEnd); + + mRendering.getViewport()->setBackgroundColour (mFogColour); + + mWater->setViewportBackground (mFogColour); + + sh::Factory::getInstance ().setSharedParameter ("viewportBackground", + sh::makeProperty (new sh::Vector3(mFogColour.r, mFogColour.g, mFogColour.b))); +} void RenderingManager::setAmbientMode() { @@ -826,8 +827,7 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } - if (mWater) - mWater->processChangedSettings(settings); + mWater->processChangedSettings(settings); if (rebuild) mObjects.rebuildStaticGeometry(); @@ -902,6 +902,8 @@ void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr) MWWorld::Class::get(ptr).getInventoryStore(ptr), RV_Actors ); mPlayer->setAnimation(anim); + mWater->removeEmitter (ptr); + mWater->addEmitter (ptr); } void RenderingManager::getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw) @@ -945,4 +947,19 @@ void RenderingManager::stopVideo() mVideoPlayer->stopVideo (); } +void RenderingManager::addWaterRippleEmitter (const MWWorld::Ptr& ptr, float scale, float force) +{ + mWater->addEmitter (ptr, scale, force); +} + +void RenderingManager::removeWaterRippleEmitter (const MWWorld::Ptr& ptr) +{ + mWater->removeEmitter (ptr); +} + +void RenderingManager::updateWaterRippleEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr) +{ + mWater->updateEmitterPtr(old, ptr); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 5d79f80aa..02d796fdd 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -163,6 +163,10 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void skySetMoonColour (bool red); void configureAmbient(MWWorld::CellStore &mCell); + void addWaterRippleEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f); + void removeWaterRippleEmitter (const MWWorld::Ptr& ptr); + void updateWaterRippleEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr); + void requestMap (MWWorld::CellStore* cell); ///< request the local map for a cell @@ -204,6 +208,7 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList sh::Factory* mFactory; void setAmbientMode(); + void applyFog(); void setMenuTransparency(float val); @@ -234,6 +239,10 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList Ogre::SceneNode *mRootNode; + Ogre::ColourValue mFogColour; + float mFogStart; + float mFogEnd; + OEngine::Physic::PhysicEngine* mPhysicsEngine; MWRender::Player *mPlayer; diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index 6c9264b60..47fbc8ddf 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -7,6 +7,11 @@ #include +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +#include "../mwworld/player.hpp" + namespace MWRender { @@ -21,8 +26,7 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) mRippleAreaLength(1000), mImpulseSize(20), mTexelOffset(0,0), - mFirstUpdate(true), - mLastPos(0,0) + mFirstUpdate(true) { Ogre::AxisAlignedBox aabInf; aabInf.setInfinite(); @@ -142,34 +146,39 @@ void RippleSimulation::update(float dt, Ogre::Vector2 position) new sh::Vector3(mRippleCenter.x + mTexelOffset.x, mRippleCenter.y + mTexelOffset.y, 0))); } -void RippleSimulation::addImpulse(Ogre::Vector2 position, float scale, float force) -{ - // don't emit if there wasn't enough movement - /// \todo this should be done somewhere else, otherwise multiple emitters cannot be supported - if ((position - mLastPos).length () <= 2) - return; - - mLastPos = position; - - /// \todo scale, force - mImpulses.push(position); -} - void RippleSimulation::addImpulses() { mRectangle->setVisible(false); mImpulse->setVisible(true); - while (mImpulses.size()) + /// \todo it should be more efficient to render all emitters at once + for (std::vector::iterator it=mEmitters.begin(); it !=mEmitters.end(); ++it) { - Ogre::Vector2 pos = mImpulses.front(); - pos -= mRippleCenter; - pos /= mRippleAreaLength; - float size = mImpulseSize / mRippleAreaLength; - mImpulse->setCorners(pos.x-size, pos.y+size, pos.x+size, pos.y-size, false); - mImpulses.pop(); + if (it->mPtr == MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()) + { + // fetch a new ptr (to handle cell change etc) + // for non-player actors this is done in updateObjectCell + it->mPtr = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer (); + } + float* _currentPos = it->mPtr.getRefData().getPosition().pos; + Ogre::Vector3 currentPos (_currentPos[0], _currentPos[1], _currentPos[2]); - mRenderTargets[1]->update(); + if ( (currentPos - it->mLastEmitPosition).length() > 2 + && MWBase::Environment::get().getWorld ()->isUnderwater (it->mPtr.getCell(), currentPos)) + { + it->mLastEmitPosition = currentPos; + + Ogre::Vector2 pos (currentPos.x, currentPos.y); + pos -= mRippleCenter; + pos /= mRippleAreaLength; + float size = mImpulseSize / mRippleAreaLength; + mImpulse->setCorners(pos.x-size, pos.y+size, pos.x+size, pos.y-size, false); + + // don't render if we are offscreen + if (pos.x - size >= 1.0 || pos.y+size <= -1.0 || pos.x+size <= -1.0 || pos.y-size >= 1.0) + continue; + mRenderTargets[1]->update(); + } } mImpulse->setVisible(false); @@ -216,5 +225,39 @@ void RippleSimulation::swapHeightMaps() mTextures[2] = tmp2; } +void RippleSimulation::addEmitter(const MWWorld::Ptr& ptr, float scale, float force) +{ + Emitter newEmitter; + newEmitter.mPtr = ptr; + newEmitter.mScale = scale; + newEmitter.mForce = force; + newEmitter.mLastEmitPosition = Ogre::Vector3(0,0,0); + mEmitters.push_back (newEmitter); +} + +void RippleSimulation::removeEmitter (const MWWorld::Ptr& ptr) +{ + for (std::vector::iterator it = mEmitters.begin(); it != mEmitters.end(); ++it) + { + if (it->mPtr == ptr) + { + mEmitters.erase(it); + return; + } + } +} + +void RippleSimulation::updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr) +{ + for (std::vector::iterator it = mEmitters.begin(); it != mEmitters.end(); ++it) + { + if (it->mPtr == old) + { + it->mPtr = ptr; + return; + } + } +} + } diff --git a/apps/openmw/mwrender/ripplesimulation.hpp b/apps/openmw/mwrender/ripplesimulation.hpp index 2f8cae24f..7e7eebc1c 100644 --- a/apps/openmw/mwrender/ripplesimulation.hpp +++ b/apps/openmw/mwrender/ripplesimulation.hpp @@ -4,6 +4,9 @@ #include #include #include +#include + +#include "../mwworld/ptr.hpp" namespace Ogre { @@ -16,6 +19,14 @@ namespace Ogre namespace MWRender { +struct Emitter +{ + MWWorld::Ptr mPtr; + Ogre::Vector3 mLastEmitPosition; + float mScale; + float mForce; +}; + class RippleSimulation { public: @@ -24,9 +35,14 @@ public: void update(float dt, Ogre::Vector2 position); - void addImpulse (Ogre::Vector2 position, float scale = 1.f, float force = 1.f); + /// adds an emitter, position will be tracked automatically + void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f); + void removeEmitter (const MWWorld::Ptr& ptr); + void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr); private: + std::vector mEmitters; + Ogre::RenderTexture* mRenderTargets[4]; Ogre::TexturePtr mTextures[4]; @@ -34,8 +50,6 @@ private: float mRippleAreaLength; float mImpulseSize; - Ogre::Vector2 mLastPos; - bool mFirstUpdate; Ogre::Camera* mCamera; @@ -51,8 +65,6 @@ private: Ogre::Rectangle2D* mImpulse; - std::queue mImpulses; - void addImpulses(); void heightMapToNormalMap(); void waterSimulation(); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 7d6ca1a0d..d112e17b2 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -81,6 +81,7 @@ void CubeReflection::update () PlaneReflection::PlaneReflection(Ogre::SceneManager* sceneManager, SkyManager* sky) : Reflection(sceneManager) , mSky(sky) + , mRenderActive(false) { mCamera = mSceneMgr->createCamera ("PlaneReflectionCamera"); mSceneMgr->addRenderQueueListener(this); @@ -186,7 +187,7 @@ void PlaneReflection::setVisibilityMask (int flags) // -------------------------------------------------------------------------------------------------------------------------------- -Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell) : +Water::Water (Ogre::Camera *camera, RenderingManager* rend) : mCamera (camera), mSceneMgr (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), mActive(1), mToggled(1), @@ -202,7 +203,7 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mMaterial = MaterialManager::getSingleton().getByName("Water"); - mTop = cell->mWater; + mTop = 0; mIsUnderwater = false; @@ -216,10 +217,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mWaterNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); - if(!(cell->mData.mFlags & cell->Interior)) - { - mWaterNode->setPosition(getSceneNodeCoordinates(cell->mData.mX, cell->mData.mY)); - } mWaterNode->attachObject(mWater); applyRTT(); @@ -397,7 +394,7 @@ void Water::update(float dt, Ogre::Vector3 player) { //mSimulation->addImpulse(Ogre::Vector2(player.x, player.z)); } - mSimulation->update(dt, Ogre::Vector2(player.x, player.z)); + mSimulation->update(dt, Ogre::Vector2(player.x, player.y)); if (mReflection) mReflection->update(); @@ -499,10 +496,19 @@ void Water::createdConfiguration (sh::MaterialInstance* m, const std::string& co } } -void Water::addImpulse (Vector2 position, float scale, float force) +void Water::addEmitter (const MWWorld::Ptr& ptr, float scale, float force) { - if (mSimulation) - mSimulation->addImpulse (position, scale, force); + mSimulation->addEmitter (ptr, scale, force); +} + +void Water::removeEmitter (const MWWorld::Ptr& ptr) +{ + mSimulation->removeEmitter (ptr); +} + +void Water::updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr) +{ + mSimulation->updateEmitterPtr(old, ptr); } } // namespace diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index eb7d98f5d..ddf6ef7ab 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -11,9 +11,12 @@ #include #include +#include + + #include "renderconst.hpp" -#include +#include "../mwworld/ptr.hpp" namespace Ogre { @@ -138,7 +141,7 @@ namespace MWRender { RippleSimulation* mSimulation; public: - Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell); + Water (Ogre::Camera *camera, RenderingManager* rend); ~Water(); void setActive(bool active); @@ -146,7 +149,10 @@ namespace MWRender { void toggle(); void update(float dt, Ogre::Vector3 player); - void addImpulse (Ogre::Vector2 position, float scale = 1.f, float force = 1.f); + /// adds an emitter, position will be tracked automatically using its scene node + void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f); + void removeEmitter (const MWWorld::Ptr& ptr); + void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr); void setViewportBackground(const Ogre::ColourValue& bg); From 8966e88050a167e1bd6f40bcfd1376bdabc13ba4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 27 Feb 2013 16:07:15 +0100 Subject: [PATCH 072/151] Fix shadows --- files/materials/objects.shader | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index d8498b831..88ca2d152 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -32,8 +32,11 @@ SH_BEGIN_PROGRAM shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) +#if (VIEWPROJ_FIX) || (SHADOWS) + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) +#endif + #if VIEWPROJ_FIX - shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) shUniform(float4, vpRow2Fix) @shSharedParameter(vpRow2Fix, vpRow2Fix) shUniform(float4x4, vpMatrix) @shAutoConstant(vpMatrix, viewproj_matrix) #endif From 3bd228f71b1dab4f5d454b1a1cb7b2506a94afaa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 28 Feb 2013 11:50:29 +0100 Subject: [PATCH 073/151] fix for global variables of type short --- components/esm/loadglob.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index 429c6ff1d..9e20578ce 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -20,6 +20,14 @@ void Global::load(ESMReader &esm) // Note: Both floats and longs are represented as floats. esm.getHNT(mValue, "FLTV"); + + if (mType==VT_Short) + { + if (mValue!=mValue) + mValue = 0; // nan + else + mValue = static_cast (mValue); + } } void Global::save(ESMWriter &esm) From e1957e4ee900b31eabb2f3fb9e90fb89d38d1958 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 2 Mar 2013 13:34:26 +0100 Subject: [PATCH 074/151] Potion effects should be hidden until discovered --- apps/openmw/mwclass/potion.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index c3a6df211..0ac78a2e4 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -20,6 +20,8 @@ #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" +#include "../mwmechanics/npcstats.hpp" + namespace MWClass { void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -138,6 +140,23 @@ namespace MWClass text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects); + + // hide effects the player doesnt know about + MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer(); + MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player); + int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase(); + int i=0; + for (MWGui::Widgets::SpellEffectList::iterator it = info.effects.begin(); it != info.effects.end(); ++it) + { + /// \todo this code is duplicated from mwclass/ingredient, put it in a helper function + it->mKnown = ( (i == 0 && alchemySkill >= 15) + || (i == 1 && alchemySkill >= 30) + || (i == 2 && alchemySkill >= 45) + || (i == 3 && alchemySkill >= 60)); + + ++i; + } + info.isPotion = true; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { From 9acd4061ccc2ff497cca8e18baa4052beb073da3 Mon Sep 17 00:00:00 2001 From: k1ll Date: Sat, 2 Mar 2013 17:04:17 +0100 Subject: [PATCH 075/151] Fix dangling static references in mShared --- apps/openmw/mwworld/store.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 5fad63ff5..52120ed0e 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -187,6 +187,15 @@ namespace MWWorld T item; item.mId = Misc::StringUtils::lowerCase(id); + // delete from static part of shared + typename std::vector::iterator sharedit = mShared.begin(); + for (; sharedit != (mShared.begin()+mStatic.size()); ++sharedit) { + if((*sharedit)->mId == item.mId) { + mShared.erase(sharedit); + break; + } + } + typename std::map::iterator it = mStatic.find(item.mId); if (it != mStatic.end() && Misc::StringUtils::ciEqual(it->second.mId, id)) { From 6de6d9ff6eabc79236b206a09c710b85ec4135f9 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Sat, 5 Jan 2013 13:03:05 -0800 Subject: [PATCH 076/151] Factored a NIFStream class out of the NIFFile class. Split NIFFile into two parts, NIFFile which is cached and is a container for a parsed NIF, and NIFStream which is a class specialized for parsing NIFs. This required a semi-sweeping change to make all record classes accept a NIFStream instead of a NIFFile as an agurment to their read functions. --- components/nif/controlled.hpp | 14 +-- components/nif/controller.hpp | 18 ++-- components/nif/data.hpp | 30 +++--- components/nif/effect.hpp | 6 +- components/nif/extra.hpp | 8 +- components/nif/nif_file.cpp | 15 ++- components/nif/nif_file.hpp | 154 ++---------------------------- components/nif/nif_stream.hpp | 175 ++++++++++++++++++++++++++++++++++ components/nif/node.hpp | 14 +-- components/nif/property.hpp | 16 ++-- components/nif/record.hpp | 3 +- components/nif/record_ptr.hpp | 4 +- 12 files changed, 249 insertions(+), 208 deletions(-) create mode 100644 components/nif/nif_stream.hpp diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index b9d84b58a..dac541b2d 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -36,7 +36,7 @@ class Controlled : public Extra public: ControllerPtr controller; - void read(NIFFile *nif) + void read(NIFStream *nif) { Extra::read(nif); controller.read(nif); @@ -55,7 +55,7 @@ class Named : public Controlled public: std::string name; - void read(NIFFile *nif) + void read(NIFStream *nif) { name = nif->getString(); Controlled::read(nif); @@ -66,7 +66,7 @@ typedef Named NiSequenceStreamHelper; class NiParticleGrowFade : public Controlled { public: - void read(NIFFile *nif) + void read(NIFStream *nif) { Controlled::read(nif); @@ -80,7 +80,7 @@ class NiParticleColorModifier : public Controlled public: NiColorDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Controlled::read(nif); data.read(nif); @@ -96,7 +96,7 @@ public: class NiGravity : public Controlled { public: - void read(NIFFile *nif) + void read(NIFStream *nif) { Controlled::read(nif); @@ -109,7 +109,7 @@ public: class NiPlanarCollider : public Controlled { public: - void read(NIFFile *nif) + void read(NIFStream *nif) { Controlled::read(nif); @@ -121,7 +121,7 @@ public: class NiParticleRotation : public Controlled { public: - void read(NIFFile *nif) + void read(NIFStream *nif) { Controlled::read(nif); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index cbc19cd8f..4f7ef3c0f 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -40,7 +40,7 @@ public: float timeStart, timeStop; ControlledPtr target; - void read(NIFFile *nif) + void read(NIFStream *nif) { next.read(nif); @@ -65,7 +65,7 @@ public: class NiBSPArrayController : public Controller { public: - void read(NIFFile *nif) + void read(NIFStream *nif) { Controller::read(nif); @@ -82,7 +82,7 @@ class NiMaterialColorController : public Controller public: NiPosDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Controller::read(nif); data.read(nif); @@ -101,7 +101,7 @@ public: NiPosDataPtr posData; NiFloatDataPtr floatData; - void read(NIFFile *nif) + void read(NIFStream *nif) { Controller::read(nif); @@ -129,7 +129,7 @@ class NiUVController : public Controller public: NiUVDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Controller::read(nif); @@ -149,7 +149,7 @@ class NiKeyframeController : public Controller public: NiKeyframeDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Controller::read(nif); data.read(nif); @@ -167,7 +167,7 @@ class NiAlphaController : public Controller public: NiFloatDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Controller::read(nif); data.read(nif); @@ -185,7 +185,7 @@ class NiGeomMorpherController : public Controller public: NiMorphDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Controller::read(nif); data.read(nif); @@ -204,7 +204,7 @@ class NiVisController : public Controller public: NiVisDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Controller::read(nif); data.read(nif); diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 46b58da8f..5f18800f0 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -65,7 +65,7 @@ public: */ int alpha; - void read(NIFFile *nif) + void read(NIFStream *nif) { Named::read(nif); @@ -102,7 +102,7 @@ public: Ogre::Vector3 center; float radius; - void read(NIFFile *nif) + void read(NIFStream *nif) { int verts = nif->getUShort(); @@ -138,7 +138,7 @@ public: // Triangles, three vertex indices per triangle std::vector triangles; - void read(NIFFile *nif) + void read(NIFStream *nif) { ShapeData::read(nif); @@ -167,7 +167,7 @@ class NiAutoNormalParticlesData : public ShapeData public: int activeCount; - void read(NIFFile *nif) + void read(NIFStream *nif) { ShapeData::read(nif); @@ -189,7 +189,7 @@ public: class NiRotatingParticlesData : public NiAutoNormalParticlesData { public: - void read(NIFFile *nif) + void read(NIFStream *nif) { NiAutoNormalParticlesData::read(nif); @@ -208,7 +208,7 @@ class NiPosData : public Record public: Vector3KeyList mKeyList; - void read(NIFFile *nif) + void read(NIFStream *nif) { mKeyList.read(nif); } @@ -219,7 +219,7 @@ class NiUVData : public Record public: FloatKeyList mKeyList[4]; - void read(NIFFile *nif) + void read(NIFStream *nif) { for(int i = 0;i < 4;i++) mKeyList[i].read(nif); @@ -231,7 +231,7 @@ class NiFloatData : public Record public: FloatKeyList mKeyList; - void read(NIFFile *nif) + void read(NIFStream *nif) { mKeyList.read(nif); } @@ -243,7 +243,7 @@ public: unsigned int rmask, gmask, bmask, amask; int bpp, mips; - void read(NIFFile *nif) + void read(NIFStream *nif) { nif->getInt(); // always 0 or 1 @@ -281,7 +281,7 @@ class NiColorData : public Record public: Vector4KeyList mKeyList; - void read(NIFFile *nif) + void read(NIFStream *nif) { mKeyList.read(nif); } @@ -295,7 +295,7 @@ public: char isSet; }; - void read(NIFFile *nif) + void read(NIFStream *nif) { int count = nif->getInt(); @@ -311,7 +311,7 @@ public: NodePtr root; NodeList bones; - void read(NIFFile *nif) + void read(NIFStream *nif) { data.read(nif); root.read(nif); @@ -347,7 +347,7 @@ public: BoneTrafo trafo; std::vector bones; - void read(NIFFile *nif) + void read(NIFStream *nif) { trafo.rotation = nif->getMatrix3(); trafo.trans = nif->getVector3(); @@ -385,7 +385,7 @@ struct NiMorphData : public Record }; std::vector mMorphs; - void read(NIFFile *nif) + void read(NIFStream *nif) { int morphCount = nif->getInt(); int vertCount = nif->getInt(); @@ -410,7 +410,7 @@ struct NiKeyframeData : public Record Vector3KeyList mTranslations; FloatKeyList mScales; - void read(NIFFile *nif) + void read(NIFStream *nif) { mRotations.read(nif); mTranslations.read(nif); diff --git a/components/nif/effect.hpp b/components/nif/effect.hpp index 850415dad..b07a39303 100644 --- a/components/nif/effect.hpp +++ b/components/nif/effect.hpp @@ -42,7 +42,7 @@ struct NiLight : Effect Ogre::Vector3 diffuse; Ogre::Vector3 specular; - void read(NIFFile *nif) + void read(NIFStream *nif) { dimmer = nif->getFloat(); ambient = nif->getVector3(); @@ -52,7 +52,7 @@ struct NiLight : Effect }; SLight light; - void read(NIFFile *nif) + void read(NIFStream *nif) { Effect::read(nif); @@ -66,7 +66,7 @@ struct NiTextureEffect : Effect { NiSourceTexturePtr texture; - void read(NIFFile *nif) + void read(NIFStream *nif) { Effect::read(nif); diff --git a/components/nif/extra.hpp b/components/nif/extra.hpp index 35781dbf5..b5335f987 100644 --- a/components/nif/extra.hpp +++ b/components/nif/extra.hpp @@ -40,14 +40,14 @@ class Extra : public Record public: ExtraPtr extra; - void read(NIFFile *nif) { extra.read(nif); } + void read(NIFStream *nif) { extra.read(nif); } void post(NIFFile *nif) { extra.post(nif); } }; class NiVertWeightsExtraData : public Extra { public: - void read(NIFFile *nif) + void read(NIFStream *nif) { Extra::read(nif); @@ -70,7 +70,7 @@ public: }; std::vector list; - void read(NIFFile *nif) + void read(NIFStream *nif) { Extra::read(nif); @@ -95,7 +95,7 @@ public: */ std::string string; - void read(NIFFile *nif) + void read(NIFStream *nif) { Extra::read(nif); diff --git a/components/nif/nif_file.cpp b/components/nif/nif_file.cpp index 6e806e7ec..f3faf563c 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/nif_file.cpp @@ -174,10 +174,7 @@ NIFFile::ptr NIFFile::create (const std::string &name) { return LoadedCache::cre NIFFile::NIFFile(const std::string &name, psudo_private_modifier) : filename(name) { - inp = Ogre::ResourceGroupManager::getSingleton().openResource(name); parse(); - // Make sure to close the file after it was loaded into memory - inp.setNull(); } NIFFile::~NIFFile() @@ -195,18 +192,20 @@ NIFFile::~NIFFile() void NIFFile::parse() { + NIFStream nif (this, Ogre::ResourceGroupManager::getSingleton().openResource(filename)); + // Check the header string - std::string head = getString(40); + std::string head = nif.getString(40); if(head.compare(0, 22, "NetImmerse File Format") != 0) fail("Invalid NIF header"); // Get BCD version - ver = getInt(); + ver = nif.getInt(); if(ver != VER_MW) fail("Unsupported NIF version"); // Number of records - size_t recNum = getInt(); + size_t recNum = nif.getInt(); records.resize(recNum); /* The format for 10.0.1.0 seems to be a bit different. After the @@ -222,7 +221,7 @@ void NIFFile::parse() { Record *r = NULL; - std::string rec = getString(); + std::string rec = nif.getString(); /* These are all the record types we know how to read. @@ -312,7 +311,7 @@ void NIFFile::parse() r->recName = rec; r->recIndex = i; records[i] = r; - r->read(this); + r->read(&nif); // Discard tranformations for the root node, otherwise some meshes // occasionally get wrong orientation. Only for NiNode-s for now, but diff --git a/components/nif/nif_file.hpp b/components/nif/nif_file.hpp index 5e9694f4b..a406de4a0 100644 --- a/components/nif/nif_file.hpp +++ b/components/nif/nif_file.hpp @@ -46,6 +46,7 @@ #include "record.hpp" #include "nif_types.hpp" +#include "nif_stream.hpp" namespace Nif { @@ -59,9 +60,6 @@ class NIFFile /// Nif file version int ver; - /// Input stream - Ogre::DataStreamPtr inp; - /// File name, used for error messages std::string filename; @@ -71,33 +69,6 @@ class NIFFile /// Parse the file void parse(); - uint8_t read_byte() - { - uint8_t byte; - if(inp->read(&byte, 1) != 1) return 0; - return byte; - } - uint16_t read_le16() - { - uint8_t buffer[2]; - if(inp->read(buffer, 2) != 2) return 0; - return buffer[0] | (buffer[1]<<8); - } - uint32_t read_le32() - { - uint8_t buffer[4]; - if(inp->read(buffer, 4) != 4) return 0; - return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24); - } - float read_le32f() - { - union { - uint32_t i; - float f; - } u = { read_le32() }; - return u.f; - } - class LoadedCache; friend class LoadedCache; @@ -117,8 +88,8 @@ public: void warn(const std::string &msg) { - std::cerr<< "NIFFile Warning: "< ptr; @@ -147,111 +118,6 @@ public: /// Number of records size_t numRecords() { return records.size(); } - - /************************************************* - Parser functions - ****************************************************/ - - void skip(size_t size) { inp->skip(size); } - - char getChar() { return read_byte(); } - short getShort() { return read_le16(); } - unsigned short getUShort() { return read_le16(); } - int getInt() { return read_le32(); } - unsigned int getUInt() { return read_le32(); } - float getFloat() { return read_le32f(); } - Ogre::Vector2 getVector2() - { - float a[2]; - for(size_t i = 0;i < 2;i++) - a[i] = getFloat(); - return Ogre::Vector2(a); - } - Ogre::Vector3 getVector3() - { - float a[3]; - for(size_t i = 0;i < 3;i++) - a[i] = getFloat(); - return Ogre::Vector3(a); - } - Ogre::Vector4 getVector4() - { - float a[4]; - for(size_t i = 0;i < 4;i++) - a[i] = getFloat(); - return Ogre::Vector4(a); - } - Ogre::Matrix3 getMatrix3() - { - Ogre::Real a[3][3]; - for(size_t i = 0;i < 3;i++) - { - for(size_t j = 0;j < 3;j++) - a[i][j] = Ogre::Real(getFloat()); - } - return Ogre::Matrix3(a); - } - Ogre::Quaternion getQuaternion() - { - float a[4]; - for(size_t i = 0;i < 4;i++) - a[i] = getFloat(); - return Ogre::Quaternion(a); - } - Transformation getTrafo() - { - Transformation t; - t.pos = getVector3(); - t.rotation = getMatrix3(); - t.scale = getFloat(); - return t; - } - - std::string getString(size_t length) - { - std::vector str (length+1, 0); - - if(inp->read(&str[0], length) != length) - throw std::runtime_error ("string length in NIF file does not match"); - - return &str[0]; - } - std::string getString() - { - size_t size = read_le32(); - return getString(size); - } - - void getShorts(std::vector &vec, size_t size) - { - vec.resize(size); - for(size_t i = 0;i < vec.size();i++) - vec[i] = getShort(); - } - void getFloats(std::vector &vec, size_t size) - { - vec.resize(size); - for(size_t i = 0;i < vec.size();i++) - vec[i] = getFloat(); - } - void getVector2s(std::vector &vec, size_t size) - { - vec.resize(size); - for(size_t i = 0;i < vec.size();i++) - vec[i] = getVector2(); - } - void getVector3s(std::vector &vec, size_t size) - { - vec.resize(size); - for(size_t i = 0;i < vec.size();i++) - vec[i] = getVector3(); - } - void getVector4s(std::vector &vec, size_t size) - { - vec.resize(size); - for(size_t i = 0;i < vec.size();i++) - vec[i] = getVector4(); - } }; @@ -270,7 +136,7 @@ typedef KeyT Vector3Key; typedef KeyT Vector4Key; typedef KeyT QuaternionKey; -template +template struct KeyListT { typedef std::vector< KeyT > VecType; @@ -281,7 +147,7 @@ struct KeyListT { int mInterpolationType; VecType mKeys; - void read(NIFFile *nif, bool force=false) + void read(NIFStream *nif, bool force=false) { size_t count = nif->getInt(); if(count == 0 && !force) @@ -322,13 +188,13 @@ struct KeyListT { } } else - nif->warn("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); + nif->file->warn("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); } }; -typedef KeyListT FloatKeyList; -typedef KeyListT Vector3KeyList; -typedef KeyListT Vector4KeyList; -typedef KeyListT QuaternionKeyList; +typedef KeyListT FloatKeyList; +typedef KeyListT Vector3KeyList; +typedef KeyListT Vector4KeyList; +typedef KeyListT QuaternionKeyList; } // Namespace #endif diff --git a/components/nif/nif_stream.hpp b/components/nif/nif_stream.hpp new file mode 100644 index 000000000..8fb98f3d6 --- /dev/null +++ b/components/nif/nif_stream.hpp @@ -0,0 +1,175 @@ +#ifndef _NIF_STREAM_HPP_ +#define _NIF_STREAM_HPP_ + +namespace Nif +{ + +class NIFFile; + +class NIFStream { + + /// Input stream + Ogre::DataStreamPtr inp; + + uint8_t read_byte() + { + uint8_t byte; + if(inp->read(&byte, 1) != 1) return 0; + return byte; + } + uint16_t read_le16() + { + uint8_t buffer[2]; + if(inp->read(buffer, 2) != 2) return 0; + return buffer[0] | (buffer[1]<<8); + } + uint32_t read_le32() + { + uint8_t buffer[4]; + if(inp->read(buffer, 4) != 4) return 0; + return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24); + } + float read_le32f() + { + union { + uint32_t i; + float f; + } u = { read_le32() }; + return u.f; + } + +public: + + NIFFile * const file; + + NIFStream (NIFFile * file, Ogre::DataStreamPtr inp): file (file), inp (inp) {} + + /************************************************* + Parser functions + ****************************************************/ + + template + struct GetHandler + { + typedef T (NIFStream::*fn_t)(); + + static const fn_t sValue; // this is specialized per supported type in the .cpp file + + static T read (NIFStream* nif) + { + return (nif->*sValue) (); + } + }; + + template + void read (NIFStream* nif, T & Value) + { + Value = GetHandler ::read (nif); + } + + void skip(size_t size) { inp->skip(size); } + void read (void * data, size_t size) { inp->read (data, size); } + + char getChar() { return read_byte(); } + short getShort() { return read_le16(); } + unsigned short getUShort() { return read_le16(); } + int getInt() { return read_le32(); } + int getUInt() { return read_le32(); } + float getFloat() { return read_le32f(); } + Ogre::Vector2 getVector2() + { + float a[2]; + for(size_t i = 0;i < 2;i++) + a[i] = getFloat(); + return Ogre::Vector2(a); + } + Ogre::Vector3 getVector3() + { + float a[3]; + for(size_t i = 0;i < 3;i++) + a[i] = getFloat(); + return Ogre::Vector3(a); + } + Ogre::Vector4 getVector4() + { + float a[4]; + for(size_t i = 0;i < 4;i++) + a[i] = getFloat(); + return Ogre::Vector4(a); + } + Ogre::Matrix3 getMatrix3() + { + Ogre::Real a[3][3]; + for(size_t i = 0;i < 3;i++) + { + for(size_t j = 0;j < 3;j++) + a[i][j] = Ogre::Real(getFloat()); + } + return Ogre::Matrix3(a); + } + Ogre::Quaternion getQuaternion() + { + float a[4]; + for(size_t i = 0;i < 4;i++) + a[i] = getFloat(); + return Ogre::Quaternion(a); + } + Transformation getTrafo() + { + Transformation t; + t.pos = getVector3(); + t.rotation = getMatrix3(); + t.scale = getFloat(); + return t; + } + + std::string getString(size_t length) + { + std::vector str (length+1, 0); + + if(inp->read(&str[0], length) != length) + throw std::runtime_error ("string length in NIF file does not match"); + + return &str[0]; + } + std::string getString() + { + size_t size = read_le32(); + return getString(size); + } + + void getShorts(std::vector &vec, size_t size) + { + vec.resize(size); + for(size_t i = 0;i < vec.size();i++) + vec[i] = getShort(); + } + void getFloats(std::vector &vec, size_t size) + { + vec.resize(size); + for(size_t i = 0;i < vec.size();i++) + vec[i] = getFloat(); + } + void getVector2s(std::vector &vec, size_t size) + { + vec.resize(size); + for(size_t i = 0;i < vec.size();i++) + vec[i] = getVector2(); + } + void getVector3s(std::vector &vec, size_t size) + { + vec.resize(size); + for(size_t i = 0;i < vec.size();i++) + vec[i] = getVector3(); + } + void getVector4s(std::vector &vec, size_t size) + { + vec.resize(size); + for(size_t i = 0;i < vec.size();i++) + vec[i] = getVector4(); + } +}; + +} + +#endif diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 07e7868cc..e08703756 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -54,7 +54,7 @@ public: Ogre::Matrix3 boundRot; Ogre::Vector3 boundXYZ; // Box size - void read(NIFFile *nif) + void read(NIFStream *nif) { Named::read(nif); @@ -128,7 +128,7 @@ struct NiNode : Node 0x20, 0x40, 0x80 unknown */ - void read(NIFFile *nif) + void read(NIFStream *nif) { Node::read(nif); children.read(nif); @@ -162,7 +162,7 @@ struct NiTriShape : Node NiTriShapeDataPtr data; NiSkinInstancePtr skin; - void read(NIFFile *nif) + void read(NIFStream *nif) { Node::read(nif); data.read(nif); @@ -190,7 +190,7 @@ struct NiCamera : Node // Level of detail modifier float LOD; - void read(NIFFile *nif) + void read(NIFStream *nif) { left = nif->getFloat(); right = nif->getFloat(); @@ -209,7 +209,7 @@ struct NiCamera : Node }; Camera cam; - void read(NIFFile *nif) + void read(NIFStream *nif) { Node::read(nif); @@ -224,7 +224,7 @@ struct NiAutoNormalParticles : Node { NiAutoNormalParticlesDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Node::read(nif); data.read(nif); @@ -242,7 +242,7 @@ struct NiRotatingParticles : Node { NiRotatingParticlesDataPtr data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Node::read(nif); data.read(nif); diff --git a/components/nif/property.hpp b/components/nif/property.hpp index 046fb0465..cdf97986c 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -35,7 +35,7 @@ public: // The meaning of these depends on the actual property type. int flags; - void read(NIFFile *nif) + void read(NIFStream *nif) { Named::read(nif); flags = nif->getUShort(); @@ -67,7 +67,7 @@ public: int clamp, set, filter; short unknown2; - void read(NIFFile *nif) + void read(NIFStream *nif) { inUse = !!nif->getInt(); if(!inUse) return; @@ -111,7 +111,7 @@ public: */ Texture textures[7]; - void read(NIFFile *nif) + void read(NIFStream *nif) { Property::read(nif); apply = nif->getInt(); @@ -157,7 +157,7 @@ struct StructPropT : Property { T data; - void read(NIFFile *nif) + void read(NIFStream *nif) { Property::read(nif); data.read(nif); @@ -170,7 +170,7 @@ struct S_MaterialProperty Ogre::Vector3 ambient, diffuse, specular, emissive; float glossiness, alpha; - void read(NIFFile *nif) + void read(NIFStream *nif) { ambient = nif->getVector3(); diffuse = nif->getVector3(); @@ -194,7 +194,7 @@ struct S_VertexColorProperty */ int vertmode, lightmode; - void read(NIFFile *nif) + void read(NIFStream *nif) { vertmode = nif->getInt(); lightmode = nif->getInt(); @@ -251,7 +251,7 @@ struct S_AlphaProperty // Tested against when certain flags are set (see above.) unsigned char threshold; - void read(NIFFile *nif) + void read(NIFStream *nif) { threshold = nif->getChar(); } @@ -300,7 +300,7 @@ struct S_StencilProperty */ int drawMode; - void read(NIFFile *nif) + void read(NIFStream *nif) { enabled = nif->getChar(); compareFunc = nif->getInt(); diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 073f4657c..9f0645dfd 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -30,6 +30,7 @@ namespace Nif { class NIFFile; +class NIFStream; enum RecordType { @@ -97,7 +98,7 @@ struct Record Record() : recType(RC_MISSING), recIndex(~(size_t)0) {} /// Parses the record from file - virtual void read(NIFFile *nif) = 0; + virtual void read(NIFStream *nif) = 0; /// Does post-processing, after the entire tree is loaded virtual void post(NIFFile *nif) {} diff --git a/components/nif/record_ptr.hpp b/components/nif/record_ptr.hpp index ef5bb1dee..855099a04 100644 --- a/components/nif/record_ptr.hpp +++ b/components/nif/record_ptr.hpp @@ -46,7 +46,7 @@ public: RecordPtrT() : index(-2) {} /// Read the index from the nif - void read(NIFFile *nif) + void read(NIFStream *nif) { // Can only read the index once assert(index == -2); @@ -99,7 +99,7 @@ class RecordListT std::vector list; public: - void read(NIFFile *nif) + void read(NIFStream *nif) { int len = nif->getInt(); list.resize(len); From 0ed2015319a0afa2c59a393e7e876572af419134 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Thu, 3 Jan 2013 23:59:32 -0800 Subject: [PATCH 077/151] refactored NIFFile parse to get better code/data seperation --- components/nif/nif_file.cpp | 182 ++++++++++++++++++++---------------- 1 file changed, 102 insertions(+), 80 deletions(-) diff --git a/components/nif/nif_file.cpp b/components/nif/nif_file.cpp index f3faf563c..dc8670cba 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/nif_file.cpp @@ -185,6 +185,101 @@ NIFFile::~NIFFile() delete records[i]; } +template static Record* construct() { return new NodeType; } + +struct RecordFactoryEntry { + + typedef Record* (*create_t) (); + + char const * mName; + create_t mCreate; + RecordType mType; + +}; + +/* These are all the record types we know how to read. + + This can be heavily optimized later if needed. For example, a + hash table or a FSM-based parser could be used to look up + node names. +*/ + +static const RecordFactoryEntry recordFactories [] = { + + { "NiNode", &construct , RC_NiNode }, + { "AvoidNode", &construct , RC_NiNode }, + { "NiBSParticleNode", &construct , RC_NiNode }, + { "NiBSAnimationNode", &construct , RC_NiNode }, + { "NiBillboardNode", &construct , RC_NiNode }, + { "NiTriShape", &construct , RC_NiTriShape }, + { "NiRotatingParticles", &construct , RC_NiRotatingParticles }, + { "NiAutoNormalParticles", &construct , RC_NiAutoNormalParticles }, + { "NiCamera", &construct , RC_NiCamera }, + { "RootCollisionNode", &construct , RC_RootCollisionNode }, + { "NiTexturingProperty", &construct , RC_NiTexturingProperty }, + { "NiMaterialProperty", &construct , RC_NiMaterialProperty }, + { "NiZBufferProperty", &construct , RC_NiZBufferProperty }, + { "NiAlphaProperty", &construct , RC_NiAlphaProperty }, + { "NiVertexColorProperty", &construct , RC_NiVertexColorProperty }, + { "NiShadeProperty", &construct , RC_NiShadeProperty }, + { "NiDitherProperty", &construct , RC_NiDitherProperty }, + { "NiWireframeProperty", &construct , RC_NiWireframeProperty }, + { "NiSpecularProperty", &construct , RC_NiSpecularProperty }, + { "NiStencilProperty", &construct , RC_NiStencilProperty }, + { "NiVisController", &construct , RC_NiVisController }, + { "NiGeomMorpherController", &construct , RC_NiGeomMorpherController }, + { "NiKeyframeController", &construct , RC_NiKeyframeController }, + { "NiAlphaController", &construct , RC_NiAlphaController }, + { "NiUVController", &construct , RC_NiUVController }, + { "NiPathController", &construct , RC_NiPathController }, + { "NiMaterialColorController", &construct , RC_NiMaterialColorController }, + { "NiBSPArrayController", &construct , RC_NiBSPArrayController }, + { "NiParticleSystemController", &construct , RC_NiParticleSystemController }, + { "NiAmbientLight", &construct , RC_NiLight }, + { "NiDirectionalLight", &construct , RC_NiLight }, + { "NiTextureEffect", &construct , RC_NiTextureEffect }, + { "NiVertWeightsExtraData", &construct , RC_NiVertWeightsExtraData }, + { "NiTextKeyExtraData", &construct , RC_NiTextKeyExtraData }, + { "NiStringExtraData", &construct , RC_NiStringExtraData }, + { "NiGravity", &construct , RC_NiGravity }, + { "NiPlanarCollider", &construct , RC_NiPlanarCollider }, + { "NiParticleGrowFade", &construct , RC_NiParticleGrowFade }, + { "NiParticleColorModifier", &construct , RC_NiParticleColorModifier }, + { "NiParticleRotation", &construct , RC_NiParticleRotation }, + { "NiFloatData", &construct , RC_NiFloatData }, + { "NiTriShapeData", &construct , RC_NiTriShapeData }, + { "NiVisData", &construct , RC_NiVisData }, + { "NiColorData", &construct , RC_NiColorData }, + { "NiPixelData", &construct , RC_NiPixelData }, + { "NiMorphData", &construct , RC_NiMorphData }, + { "NiKeyframeData", &construct , RC_NiKeyframeData }, + { "NiSkinData", &construct , RC_NiSkinData }, + { "NiUVData", &construct , RC_NiUVData }, + { "NiPosData", &construct , RC_NiPosData }, + { "NiRotatingParticlesData", &construct , RC_NiRotatingParticlesData }, + { "NiAutoNormalParticlesData", &construct , RC_NiAutoNormalParticlesData }, + { "NiSequenceStreamHelper", &construct , RC_NiSequenceStreamHelper }, + { "NiSourceTexture", &construct , RC_NiSourceTexture }, + { "NiSkinInstance", &construct , RC_NiSkinInstance }, +}; + +static RecordFactoryEntry const * recordFactories_begin = &recordFactories [0]; +static RecordFactoryEntry const * recordFactories_end = &recordFactories [sizeof (recordFactories) / sizeof (recordFactories[0])]; + +RecordFactoryEntry const * lookupRecordFactory (char const * name) +{ + RecordFactoryEntry const * i; + + for (i = recordFactories_begin; i != recordFactories_end; ++i) + if (strcmp (name, i->mName) == 0) + break; + + if (i == recordFactories_end) + return NULL; + + return i; +} + /* This file implements functions from the NIFFile class. It is also where we stash all the functions we couldn't add as inline definitions in the record types. @@ -223,88 +318,15 @@ void NIFFile::parse() std::string rec = nif.getString(); - /* These are all the record types we know how to read. + RecordFactoryEntry const * entry = lookupRecordFactory (rec.c_str ()); - This can be heavily optimized later if needed. For example, a - hash table or a FSM-based parser could be used to look up - node names. - */ - - // NiNodes - if(rec == "NiNode" || rec == "AvoidNode" || - rec == "NiBSParticleNode" || - rec == "NiBSAnimationNode" || - rec == "NiBillboardNode") { r = new NiNode; r->recType = RC_NiNode; } - - // Other nodes - else if(rec == "NiTriShape") { r = new NiTriShape; r->recType = RC_NiTriShape; } - else if(rec == "NiRotatingParticles") { r = new NiRotatingParticles; r->recType = RC_NiRotatingParticles; } - else if(rec == "NiAutoNormalParticles") { r = new NiAutoNormalParticles; r->recType = RC_NiAutoNormalParticles; } - else if(rec == "NiCamera") { r = new NiCamera; r->recType = RC_NiCamera; } - else if(rec == "RootCollisionNode"){ r = new NiNode; r->recType = RC_RootCollisionNode; }// a root collision node is exactly like a node - //that's why there is no need to create a new type - - // Properties - else if(rec == "NiTexturingProperty") { r = new NiTexturingProperty; r->recType = RC_NiTexturingProperty; } - else if(rec == "NiMaterialProperty") { r = new NiMaterialProperty; r->recType = RC_NiMaterialProperty; } - else if(rec == "NiZBufferProperty") { r = new NiZBufferProperty; r->recType = RC_NiZBufferProperty; } - else if(rec == "NiAlphaProperty") { r = new NiAlphaProperty; r->recType = RC_NiAlphaProperty; } - else if(rec == "NiVertexColorProperty") { r = new NiVertexColorProperty; r->recType = RC_NiVertexColorProperty; } - else if(rec == "NiShadeProperty") { r = new NiShadeProperty; r->recType = RC_NiShadeProperty; } - else if(rec == "NiDitherProperty") { r = new NiDitherProperty; r->recType = RC_NiDitherProperty; } - else if(rec == "NiWireframeProperty") { r = new NiWireframeProperty; r->recType = RC_NiWireframeProperty; } - else if(rec == "NiSpecularProperty") { r = new NiSpecularProperty; r->recType = RC_NiSpecularProperty; } - else if(rec == "NiStencilProperty") { r = new NiStencilProperty; r->recType = RC_NiStencilProperty; } - - // Controllers - else if(rec == "NiVisController") { r = new NiVisController; r->recType = RC_NiVisController; } - else if(rec == "NiGeomMorpherController") { r = new NiGeomMorpherController; r->recType = RC_NiGeomMorpherController; } - else if(rec == "NiKeyframeController") { r = new NiKeyframeController; r->recType = RC_NiKeyframeController; } - else if(rec == "NiAlphaController") { r = new NiAlphaController; r->recType = RC_NiAlphaController; } - else if(rec == "NiUVController") { r = new NiUVController; r->recType = RC_NiUVController; } - else if(rec == "NiPathController") { r = new NiPathController; r->recType = RC_NiPathController; } - else if(rec == "NiMaterialColorController") { r = new NiMaterialColorController; r->recType = RC_NiMaterialColorController; } - else if(rec == "NiBSPArrayController") { r = new NiBSPArrayController; r->recType = RC_NiBSPArrayController; } - else if(rec == "NiParticleSystemController") { r = new NiParticleSystemController; r->recType = RC_NiParticleSystemController; } - - // Effects - else if(rec == "NiAmbientLight" || - rec == "NiDirectionalLight") { r = new NiLight; r->recType = RC_NiLight; } - else if(rec == "NiTextureEffect") { r = new NiTextureEffect; r->recType = RC_NiTextureEffect; } - - // Extra Data - else if(rec == "NiVertWeightsExtraData") { r = new NiVertWeightsExtraData; r->recType = RC_NiVertWeightsExtraData; } - else if(rec == "NiTextKeyExtraData") { r = new NiTextKeyExtraData; r->recType = RC_NiTextKeyExtraData; } - else if(rec == "NiStringExtraData") { r = new NiStringExtraData; r->recType = RC_NiStringExtraData; } - - else if(rec == "NiGravity") { r = new NiGravity; r->recType = RC_NiGravity; } - else if(rec == "NiPlanarCollider") { r = new NiPlanarCollider; r->recType = RC_NiPlanarCollider; } - else if(rec == "NiParticleGrowFade") { r = new NiParticleGrowFade; r->recType = RC_NiParticleGrowFade; } - else if(rec == "NiParticleColorModifier") { r = new NiParticleColorModifier; r->recType = RC_NiParticleColorModifier; } - else if(rec == "NiParticleRotation") { r = new NiParticleRotation; r->recType = RC_NiParticleRotation; } - - // Data - else if(rec == "NiFloatData") { r = new NiFloatData; r->recType = RC_NiFloatData; } - else if(rec == "NiTriShapeData") { r = new NiTriShapeData; r->recType = RC_NiTriShapeData; } - else if(rec == "NiVisData") { r = new NiVisData; r->recType = RC_NiVisData; } - else if(rec == "NiColorData") { r = new NiColorData; r->recType = RC_NiColorData; } - else if(rec == "NiPixelData") { r = new NiPixelData; r->recType = RC_NiPixelData; } - else if(rec == "NiMorphData") { r = new NiMorphData; r->recType = RC_NiMorphData; } - else if(rec == "NiKeyframeData") { r = new NiKeyframeData; r->recType = RC_NiKeyframeData; } - else if(rec == "NiSkinData") { r = new NiSkinData; r->recType = RC_NiSkinData; } - else if(rec == "NiUVData") { r = new NiUVData; r->recType = RC_NiUVData; } - else if(rec == "NiPosData") { r = new NiPosData; r->recType = RC_NiPosData; } - else if(rec == "NiRotatingParticlesData") { r = new NiRotatingParticlesData; r->recType = RC_NiRotatingParticlesData; } - else if(rec == "NiAutoNormalParticlesData") { r = new NiAutoNormalParticlesData; r->recType = RC_NiAutoNormalParticlesData; } - - // Other - else if(rec == "NiSequenceStreamHelper") { r = new NiSequenceStreamHelper; r->recType = RC_NiSequenceStreamHelper; } - else if(rec == "NiSourceTexture") { r = new NiSourceTexture; r->recType = RC_NiSourceTexture; } - else if(rec == "NiSkinInstance") { r = new NiSkinInstance; r->recType = RC_NiSkinInstance; } - - // Failure + if (entry != NULL) + { + r = entry->mCreate (); + r->recType = entry->mType; + } else - fail("Unknown record type " + rec); + fail("Unknown record type " + rec); assert(r != NULL); assert(r->recType != RC_MISSING); From d3c1f5e7b23bcfb30fb418b9f0acb18bcfa273a9 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Sun, 24 Feb 2013 13:51:56 -0800 Subject: [PATCH 078/151] renamed low-level NIF related files and include guards to conform to naming convention --- apps/openmw/engine.cpp | 2 +- apps/openmw/mwworld/scene.cpp | 2 +- components/CMakeLists.txt | 2 +- components/nif/controlled.hpp | 4 ++-- components/nif/controller.hpp | 8 ++++---- components/nif/data.hpp | 4 ++-- components/nif/effect.hpp | 4 ++-- components/nif/extra.hpp | 8 ++++---- components/nif/{nif_file.cpp => niffile.cpp} | 2 +- components/nif/{nif_file.hpp => niffile.hpp} | 8 ++++---- components/nif/{nif_stream.hpp => nifstream.hpp} | 4 ++-- components/nif/{nif_types.hpp => niftypes.hpp} | 4 ++-- components/nif/node.hpp | 4 ++-- components/nif/property.hpp | 4 ++-- components/nif/record.hpp | 4 ++-- components/nif/{record_ptr.hpp => recordptr.hpp} | 6 +++--- components/nifbullet/bullet_nif_loader.cpp | 2 +- 17 files changed, 36 insertions(+), 36 deletions(-) rename components/nif/{nif_file.cpp => niffile.cpp} (99%) rename components/nif/{nif_file.hpp => niffile.hpp} (97%) rename components/nif/{nif_stream.hpp => nifstream.hpp} (97%) rename components/nif/{nif_types.hpp => niftypes.hpp} (93%) rename components/nif/{record_ptr.hpp => recordptr.hpp} (97%) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d14696cdd..a69dc7402 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index ecf783d6c..35024b307 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -1,6 +1,6 @@ #include "scene.hpp" -#include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" /// FIXME diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 00342e2ac..a80afdd6b 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -15,7 +15,7 @@ add_component_dir (bsa ) add_component_dir (nif - controlled effect nif_types record controller extra node record_ptr data nif_file property + controlled effect niftypes record controller extra node record_ptr data niffile property ) add_component_dir (nifogre diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index dac541b2d..36c9a82ac 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -21,8 +21,8 @@ */ -#ifndef _NIF_CONTROLLED_H_ -#define _NIF_CONTROLLED_H_ +#ifndef OPENMW_COMPONENTS_NIF_CONTROLLED_HPP +#define OPENMW_COMPONENTS_NIF_CONTROLLED_HPP #include "extra.hpp" #include "controller.hpp" diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 4f7ef3c0f..8331b93b7 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -21,12 +21,12 @@ */ -#ifndef _NIF_CONTROLLER_H_ -#define _NIF_CONTROLLER_H_ +#ifndef OPENMW_COMPONENTS_NIF_CONTROLLER_HPP +#define OPENMW_COMPONENTS_NIF_CONTROLLER_HPP #include "record.hpp" -#include "nif_file.hpp" -#include "record_ptr.hpp" +#include "niffile.hpp" +#include "recordptr.hpp" namespace Nif { diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 5f18800f0..9bdba6396 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -21,8 +21,8 @@ */ -#ifndef _NIF_DATA_H_ -#define _NIF_DATA_H_ +#ifndef OPENMW_COMPONENTS_NIF_DATA_HPP +#define OPENMW_COMPONENTS_NIF_DATA_HPP #include "controlled.hpp" diff --git a/components/nif/effect.hpp b/components/nif/effect.hpp index b07a39303..cc1b0f41c 100644 --- a/components/nif/effect.hpp +++ b/components/nif/effect.hpp @@ -21,8 +21,8 @@ */ -#ifndef _NIF_EFFECT_H_ -#define _NIF_EFFECT_H_ +#ifndef OPENMW_COMPONENTS_NIF_EFFECT_HPP +#define OPENMW_COMPONENTS_NIF_EFFECT_HPP #include "node.hpp" diff --git a/components/nif/extra.hpp b/components/nif/extra.hpp index b5335f987..45c4fefc6 100644 --- a/components/nif/extra.hpp +++ b/components/nif/extra.hpp @@ -21,12 +21,12 @@ */ -#ifndef _NIF_EXTRA_H_ -#define _NIF_EXTRA_H_ +#ifndef OPENMW_COMPONENTS_NIF_EXTRA_HPP +#define OPENMW_COMPONENTS_NIF_EXTRA_HPP #include "record.hpp" -#include "nif_file.hpp" -#include "record_ptr.hpp" +#include "niffile.hpp" +#include "recordptr.hpp" namespace Nif { diff --git a/components/nif/nif_file.cpp b/components/nif/niffile.cpp similarity index 99% rename from components/nif/nif_file.cpp rename to components/nif/niffile.cpp index dc8670cba..bf05e7576 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/niffile.cpp @@ -21,7 +21,7 @@ */ -#include "nif_file.hpp" +#include "niffile.hpp" #include "record.hpp" #include "components/misc/stringops.hpp" diff --git a/components/nif/nif_file.hpp b/components/nif/niffile.hpp similarity index 97% rename from components/nif/nif_file.hpp rename to components/nif/niffile.hpp index a406de4a0..ed11bdd7c 100644 --- a/components/nif/nif_file.hpp +++ b/components/nif/niffile.hpp @@ -21,8 +21,8 @@ */ -#ifndef _NIF_FILE_H_ -#define _NIF_FILE_H_ +#ifndef OPENMW_COMPONENTS_NIF_NIFFILE_HPP +#define OPENMW_COMPONENTS_NIF_NIFFILE_HPP #include #include @@ -45,8 +45,8 @@ #include #include "record.hpp" -#include "nif_types.hpp" -#include "nif_stream.hpp" +#include "niftypes.hpp" +#include "nifstream.hpp" namespace Nif { diff --git a/components/nif/nif_stream.hpp b/components/nif/nifstream.hpp similarity index 97% rename from components/nif/nif_stream.hpp rename to components/nif/nifstream.hpp index 8fb98f3d6..02b931b7e 100644 --- a/components/nif/nif_stream.hpp +++ b/components/nif/nifstream.hpp @@ -1,5 +1,5 @@ -#ifndef _NIF_STREAM_HPP_ -#define _NIF_STREAM_HPP_ +#ifndef OPENMW_COMPONENTS_NIF_NIFSTREAM_HPP +#define OPENMW_COMPONENTS_NIF_NIFSTREAM_HPP namespace Nif { diff --git a/components/nif/nif_types.hpp b/components/nif/niftypes.hpp similarity index 93% rename from components/nif/nif_types.hpp rename to components/nif/niftypes.hpp index a5fb61361..786c48b65 100644 --- a/components/nif/nif_types.hpp +++ b/components/nif/niftypes.hpp @@ -21,8 +21,8 @@ */ -#ifndef _NIF_TYPES_H_ -#define _NIF_TYPES_H_ +#ifndef OPENMW_COMPONENTS_NIF_NIFTYPES_HPP +#define OPENMW_COMPONENTS_NIF_NIFTYPES_HPP #include #include diff --git a/components/nif/node.hpp b/components/nif/node.hpp index e08703756..ab92d74f8 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -21,8 +21,8 @@ */ -#ifndef _NIF_NODE_H_ -#define _NIF_NODE_H_ +#ifndef OPENMW_COMPONENTS_NIF_NODE_HPP +#define OPENMW_COMPONENTS_NIF_NODE_HPP #include diff --git a/components/nif/property.hpp b/components/nif/property.hpp index cdf97986c..cd1e0a5d1 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -21,8 +21,8 @@ */ -#ifndef _NIF_PROPERTY_H_ -#define _NIF_PROPERTY_H_ +#ifndef OPENMW_COMPONENTS_NIF_PROPERTY_HPP +#define OPENMW_COMPONENTS_NIF_PROPERTY_HPP #include "controlled.hpp" diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 9f0645dfd..3a3cd9b84 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -21,8 +21,8 @@ */ -#ifndef _NIF_RECORD_H_ -#define _NIF_RECORD_H_ +#ifndef OPENMW_COMPONENTS_NIF_RECORD_HPP +#define OPENMW_COMPONENTS_NIF_RECORD_HPP #include diff --git a/components/nif/record_ptr.hpp b/components/nif/recordptr.hpp similarity index 97% rename from components/nif/record_ptr.hpp rename to components/nif/recordptr.hpp index 855099a04..c5bafea12 100644 --- a/components/nif/record_ptr.hpp +++ b/components/nif/recordptr.hpp @@ -21,10 +21,10 @@ */ -#ifndef _NIF_RECORD_PTR_H_ -#define _NIF_RECORD_PTR_H_ +#ifndef OPENMW_COMPONENTS_NIF_RECORDPTR_HPP +#define OPENMW_COMPONENTS_NIF_RECORDPTR_HPP -#include "nif_file.hpp" +#include "niffile.hpp" #include namespace Nif diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index 3d9c16ebb..e33754264 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -25,7 +25,7 @@ http://www.gnu.org/licenses/ . #include #include -#include "../nif/nif_file.hpp" +#include "../nif/niffile.hpp" #include "../nif/node.hpp" #include "../nif/data.hpp" #include "../nif/property.hpp" From fdfcd5bb4774e6a03fef5afafc5f116a635015cd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 2 Mar 2013 12:23:29 -0800 Subject: [PATCH 079/151] Material properties are accumulative along the node tree --- components/nifogre/ogre_nif_loader.cpp | 101 +++++++++++++------------ 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index d33243dd4..1d9c4d748 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -549,7 +549,10 @@ static void fail(const std::string &msg) public: -static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String &name, const Ogre::String &group) +static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String &name, const Ogre::String &group, + const Nif::NiTexturingProperty *texprop, + const Nif::NiMaterialProperty *matprop, + const Nif::NiAlphaProperty *alphaprop) { Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); Ogre::MaterialPtr material = matMgr.getByName(name); @@ -568,36 +571,11 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String bool vertexColour = (shape->data->colors.size() != 0); - // These are set below if present - const Nif::NiTexturingProperty *t = NULL; - const Nif::NiMaterialProperty *m = NULL; - const Nif::NiAlphaProperty *a = NULL; - - // Scan the property list for material information - const Nif::PropertyList &list = shape->props; - for (size_t i = 0;i < list.length();i++) - { - // Entries may be empty - if (list[i].empty()) continue; - - const Nif::Property *pr = list[i].getPtr(); - if (pr->recType == Nif::RC_NiTexturingProperty) - t = static_cast(pr); - else if (pr->recType == Nif::RC_NiMaterialProperty) - m = static_cast(pr); - else if (pr->recType == Nif::RC_NiAlphaProperty) - a = static_cast(pr); - else if (pr->recType == Nif::RC_NiStencilProperty) - /* unused */; - else - warn("Skipped property type: "+pr->recName); - } - // Texture - if (t && t->textures[0].inUse) + if(texprop && texprop->textures[0].inUse) { - Nif::NiSourceTexture *st = t->textures[0].texture.getPtr(); - if (st->external) + const Nif::NiSourceTexture *st = texprop->textures[0].texture.getPtr(); + if(st->external) { /* Bethesda at some point converted all their BSA * textures from tga to dds for increased load speed, but all @@ -633,25 +611,25 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String } // Alpha modifiers - if (a) + if(alphaprop) { - alphaFlags = a->flags; - alphaTest = a->data.threshold; + alphaFlags = alphaprop->flags; + alphaTest = alphaprop->data.threshold; } // Material - if(m) + if(matprop) { - ambient = m->data.ambient; - diffuse = m->data.diffuse; - specular = m->data.specular; - emissive = m->data.emissive; - glossiness = m->data.glossiness; - alpha = m->data.alpha; + ambient = matprop->data.ambient; + diffuse = matprop->data.diffuse; + specular = matprop->data.specular; + emissive = matprop->data.emissive; + glossiness = matprop->data.glossiness; + alpha = matprop->data.alpha; } Ogre::String matname = name; - if (m || !texName.empty()) + if(matprop || !texName.empty()) { // Generate a hash out of all properties that can affect the material. size_t h = 0; @@ -749,7 +727,6 @@ class NIFMeshLoader : Ogre::ManualResourceLoader std::string mName; std::string mGroup; size_t mShapeIndex; - std::string mMaterialName; void warn(const std::string &msg) { @@ -764,7 +741,10 @@ class NIFMeshLoader : Ogre::ManualResourceLoader // Convert NiTriShape to Ogre::SubMesh - void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape const *shape) + void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape const *shape, + const Nif::NiTexturingProperty *texprop, + const Nif::NiMaterialProperty *matprop, + const Nif::NiAlphaProperty *alphaprop) { Ogre::SkeletonPtr skel; const Nif::NiTriShapeData *data = shape->data.getPtr(); @@ -962,15 +942,39 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } } - if(mMaterialName.length() > 0) - sub->setMaterialName(mMaterialName); + std::string matname = NIFMaterialLoader::getMaterial(shape, mName, mGroup, + texprop, matprop, alphaprop); + if(matname.length() > 0) + sub->setMaterialName(matname); } - bool findTriShape(Ogre::Mesh *mesh, Nif::Node const *node) + bool findTriShape(Ogre::Mesh *mesh, const Nif::Node *node, + const Nif::NiTexturingProperty *texprop=NULL, + const Nif::NiMaterialProperty *matprop=NULL, + const Nif::NiAlphaProperty *alphaprop=NULL) { + // Scan the property list for material information + const Nif::PropertyList &proplist = node->props; + for(size_t i = 0;i < proplist.length();i++) + { + // Entries may be empty + if(proplist[i].empty()) + continue; + + const Nif::Property *pr = proplist[i].getPtr(); + if(pr->recType == Nif::RC_NiTexturingProperty) + texprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiMaterialProperty) + matprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiAlphaProperty) + alphaprop = static_cast(pr); + else + warn("Unhandled property type: "+pr->recName); + } + if(node->recType == Nif::RC_NiTriShape && mShapeIndex == node->recIndex) { - handleNiTriShape(mesh, dynamic_cast(node)); + handleNiTriShape(mesh, dynamic_cast(node), texprop, matprop, alphaprop); return true; } @@ -982,7 +986,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { if(!children[i].empty()) { - if(findTriShape(mesh, children[i].getPtr())) + if(findTriShape(mesh, children[i].getPtr(), texprop, matprop, alphaprop)) return true; } } @@ -1015,7 +1019,7 @@ public: return; } - Nif::Node const *node = dynamic_cast(nif->getRecord(mShapeIndex)); + const Nif::Node *node = dynamic_cast(nif->getRecord(0)); findTriShape(mesh, node); } @@ -1066,7 +1070,6 @@ public: NIFMeshLoader *loader = &sLoaders[fullname]; *loader = *this; loader->mShapeIndex = shape->recIndex; - loader->mMaterialName = NIFMaterialLoader::getMaterial(shape, fullname, mGroup); mesh = meshMgr.createManual(fullname, mGroup, loader); mesh->setAutoBuildEdgeLists(false); From dde43e8c87430c98e52e4aa88186a57ebdde9620 Mon Sep 17 00:00:00 2001 From: k1ll Date: Sat, 2 Mar 2013 21:46:31 +0100 Subject: [PATCH 080/151] Some cleanup --- apps/openmw/mwworld/store.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 52120ed0e..586e407ff 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -187,11 +187,11 @@ namespace MWWorld T item; item.mId = Misc::StringUtils::lowerCase(id); - // delete from static part of shared - typename std::vector::iterator sharedit = mShared.begin(); - for (; sharedit != (mShared.begin()+mStatic.size()); ++sharedit) { - if((*sharedit)->mId == item.mId) { - mShared.erase(sharedit); + // 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; } } From 109dff2d29f1ed3b71c4169f917f390043278b46 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Sun, 24 Feb 2013 13:52:23 -0800 Subject: [PATCH 081/151] renamed high level NIF files... --- apps/openmw/engine.cpp | 4 ++-- apps/openmw/mwrender/animation.hpp | 2 +- apps/openmw/mwrender/objects.cpp | 2 +- apps/openmw/mwrender/sky.cpp | 2 +- apps/openmw/mwworld/physicssystem.cpp | 2 +- components/CMakeLists.txt | 4 ++-- .../nifbullet/{bullet_nif_loader.cpp => bulletnifloader.cpp} | 2 +- .../nifbullet/{bullet_nif_loader.hpp => bulletnifloader.hpp} | 4 ++-- components/nifogre/{ogre_nif_loader.cpp => ogrenifloader.cpp} | 2 +- components/nifogre/{ogre_nif_loader.hpp => ogrenifloader.hpp} | 4 ++-- components/nifoverrides/nifoverrides.hpp | 4 ++-- libs/openengine/bullet/CMotionState.cpp | 2 +- libs/openengine/bullet/physic.cpp | 2 +- 13 files changed, 18 insertions(+), 18 deletions(-) rename components/nifbullet/{bullet_nif_loader.cpp => bulletnifloader.cpp} (99%) rename components/nifbullet/{bullet_nif_loader.hpp => bulletnifloader.hpp} (96%) rename components/nifogre/{ogre_nif_loader.cpp => ogrenifloader.cpp} (99%) rename components/nifogre/{ogre_nif_loader.hpp => ogrenifloader.hpp} (96%) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a69dc7402..74e967d8d 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -12,8 +12,8 @@ #include #include -#include -#include +#include +#include #include "mwinput/inputmanagerimp.hpp" diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 810ca869f..7caf35169 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -1,7 +1,7 @@ #ifndef _GAME_RENDER_ANIMATION_H #define _GAME_RENDER_ANIMATION_H -#include +#include #include "../mwworld/ptr.hpp" diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index e91180a42..89425e9f2 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include "../mwworld/ptr.hpp" diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 062079693..0f778511d 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -14,7 +14,7 @@ #include -#include +#include #include diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 65cbc1164..566a463b6 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include //#include "../mwbase/world.hpp" // FIXME #include "../mwbase/environment.hpp" diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index a80afdd6b..9fdc72873 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -19,11 +19,11 @@ add_component_dir (nif ) add_component_dir (nifogre - ogre_nif_loader + ogrenifloader ) add_component_dir (nifbullet - bullet_nif_loader + bulletnifloader ) add_component_dir (to_utf8 diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bulletnifloader.cpp similarity index 99% rename from components/nifbullet/bullet_nif_loader.cpp rename to components/nifbullet/bulletnifloader.cpp index e33754264..91fd6dbcf 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -21,7 +21,7 @@ http://www.gnu.org/licenses/ . */ -#include "bullet_nif_loader.hpp" +#include "bulletnifloader.hpp" #include #include diff --git a/components/nifbullet/bullet_nif_loader.hpp b/components/nifbullet/bulletnifloader.hpp similarity index 96% rename from components/nifbullet/bullet_nif_loader.hpp rename to components/nifbullet/bulletnifloader.hpp index 0629b208d..0ff4b4ccd 100644 --- a/components/nifbullet/bullet_nif_loader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -21,8 +21,8 @@ */ -#ifndef _BULLET_NIF_LOADER_H_ -#define _BULLET_NIF_LOADER_H_ +#ifndef OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP +#define OPENMW_COMPONENTS_NIFBULLET_BULLETNIFLOADER_HPP #include #include diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogrenifloader.cpp similarity index 99% rename from components/nifogre/ogre_nif_loader.cpp rename to components/nifogre/ogrenifloader.cpp index d33243dd4..4eaedeaa8 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -21,7 +21,7 @@ */ -#include "ogre_nif_loader.hpp" +#include "ogrenifloader.hpp" #include diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogrenifloader.hpp similarity index 96% rename from components/nifogre/ogre_nif_loader.hpp rename to components/nifogre/ogrenifloader.hpp index eae37dd8a..b8b2e3c00 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -21,8 +21,8 @@ */ -#ifndef _OGRE_NIF_LOADER_H_ -#define _OGRE_NIF_LOADER_H_ +#ifndef OPENMW_COMPONENTS_NIFOGRE_OGRENIFLOADER_HPP +#define OPENMW_COMPONENTS_NIFOGRE_OGRENIFLOADER_HPP #include #include diff --git a/components/nifoverrides/nifoverrides.hpp b/components/nifoverrides/nifoverrides.hpp index c9b711df6..ba2e4cc3c 100644 --- a/components/nifoverrides/nifoverrides.hpp +++ b/components/nifoverrides/nifoverrides.hpp @@ -1,5 +1,5 @@ -#ifndef COMPONENTS_NIFOVERRIDES_H -#define COMPONENTS_NIFOVERRIDES_H +#ifndef OPENMW_COMPONENTS_NIFOVERRIDES_NIFOVERRIDES_HPP +#define OPENMW_COMPONENTS_NIFOVERRIDES_NIFOVERRIDES_HPP #include diff --git a/libs/openengine/bullet/CMotionState.cpp b/libs/openengine/bullet/CMotionState.cpp index 6be615dfb..c20415884 100644 --- a/libs/openengine/bullet/CMotionState.cpp +++ b/libs/openengine/bullet/CMotionState.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include namespace OEngine { namespace Physic diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index f993ce68e..119f6893a 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include "CMotionState.h" #include "OgreRoot.h" #include "btKinematicCharacterController.h" From 2b6bb9657bd46d2c2a5509a019647bcaa12dc7bb Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sat, 2 Mar 2013 23:49:31 +0100 Subject: [PATCH 082/151] Added Qt Designer .ui files --- apps/launcher/CMakeLists.txt | 10 +- apps/launcher/ui/graphicspage.ui | 134 +++++++++++++++++++++++ apps/launcher/ui/mainwindow.ui | 80 ++++++++++++++ apps/launcher/ui/playpage.ui | 180 +++++++++++++++++++++++++++++++ 4 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 apps/launcher/ui/graphicspage.ui create mode 100644 apps/launcher/ui/mainwindow.ui create mode 100644 apps/launcher/ui/playpage.ui diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index b2e6c7009..bc3969097 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -53,7 +53,13 @@ set(LAUNCHER_HEADER_MOC utils/textinputdialog.hpp ) -source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC}) +set(LAUNCHER_UI + ui/graphicspage.ui + ui/mainwindow.ui + ui/playpage.ui +) + +source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) find_package(Qt4 REQUIRED) set(QT_USE_QTGUI 1) @@ -66,6 +72,7 @@ endif(WIN32) QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) +QT4_WRAP_UI(UI_HDRS ${LAUCHER_UI}) include(${QT_USE_FILE}) @@ -85,6 +92,7 @@ add_executable(omwlauncher ${LAUNCHER_HEADER} ${RCC_SRCS} ${MOC_SRCS} + ${UI_HDRS} ) target_link_libraries(omwlauncher diff --git a/apps/launcher/ui/graphicspage.ui b/apps/launcher/ui/graphicspage.ui new file mode 100644 index 000000000..670b4f9c6 --- /dev/null +++ b/apps/launcher/ui/graphicspage.ui @@ -0,0 +1,134 @@ + + + graphicsPage + + + + 0 + 0 + 400 + 300 + + + + + + + Render System + + + + + + Rendering Subsystem: + + + + + + + + + + + + + GroupBox + + + + + + Vertical Sync + + + + + + + Full Screen + + + + + + + Anti-aliasing: + + + + + + + Resolution: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + + + + + + + x + + + + + + + + + + + + Custom: + + + + + + + Standard: + + + true + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 61 + + + + + + + + + diff --git a/apps/launcher/ui/mainwindow.ui b/apps/launcher/ui/mainwindow.ui new file mode 100644 index 000000000..4e1a7854d --- /dev/null +++ b/apps/launcher/ui/mainwindow.ui @@ -0,0 +1,80 @@ + + + MainWindow + + + + 0 + 0 + 575 + 575 + + + + + 575 + 575 + + + + OpenMW Launcher + + + + :/images/openmw.png:/images/openmw.png + + + + + + + + 400 + 80 + + + + + 16777215 + 80 + + + + #iconWidget { + background-image: url(":/images/openmw-header.png"); + background-color: white; + background-repeat: no-repeat; + background-attachment: scroll; + background-position: right; +} + + + + + + + + + + + + + + + + + + + + QDialogButtonBox::Close + + + + + + + + + + + diff --git a/apps/launcher/ui/playpage.ui b/apps/launcher/ui/playpage.ui new file mode 100644 index 000000000..86a763f64 --- /dev/null +++ b/apps/launcher/ui/playpage.ui @@ -0,0 +1,180 @@ + + + playPage + + + #playPage { + background-image: url(":/images/playpage-background.png"); + background-repeat: no-repeat; + background-position: top; +} + + + + + 30 + + + 100 + + + 30 + + + + + + 200 + 85 + + + + + 200 + 85 + + + + #playButton { + height: 50px; + margin-bottom: 30px; + + background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 rgba(255, 255, 255, 200), + stop:0.1 rgba(255, 255, 255, 15), + stop:0.49 rgba(255, 255, 255, 75), + stop:0.5 rgba(0, 0, 0, 0), + stop:0.9 rgba(0, 0, 0, 55), + stop:1 rgba(0, 0, 0, 100)); + + font-size: 26pt; + font-family: "EB Garamond", "EB Garamond 08"; + color: black; + + border-right: 1px solid rgba(0, 0, 0, 155); + border-left: 1px solid rgba(0, 0, 0, 55); + border-top: 1px solid rgba(0, 0, 0, 55); + border-bottom: 1px solid rgba(0, 0, 0, 155); + + border-radius: 5px; +} + +#playButton:hover { + border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-width: 2px; + border-style: solid; +} + +#playButton:pressed { + 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), + stop:0.2 rgba(255, 255, 255, 55) + stop:0.95 rgba(255, 255, 255, 55), + stop:1 rgba(255, 255, 255, 155)); + + border: 1px solid rgba(0, 0, 0, 55); +} + + + Play + + + + + + + #profileLabel { + font-size: 18pt; + font-family: "EB Garamond", "EB Garamond 08"; +} + + + + Current Profile: + + + + + + + #profilesComboBox { + padding: 1px 18px 1px 3px; + + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:0.2 rgba(0, 0, 0, 25), stop:1 white); + border-width: 1px; + border-color: rgba(0, 0, 0, 125); + border-style: solid; + border-radius: 2px; +} + +/*QComboBox gets the "on" state when the popup is open */ +#profilesComboBox:!editable:on, #ProfilesComboBox::drop-down: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), + stop:0.2 rgba(255, 255, 255, 55)); + + border: 1px solid rgba(0, 0, 0, 55); +} + +#profilesComboBox { /* shift the text when the popup opens */ + padding-top: 3px; + padding-left: 4px; + + font-size: 12pt; + font-family: "EB Garamond", "EB Garamond 08"; +} + +#profilesComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + + border-width: 1px; + border-left-width: 1px; + border-left-color: darkgray; + border-left-style: solid; /* just a single line */ + border-top-right-radius: 3px; /* same radius as the QComboBox */ + border-bottom-right-radius: 3px; +} + +#profilesComboBox::down-arrow { + image: url(":/images/down.png"); +} + +#profilesComboBox::down-arrow:on { /* shift the arrow when popup is open */ + top: 1px; + left: 1px; +} + +#profilesComboBox QAbstractItemView { + border: 2px solid lightgray; + border-radius: 5px; +} + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + From f2193bb1bacde7fe5c37475cab839c3f2e08374f Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 3 Mar 2013 00:48:09 +0100 Subject: [PATCH 083/151] Made the mainwindow use a .ui file and removed the stylesheet --- CMakeLists.txt | 6 -- apps/launcher/CMakeLists.txt | 22 ++----- apps/launcher/maindialog.cpp | 92 +++++++------------------- apps/launcher/maindialog.hpp | 8 ++- files/launcher.qss | 123 ----------------------------------- 5 files changed, 35 insertions(+), 216 deletions(-) delete mode 100644 files/launcher.qss diff --git a/CMakeLists.txt b/CMakeLists.txt index e583f23d4..6498e723c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -379,7 +379,6 @@ if(WIN32) "${OpenMW_SOURCE_DIR}/OFL.txt" "${OpenMW_SOURCE_DIR}/DejaVu Font License.txt" "${OpenMW_SOURCE_DIR}/Daedric Font License.txt" - "${OpenMW_BINARY_DIR}/launcher.qss" "${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" "${OpenMW_BINARY_DIR}/Release/omwlauncher.exe" @@ -566,8 +565,6 @@ if (APPLE) install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) @@ -681,7 +678,4 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) # Install resources INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" ) - IF(BUILD_LAUNCHER) - INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${DATADIR}/resources" ) - ENDIF(BUILD_LAUNCHER) endif(NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index bc3969097..206e94794 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -36,6 +36,7 @@ set(LAUNCHER_HEADER utils/comboboxlineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp + ) # Headers that must be pre-processed @@ -54,9 +55,9 @@ set(LAUNCHER_HEADER_MOC ) set(LAUNCHER_UI - ui/graphicspage.ui - ui/mainwindow.ui - ui/playpage.ui + ./ui/graphicspage.ui + ./ui/mainwindow.ui + ./ui/playpage.ui ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) @@ -72,9 +73,10 @@ endif(WIN32) QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) -QT4_WRAP_UI(UI_HDRS ${LAUCHER_UI}) +QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) include(${QT_USE_FILE}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) # Main executable IF(OGRE_STATIC) @@ -107,18 +109,6 @@ if(DPKG_PROGRAM) INSTALL(TARGETS omwlauncher RUNTIME DESTINATION games COMPONENT omwlauncher) endif() -if (APPLE) - configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss - "${APP_BUNDLE_DIR}/../launcher.qss") -else() - configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss - "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/resources/launcher.qss") - - # Fallback in case getGlobalDataPath does not point to resources - configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss - "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss") -endif() - if (BUILD_WITH_CODE_COVERAGE) add_definitions (--coverage) target_link_libraries(omwlauncher gcov) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index e69f134d2..f438e64c9 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -12,46 +12,6 @@ MainDialog::MainDialog() : mGameSettings(mCfgMgr) { - QWidget *centralWidget = new QWidget(this); - setCentralWidget(centralWidget); - - mIconWidget = new QListWidget(centralWidget); - mIconWidget->setObjectName("IconWidget"); - mIconWidget->setViewMode(QListView::IconMode); - mIconWidget->setWrapping(false); - mIconWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Just to be sure - mIconWidget->setIconSize(QSize(48, 48)); - mIconWidget->setMovement(QListView::Static); - - mIconWidget->setMinimumWidth(400); - mIconWidget->setFixedHeight(80); - mIconWidget->setSpacing(4); - mIconWidget->setCurrentRow(0); - mIconWidget->setFlow(QListView::LeftToRight); - - QGroupBox *groupBox = new QGroupBox(centralWidget); - QVBoxLayout *groupLayout = new QVBoxLayout(groupBox); - - mPagesWidget = new QStackedWidget(groupBox); - groupLayout->addWidget(mPagesWidget); - - QPushButton *playButton = new QPushButton(tr("Play")); - - QDialogButtonBox *buttonBox = new QDialogButtonBox(centralWidget); - buttonBox->setStandardButtons(QDialogButtonBox::Close); - buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole); - - QVBoxLayout *dialogLayout = new QVBoxLayout(centralWidget); - dialogLayout->addWidget(mIconWidget); - dialogLayout->addWidget(groupBox); - dialogLayout->addWidget(buttonBox); - - setWindowTitle(tr("OpenMW Launcher")); - setWindowIcon(QIcon(":/images/openmw.png")); - // Remove what's this? button - setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); - setMinimumSize(QSize(575, 575)); - // Install the stylesheet font QFile file; QFontDatabase fontDatabase; @@ -71,31 +31,27 @@ MainDialog::MainDialog() fontDatabase.addApplicationFont(font); } - // Load the stylesheet - QString config = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/launcher.qss"); - file.setFileName(config); + setupUi(this); - if (!file.exists()) - file.setFileName(QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("launcher.qss")); + iconWidget->setViewMode(QListView::IconMode); + iconWidget->setWrapping(false); + iconWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Just to be sure + iconWidget->setIconSize(QSize(48, 48)); + iconWidget->setMovement(QListView::Static); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox msgBox; - msgBox.setWindowTitle(tr("Error opening Launcher stylesheet")); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not open %0 for reading

\ - Please make sure you have the right permissions \ - and try again.
").arg(file.fileName())); - msgBox.exec(); - } else { - QString styleSheet = QLatin1String(file.readAll()); - qApp->setStyleSheet(styleSheet); - file.close(); - } + iconWidget->setSpacing(4); + iconWidget->setCurrentRow(0); + iconWidget->setFlow(QListView::LeftToRight); + + QPushButton *playButton = new QPushButton(tr("Play")); + buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole); connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); + // Remove what's this? button + setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); + createIcons(); } @@ -107,25 +63,25 @@ void MainDialog::createIcons() // We create a fallback icon because the default fallback doesn't work QIcon graphicsIcon = QIcon(":/icons/tango/video-display.png"); - QListWidgetItem *playButton = new QListWidgetItem(mIconWidget); + QListWidgetItem *playButton = new QListWidgetItem(iconWidget); playButton->setIcon(QIcon(":/images/openmw.png")); playButton->setText(tr("Play")); playButton->setTextAlignment(Qt::AlignCenter); playButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - QListWidgetItem *graphicsButton = new QListWidgetItem(mIconWidget); + QListWidgetItem *graphicsButton = new QListWidgetItem(iconWidget); graphicsButton->setIcon(QIcon::fromTheme("video-display", graphicsIcon)); graphicsButton->setText(tr("Graphics")); graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute); graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - QListWidgetItem *dataFilesButton = new QListWidgetItem(mIconWidget); + QListWidgetItem *dataFilesButton = new QListWidgetItem(iconWidget); dataFilesButton->setIcon(QIcon(":/images/openmw-plugin.png")); dataFilesButton->setText(tr("Data Files")); dataFilesButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - connect(mIconWidget, + connect(iconWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*))); @@ -142,12 +98,12 @@ void MainDialog::createPages() mPlayPage->mProfilesComboBox->setCurrentIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); // Add the pages to the stacked widget - mPagesWidget->addWidget(mPlayPage); - mPagesWidget->addWidget(mGraphicsPage); - mPagesWidget->addWidget(mDataFilesPage); + pagesWidget->addWidget(mPlayPage); + pagesWidget->addWidget(mGraphicsPage); + pagesWidget->addWidget(mDataFilesPage); // Select the first page - mIconWidget->setCurrentItem(mIconWidget->item(0), QItemSelectionModel::Select); + iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select); connect(mPlayPage->mPlayButton, SIGNAL(clicked()), this, SLOT(play())); @@ -326,7 +282,7 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) if (!current) current = previous; - mPagesWidget->setCurrentIndex(mIconWidget->row(current)); + pagesWidget->setCurrentIndex(iconWidget->row(current)); } bool MainDialog::setupLauncherSettings() diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index f221bd5e6..780cd8beb 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -9,6 +9,8 @@ #include "settings/graphicssettings.hpp" #include "settings/launchersettings.hpp" +#include "ui_mainwindow.h" + class QListWidget; class QListWidgetItem; class QStackedWidget; @@ -20,7 +22,7 @@ class PlayPage; class GraphicsPage; class DataFilesPage; -class MainDialog : public QMainWindow +class MainDialog : public QMainWindow, private Ui::MainWindow { Q_OBJECT @@ -56,8 +58,8 @@ private: void closeEvent(QCloseEvent *event); - QListWidget *mIconWidget; - QStackedWidget *mPagesWidget; +// QListWidget *mIconWidget; +// QStackedWidget *mPagesWidget; PlayPage *mPlayPage; GraphicsPage *mGraphicsPage; diff --git a/files/launcher.qss b/files/launcher.qss deleted file mode 100644 index 1eb056d4d..000000000 --- a/files/launcher.qss +++ /dev/null @@ -1,123 +0,0 @@ -#PlayGroup { - background-image: url(":/images/playpage-background.png"); - background-repeat: no-repeat; - background-position: top; - padding-left: 30px; - padding-right: 30px; -} - -#MastersWidget { - selection-background-color: palette(highlight); -} - -#PlayButton { - height: 50px; - margin-bottom: 30px; - - background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, - stop:0 rgba(255, 255, 255, 200), - stop:0.1 rgba(255, 255, 255, 15), - stop:0.49 rgba(255, 255, 255, 75), - stop:0.5 rgba(0, 0, 0, 0), - stop:0.9 rgba(0, 0, 0, 55), - stop:1 rgba(0, 0, 0, 100)); - - font-size: 26pt; - font-family: "EB Garamond", "EB Garamond 08"; - color: black; - - border-right: 1px solid rgba(0, 0, 0, 155); - border-left: 1px solid rgba(0, 0, 0, 55); - border-top: 1px solid rgba(0, 0, 0, 55); - border-bottom: 1px solid rgba(0, 0, 0, 155); - - border-radius: 5px; -} - -#PlayButton:hover { - border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-width: 2px; - border-style: solid; -} - -#PlayButton:pressed { - 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), - stop:0.2 rgba(255, 255, 255, 55) - stop:0.95 rgba(255, 255, 255, 55), - stop:1 rgba(255, 255, 255, 155)); - - border: 1px solid rgba(0, 0, 0, 55); -} - -#ProfileLabel { - font-size: 18pt; - font-family: "EB Garamond", "EB Garamond 08"; -} - -#ProfilesComboBox { - padding: 1px 18px 1px 3px; - - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:0.2 rgba(0, 0, 0, 25), stop:1 white); - border-width: 1px; - border-color: rgba(0, 0, 0, 125); - border-style: solid; - border-radius: 2px; -} - -/*QComboBox gets the "on" state when the popup is open */ -#ProfilesComboBox:!editable:on, #ProfilesComboBox::drop-down: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), - stop:0.2 rgba(255, 255, 255, 55)); - - border: 1px solid rgba(0, 0, 0, 55); -} - - -#ProfilesComboBox { /* shift the text when the popup opens */ - padding-top: 3px; - padding-left: 4px; - - font-size: 12pt; - font-family: "EB Garamond", "EB Garamond 08"; -} - -#ProfilesComboBox::drop-down { - subcontrol-origin: padding; - subcontrol-position: top right; - - border-width: 1px; - border-left-width: 1px; - border-left-color: darkgray; - border-left-style: solid; /* just a single line */ - border-top-right-radius: 3px; /* same radius as the QComboBox */ - border-bottom-right-radius: 3px; -} - -#ProfilesComboBox::down-arrow { - image: url(":/images/down.png"); -} - -#ProfilesComboBox::down-arrow:on { /* shift the arrow when popup is open */ - top: 1px; - left: 1px; -} - -#ProfilesComboBox QAbstractItemView { - border: 2px solid lightgray; - border-radius: 5px; -} - -#IconWidget { - background-image: url(":/images/openmw-header.png"); - background-color: white; - background-repeat: no-repeat; - background-attachment: scroll; - background-position: right; -} From 03785f3ecda06bad6a8c85af8aa7490da28c9f07 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 2 Mar 2013 16:28:32 -0800 Subject: [PATCH 084/151] Handle NiVertexColorProperty --- components/nifogre/ogre_nif_loader.cpp | 61 +++++++++++++++++++------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 1d9c4d748..1d0d31961 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -552,7 +552,8 @@ public: static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String &name, const Ogre::String &group, const Nif::NiTexturingProperty *texprop, const Nif::NiMaterialProperty *matprop, - const Nif::NiAlphaProperty *alphaprop) + const Nif::NiAlphaProperty *alphaprop, + const Nif::NiVertexColorProperty *vertprop) { Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); Ogre::MaterialPtr material = matMgr.getByName(name); @@ -567,6 +568,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String float alpha = 1.0f; int alphaFlags = 0; int alphaTest = 0; + int vertMode = 2; + //int lightMode = 1; Ogre::String texName; bool vertexColour = (shape->data->colors.size() != 0); @@ -617,6 +620,14 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String alphaTest = alphaprop->data.threshold; } + // Vertex color handling + if(vertprop) + { + vertMode = vertprop->data.vertmode; + // FIXME: Handle lightmode? + //lightMode = vertprop->data.lightmode; + } + // Material if(matprop) { @@ -649,6 +660,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String boost::hash_combine(h, vertexColour); boost::hash_combine(h, alphaFlags); boost::hash_combine(h, alphaTest); + boost::hash_combine(h, vertMode); std::map::iterator itr = MaterialMap.find(h); if (itr != MaterialMap.end()) @@ -662,19 +674,31 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String // No existing material like this. Create a new one. sh::MaterialInstance* instance = sh::Factory::getInstance ().createMaterialInstance (matname, "openmw_objects_base"); - instance->setProperty ("ambient", sh::makeProperty ( - new sh::Vector3(ambient.x, ambient.y, ambient.z))); + if(vertMode == 0 || !vertexColour) + { + instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, alpha))); + instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); + instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, alpha))); + } + else if(vertMode == 1) + { + instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, alpha))); + instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); + instance->setProperty("emissive", sh::makeProperty(new sh::StringValue("vertexcolour"))); + } + else if(vertMode == 2) + { + instance->setProperty("ambient", sh::makeProperty(new sh::StringValue("vertexcolour"))); + instance->setProperty("diffuse", sh::makeProperty(new sh::StringValue("vertexcolour"))); + instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, alpha))); + } + else + std::cerr<< "Unhandled vertex mode: "<setProperty ("diffuse", sh::makeProperty ( - new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); - - instance->setProperty ("specular", sh::makeProperty ( + instance->setProperty("specular", sh::makeProperty( new sh::Vector4(specular.x, specular.y, specular.z, glossiness*255.0f))); - instance->setProperty ("emissive", sh::makeProperty ( - new sh::Vector3(emissive.x, emissive.y, emissive.z))); - - instance->setProperty ("diffuseMap", sh::makeProperty(texName)); + instance->setProperty("diffuseMap", sh::makeProperty(texName)); if (vertexColour) instance->setProperty ("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); @@ -744,7 +768,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape const *shape, const Nif::NiTexturingProperty *texprop, const Nif::NiMaterialProperty *matprop, - const Nif::NiAlphaProperty *alphaprop) + const Nif::NiAlphaProperty *alphaprop, + const Nif::NiVertexColorProperty *vertprop) { Ogre::SkeletonPtr skel; const Nif::NiTriShapeData *data = shape->data.getPtr(); @@ -943,7 +968,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } std::string matname = NIFMaterialLoader::getMaterial(shape, mName, mGroup, - texprop, matprop, alphaprop); + texprop, matprop, alphaprop, + vertprop); if(matname.length() > 0) sub->setMaterialName(matname); } @@ -951,7 +977,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader bool findTriShape(Ogre::Mesh *mesh, const Nif::Node *node, const Nif::NiTexturingProperty *texprop=NULL, const Nif::NiMaterialProperty *matprop=NULL, - const Nif::NiAlphaProperty *alphaprop=NULL) + const Nif::NiAlphaProperty *alphaprop=NULL, + const Nif::NiVertexColorProperty *vertprop=NULL) { // Scan the property list for material information const Nif::PropertyList &proplist = node->props; @@ -968,13 +995,15 @@ class NIFMeshLoader : Ogre::ManualResourceLoader matprop = static_cast(pr); else if(pr->recType == Nif::RC_NiAlphaProperty) alphaprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiVertexColorProperty) + vertprop = static_cast(pr); else warn("Unhandled property type: "+pr->recName); } if(node->recType == Nif::RC_NiTriShape && mShapeIndex == node->recIndex) { - handleNiTriShape(mesh, dynamic_cast(node), texprop, matprop, alphaprop); + handleNiTriShape(mesh, dynamic_cast(node), texprop, matprop, alphaprop, vertprop); return true; } @@ -986,7 +1015,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { if(!children[i].empty()) { - if(findTriShape(mesh, children[i].getPtr(), texprop, matprop, alphaprop)) + if(findTriShape(mesh, children[i].getPtr(), texprop, matprop, alphaprop, vertprop)) return true; } } From 0a6e3701abf08bb5804f151ab8bd4f87e31a7e90 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 3 Mar 2013 01:49:41 +0100 Subject: [PATCH 085/151] Made the Play page use a .ui file too --- apps/launcher/maindialog.cpp | 15 +- apps/launcher/maindialog.hpp | 9 -- apps/launcher/playpage.cpp | 58 ++++---- apps/launcher/playpage.hpp | 22 ++- apps/launcher/ui/graphicspage.ui | 4 +- apps/launcher/ui/playpage.ui | 228 ++++++++++++++++--------------- 6 files changed, 170 insertions(+), 166 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index f438e64c9..5621b75c0 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -94,8 +94,8 @@ void MainDialog::createPages() mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage - mPlayPage->mProfilesComboBox->setModel(mDataFilesPage->mProfilesComboBox->model()); - mPlayPage->mProfilesComboBox->setCurrentIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); + mPlayPage->setProfilesComboBoxModel(mDataFilesPage->mProfilesComboBox->model()); + mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); @@ -105,15 +105,10 @@ void MainDialog::createPages() // Select the first page iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select); - connect(mPlayPage->mPlayButton, SIGNAL(clicked()), this, SLOT(play())); + connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play())); - connect(mPlayPage->mProfilesComboBox, - SIGNAL(currentIndexChanged(int)), - mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); - - connect(mDataFilesPage->mProfilesComboBox, - SIGNAL(currentIndexChanged(int)), - mPlayPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); + connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); + connect(mDataFilesPage->mProfilesComboBox, SIGNAL(currentIndexChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); } diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 780cd8beb..643206ab6 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -28,12 +28,6 @@ class MainDialog : public QMainWindow, private Ui::MainWindow public: MainDialog(); - - -// GameSettings &gameSettings, -// GraphicsSettings &GraphicsSettings, -// LauncherSettings &launcherSettings); - bool setup(); bool showFirstRunDialog(); @@ -58,9 +52,6 @@ private: void closeEvent(QCloseEvent *event); -// QListWidget *mIconWidget; -// QStackedWidget *mPagesWidget; - PlayPage *mPlayPage; GraphicsPage *mGraphicsPage; DataFilesPage *mDataFilesPage; diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp index b082e2e2c..27b7846dd 100644 --- a/apps/launcher/playpage.cpp +++ b/apps/launcher/playpage.cpp @@ -4,45 +4,37 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent) { - QWidget *playWidget = new QWidget(this); - playWidget->setObjectName("PlayGroup"); - playWidget->setFixedSize(QSize(425, 375)); - - mPlayButton = new QPushButton(tr("Play"), playWidget); - mPlayButton->setObjectName("PlayButton"); - mPlayButton->setMinimumSize(QSize(200, 50)); - - QLabel *profileLabel = new QLabel(tr("Current Profile:"), playWidget); - profileLabel->setObjectName("ProfileLabel"); + setupUi(this); // Hacks to get the stylesheet look properly on different platforms QPlastiqueStyle *style = new QPlastiqueStyle; QFont font = QApplication::font(); font.setPointSize(12); // Fixes problem with overlapping items - mProfilesComboBox = new QComboBox(playWidget); - mProfilesComboBox->setObjectName("ProfilesComboBox"); - mProfilesComboBox->setStyle(style); - mProfilesComboBox->setFont(font); + profilesComboBox->setStyle(style); + profilesComboBox->setFont(font); - QGridLayout *playLayout = new QGridLayout(playWidget); - - QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - QSpacerItem *hSpacer2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - QSpacerItem *vSpacer1 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - QSpacerItem *vSpacer2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - - playLayout->addWidget(mPlayButton, 1, 1, 1, 1); - playLayout->addWidget(profileLabel, 2, 1, 1, 1); - playLayout->addWidget(mProfilesComboBox, 3, 1, 1, 1); - playLayout->addItem(hSpacer1, 2, 0, 1, 1); - playLayout->addItem(hSpacer2, 2, 2, 1, 1); - playLayout->addItem(vSpacer1, 0, 1, 1, 1); - playLayout->addItem(vSpacer2, 4, 1, 1, 1); - - QHBoxLayout *pageLayout = new QHBoxLayout(this); - - pageLayout->addWidget(playWidget); + connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int))); + connect(playButton, SIGNAL(clicked()), this, SLOT(slotPlayClicked())); } + +void PlayPage::setProfilesComboBoxModel(QAbstractItemModel *model) +{ + profilesComboBox->setModel(model); +} + +void PlayPage::setProfilesComboBoxIndex(int index) +{ + profilesComboBox->setCurrentIndex(index); +} + +void PlayPage::slotCurrentIndexChanged(int index) +{ + emit profileChanged(index); +} + +void PlayPage::slotPlayClicked() +{ + emit playButtonClicked(); +} diff --git a/apps/launcher/playpage.hpp b/apps/launcher/playpage.hpp index efec6f2b3..4306396bd 100644 --- a/apps/launcher/playpage.hpp +++ b/apps/launcher/playpage.hpp @@ -3,19 +3,33 @@ #include +#include "ui_playpage.h" + class QComboBox; class QPushButton; +class QAbstractItemModel; -class PlayPage : public QWidget +class PlayPage : public QWidget, private Ui::PlayPage { Q_OBJECT public: PlayPage(QWidget *parent = 0); + void setProfilesComboBoxModel(QAbstractItemModel *model); + +signals: + void profileChanged(int index); + void playButtonClicked(); + +public slots: + void setProfilesComboBoxIndex(int index); + +private slots: + void slotCurrentIndexChanged(int index); + void slotPlayClicked(); + - QComboBox *mProfilesComboBox; - QPushButton *mPlayButton; }; -#endif \ No newline at end of file +#endif diff --git a/apps/launcher/ui/graphicspage.ui b/apps/launcher/ui/graphicspage.ui index 670b4f9c6..e04cd5855 100644 --- a/apps/launcher/ui/graphicspage.ui +++ b/apps/launcher/ui/graphicspage.ui @@ -1,7 +1,7 @@ - graphicsPage - + GraphicsPage + 0 diff --git a/apps/launcher/ui/playpage.ui b/apps/launcher/ui/playpage.ui index 86a763f64..ccd17f519 100644 --- a/apps/launcher/ui/playpage.ui +++ b/apps/launcher/ui/playpage.ui @@ -1,107 +1,38 @@ - playPage - - - #playPage { + PlayPage + + + + + + #Scroll { background-image: url(":/images/playpage-background.png"); background-repeat: no-repeat; background-position: top; } - - - - 30 - - - 100 - - - 30 - - - - - - 200 - 85 - - - - 200 - 85 - + + QFrame::StyledPanel - - #playButton { - height: 50px; - margin-bottom: 30px; - - background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, - stop:0 rgba(255, 255, 255, 200), - stop:0.1 rgba(255, 255, 255, 15), - stop:0.49 rgba(255, 255, 255, 75), - stop:0.5 rgba(0, 0, 0, 0), - stop:0.9 rgba(0, 0, 0, 55), - stop:1 rgba(0, 0, 0, 100)); - - font-size: 26pt; - font-family: "EB Garamond", "EB Garamond 08"; - color: black; - - border-right: 1px solid rgba(0, 0, 0, 155); - border-left: 1px solid rgba(0, 0, 0, 55); - border-top: 1px solid rgba(0, 0, 0, 55); - border-bottom: 1px solid rgba(0, 0, 0, 155); - - border-radius: 5px; -} - -#playButton:hover { - border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-width: 2px; - border-style: solid; -} - -#playButton:pressed { - 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), - stop:0.2 rgba(255, 255, 255, 55) - stop:0.95 rgba(255, 255, 255, 55), - stop:1 rgba(255, 255, 255, 155)); - - border: 1px solid rgba(0, 0, 0, 55); -} + + QFrame::Plain - - Play - - - - - - - #profileLabel { - font-size: 18pt; - font-family: "EB Garamond", "EB Garamond 08"; -} - - - - Current Profile: - - - - - - - #profilesComboBox { + + + 30 + + + 100 + + + 30 + + + + + #profilesComboBox { padding: 1px 18px 1px 3px; background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:0.2 rgba(0, 0, 0, 25), stop:1 white); @@ -155,22 +86,103 @@ border-radius: 5px; } - + + + + + + + #profileLabel { + font-size: 18pt; + font-family: "EB Garamond", "EB Garamond 08"; +} + + + + Current Profile: + + + + + + + + 200 + 85 + + + + + 200 + 85 + + + + #playButton { + height: 50px; + margin-bottom: 30px; + + background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 rgba(255, 255, 255, 200), + stop:0.1 rgba(255, 255, 255, 15), + stop:0.49 rgba(255, 255, 255, 75), + stop:0.5 rgba(0, 0, 0, 0), + stop:0.9 rgba(0, 0, 0, 55), + stop:1 rgba(0, 0, 0, 100)); + + font-size: 26pt; + font-family: "EB Garamond", "EB Garamond 08"; + color: black; + + border-right: 1px solid rgba(0, 0, 0, 155); + border-left: 1px solid rgba(0, 0, 0, 55); + border-top: 1px solid rgba(0, 0, 0, 55); + border-bottom: 1px solid rgba(0, 0, 0, 155); + + border-radius: 5px; +} + +#playButton:hover { + border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-width: 2px; + border-style: solid; +} + +#playButton:pressed { + 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), + stop:0.2 rgba(255, 255, 255, 55) + stop:0.95 rgba(255, 255, 255, 55), + stop:1 rgba(255, 255, 255, 155)); + + border: 1px solid rgba(0, 0, 0, 55); +} + + + Play + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - From 8c0326a49c94583fc50eff481408c59654fdee6f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 2 Mar 2013 18:30:28 -0800 Subject: [PATCH 086/151] Handle NiZBufferProperty --- components/nifogre/ogre_nif_loader.cpp | 33 +++++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 1d0d31961..1ea911a77 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -553,7 +553,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String const Nif::NiTexturingProperty *texprop, const Nif::NiMaterialProperty *matprop, const Nif::NiAlphaProperty *alphaprop, - const Nif::NiVertexColorProperty *vertprop) + const Nif::NiVertexColorProperty *vertprop, + const Nif::NiZBufferProperty *zprop) { Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); Ogre::MaterialPtr material = matMgr.getByName(name); @@ -570,6 +571,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String int alphaTest = 0; int vertMode = 2; //int lightMode = 1; + int depthFlags = 3; Ogre::String texName; bool vertexColour = (shape->data->colors.size() != 0); @@ -628,6 +630,12 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String //lightMode = vertprop->data.lightmode; } + if(zprop) + { + depthFlags = zprop->flags; + // Depth function??? + } + // Material if(matprop) { @@ -731,8 +739,11 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String instance->setProperty("alpha_rejection", sh::makeProperty(new sh::StringValue(reject))); } - instance->setProperty("transparent_sorting", sh::makeProperty(new sh::StringValue(((alphaFlags>>13)&1) ? - "off" : "on"))); + instance->setProperty("transparent_sorting", sh::makeProperty(new sh::BooleanValue(!((alphaFlags>>13)&1)))); + + instance->setProperty("depth_check", sh::makeProperty(new sh::BooleanValue(depthFlags&1))); + instance->setProperty("depth_write", sh::makeProperty(new sh::BooleanValue((depthFlags>>1)&1))); + // depth_func??? sh::Factory::getInstance()._ensureMaterial(matname, "Default"); return matname; @@ -769,7 +780,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader const Nif::NiTexturingProperty *texprop, const Nif::NiMaterialProperty *matprop, const Nif::NiAlphaProperty *alphaprop, - const Nif::NiVertexColorProperty *vertprop) + const Nif::NiVertexColorProperty *vertprop, + const Nif::NiZBufferProperty *zprop) { Ogre::SkeletonPtr skel; const Nif::NiTriShapeData *data = shape->data.getPtr(); @@ -969,7 +981,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader std::string matname = NIFMaterialLoader::getMaterial(shape, mName, mGroup, texprop, matprop, alphaprop, - vertprop); + vertprop, zprop); if(matname.length() > 0) sub->setMaterialName(matname); } @@ -978,7 +990,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader const Nif::NiTexturingProperty *texprop=NULL, const Nif::NiMaterialProperty *matprop=NULL, const Nif::NiAlphaProperty *alphaprop=NULL, - const Nif::NiVertexColorProperty *vertprop=NULL) + const Nif::NiVertexColorProperty *vertprop=NULL, + const Nif::NiZBufferProperty *zprop=NULL) { // Scan the property list for material information const Nif::PropertyList &proplist = node->props; @@ -997,25 +1010,27 @@ class NIFMeshLoader : Ogre::ManualResourceLoader alphaprop = static_cast(pr); else if(pr->recType == Nif::RC_NiVertexColorProperty) vertprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiZBufferProperty) + zprop = static_cast(pr); else warn("Unhandled property type: "+pr->recName); } if(node->recType == Nif::RC_NiTriShape && mShapeIndex == node->recIndex) { - handleNiTriShape(mesh, dynamic_cast(node), texprop, matprop, alphaprop, vertprop); + handleNiTriShape(mesh, dynamic_cast(node), texprop, matprop, alphaprop, vertprop, zprop); return true; } const Nif::NiNode *ninode = dynamic_cast(node); if(ninode) { - Nif::NodeList const &children = ninode->children; + const Nif::NodeList &children = ninode->children; for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) { - if(findTriShape(mesh, children[i].getPtr(), texprop, matprop, alphaprop, vertprop)) + if(findTriShape(mesh, children[i].getPtr(), texprop, matprop, alphaprop, vertprop, zprop)) return true; } } From 8e35159ad4e5372d6bd0dcaad9542f33b8f3b753 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 2 Mar 2013 19:06:28 -0800 Subject: [PATCH 087/151] Handle NiSpecularProperty --- components/nifogre/ogre_nif_loader.cpp | 33 +++++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 1ea911a77..773a6b18d 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -554,7 +554,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String const Nif::NiMaterialProperty *matprop, const Nif::NiAlphaProperty *alphaprop, const Nif::NiVertexColorProperty *vertprop, - const Nif::NiZBufferProperty *zprop) + const Nif::NiZBufferProperty *zprop, + const Nif::NiSpecularProperty *specprop) { Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); Ogre::MaterialPtr material = matMgr.getByName(name); @@ -572,6 +573,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String int vertMode = 2; //int lightMode = 1; int depthFlags = 3; + int specFlags = 1; Ogre::String texName; bool vertexColour = (shape->data->colors.size() != 0); @@ -636,6 +638,11 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String // Depth function??? } + if(specprop) + { + specFlags = specprop->flags; + } + // Material if(matprop) { @@ -669,6 +676,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String boost::hash_combine(h, alphaFlags); boost::hash_combine(h, alphaTest); boost::hash_combine(h, vertMode); + boost::hash_combine(h, specFlags); std::map::iterator itr = MaterialMap.find(h); if (itr != MaterialMap.end()) @@ -703,13 +711,16 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String else std::cerr<< "Unhandled vertex mode: "<setProperty("specular", sh::makeProperty( - new sh::Vector4(specular.x, specular.y, specular.z, glossiness*255.0f))); + if(specFlags) + { + instance->setProperty("specular", sh::makeProperty( + new sh::Vector4(specular.x, specular.y, specular.z, glossiness*255.0f))); + } instance->setProperty("diffuseMap", sh::makeProperty(texName)); if (vertexColour) - instance->setProperty ("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); + instance->setProperty("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); // Add transparency if NiAlphaProperty was present NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName); @@ -781,7 +792,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader const Nif::NiMaterialProperty *matprop, const Nif::NiAlphaProperty *alphaprop, const Nif::NiVertexColorProperty *vertprop, - const Nif::NiZBufferProperty *zprop) + const Nif::NiZBufferProperty *zprop, + const Nif::NiSpecularProperty *specprop) { Ogre::SkeletonPtr skel; const Nif::NiTriShapeData *data = shape->data.getPtr(); @@ -981,7 +993,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader std::string matname = NIFMaterialLoader::getMaterial(shape, mName, mGroup, texprop, matprop, alphaprop, - vertprop, zprop); + vertprop, zprop, specprop); if(matname.length() > 0) sub->setMaterialName(matname); } @@ -991,7 +1003,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader const Nif::NiMaterialProperty *matprop=NULL, const Nif::NiAlphaProperty *alphaprop=NULL, const Nif::NiVertexColorProperty *vertprop=NULL, - const Nif::NiZBufferProperty *zprop=NULL) + const Nif::NiZBufferProperty *zprop=NULL, + const Nif::NiSpecularProperty *specprop=NULL) { // Scan the property list for material information const Nif::PropertyList &proplist = node->props; @@ -1012,13 +1025,15 @@ class NIFMeshLoader : Ogre::ManualResourceLoader vertprop = static_cast(pr); else if(pr->recType == Nif::RC_NiZBufferProperty) zprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiSpecularProperty) + specprop = static_cast(pr); else warn("Unhandled property type: "+pr->recName); } if(node->recType == Nif::RC_NiTriShape && mShapeIndex == node->recIndex) { - handleNiTriShape(mesh, dynamic_cast(node), texprop, matprop, alphaprop, vertprop, zprop); + handleNiTriShape(mesh, dynamic_cast(node), texprop, matprop, alphaprop, vertprop, zprop, specprop); return true; } @@ -1030,7 +1045,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { if(!children[i].empty()) { - if(findTriShape(mesh, children[i].getPtr(), texprop, matprop, alphaprop, vertprop, zprop)) + if(findTriShape(mesh, children[i].getPtr(), texprop, matprop, alphaprop, vertprop, zprop, specprop)) return true; } } From 7930aa82b2d90e96bc11dc9e20b99650561ebdba Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 2 Mar 2013 19:09:15 -0800 Subject: [PATCH 088/151] Add missing depthFlags to the hash --- components/nifogre/ogre_nif_loader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 773a6b18d..9537f550b 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -676,6 +676,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String boost::hash_combine(h, alphaFlags); boost::hash_combine(h, alphaTest); boost::hash_combine(h, vertMode); + boost::hash_combine(h, depthFlags); boost::hash_combine(h, specFlags); std::map::iterator itr = MaterialMap.find(h); From 21e2c287ebf60130db3669666d0557d8b34c4f7b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 2 Mar 2013 19:30:23 -0800 Subject: [PATCH 089/151] Fix/workaround specular issues The glossiness should not be multiplied by 255, however the values set in many of Bloodmoon's meshes would look horrible otherwise. Now we can let the NiSpecularProperty specify when to enable specular (which is supposed to default to on, but due to the aforementioned meshes, we default to off). --- components/nifogre/ogre_nif_loader.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 9537f550b..9652fd605 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -573,7 +573,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String int vertMode = 2; //int lightMode = 1; int depthFlags = 3; - int specFlags = 1; + // Default should be 1, but Bloodmoon's models are broken + int specFlags = 0; Ogre::String texName; bool vertexColour = (shape->data->colors.size() != 0); @@ -715,7 +716,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String if(specFlags) { instance->setProperty("specular", sh::makeProperty( - new sh::Vector4(specular.x, specular.y, specular.z, glossiness*255.0f))); + new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); } instance->setProperty("diffuseMap", sh::makeProperty(texName)); From cf87708c1fc4a83aac6c668f3125020373371a5a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 12:01:19 +0100 Subject: [PATCH 090/151] Magic effect icons for spells --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/hud.cpp | 23 ++- apps/openmw/mwgui/hud.hpp | 10 +- apps/openmw/mwgui/spellicons.cpp | 246 +++++++++++++++++++++++ apps/openmw/mwgui/spellicons.hpp | 47 +++++ apps/openmw/mwgui/spellwindow.cpp | 10 + apps/openmw/mwgui/spellwindow.hpp | 5 + apps/openmw/mwgui/tooltips.cpp | 12 +- apps/openmw/mwgui/tooltips.hpp | 4 + apps/openmw/mwgui/widgets.cpp | 12 +- apps/openmw/mwgui/windowmanagerimp.cpp | 3 + apps/openmw/mwgui/windowmanagerimp.hpp | 1 + apps/openmw/mwmechanics/activespells.cpp | 5 + apps/openmw/mwmechanics/activespells.hpp | 2 + files/mygui/openmw_hud.layout | 5 +- files/mygui/openmw_hud_box.skin.xml | 4 + files/mygui/openmw_spell_window.layout | 4 +- 17 files changed, 360 insertions(+), 35 deletions(-) create mode 100644 apps/openmw/mwgui/spellicons.cpp create mode 100644 apps/openmw/mwgui/spellicons.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 7cfeb84c5..e09dfb108 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -30,7 +30,7 @@ add_openmw_dir (mwgui formatting inventorywindow container hud countdialog tradewindow settingswindow confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog - enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor + enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index a2c3a318b..2eb96249c 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -19,6 +19,7 @@ #include "inventorywindow.hpp" #include "container.hpp" #include "console.hpp" +#include "spellicons.hpp" using namespace MWGui; @@ -32,7 +33,6 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mWeapStatus(NULL) , mSpellStatus(NULL) , mEffectBox(NULL) - , mEffect1(NULL) , mMinimap(NULL) , mCompass(NULL) , mCrosshair(NULL) @@ -86,9 +86,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) mSpellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked); getWidget(mEffectBox, "EffectBox"); - getWidget(mEffect1, "Effect1"); mEffectBoxBaseRight = viewSize.width - mEffectBox->getRight(); - mEffectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked); getWidget(mMinimapBox, "MiniMapBox"); mMinimapBoxBaseRight = viewSize.width - mMinimapBox->getRight(); @@ -107,13 +105,18 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(mTriangleCounter, "TriangleCounter"); getWidget(mBatchCounter, "BatchCounter"); - setEffect("icons\\s\\tx_s_chameleon.dds"); - LocalMapBase::init(mMinimap, mCompass, this); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver); mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus); + + mSpellIcons = new SpellIcons(); +} + +HUD::~HUD() +{ + delete mSpellIcons; } void HUD::setFpsLevel(int level) @@ -156,11 +159,6 @@ void HUD::setBatchCount(unsigned int count) mBatchCounter->setCaption(boost::lexical_cast(count)); } -void HUD::setEffect(const char *img) -{ - mEffect1->setImageTexture(img); -} - void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& value) { static const char *ids[] = @@ -542,3 +540,8 @@ void HUD::updatePositions() mMapVisible = mMinimapBox->getVisible (); mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop()); } + +void HUD::update() +{ + mSpellIcons->updateWidgets(mEffectBox, true); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 013ad59f0..39d6eadca 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -8,12 +8,13 @@ namespace MWGui { class DragAndDrop; + class SpellIcons; class HUD : public OEngine::GUI::Layout, public LocalMapBase { public: HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); - void setEffect(const char *img); + virtual ~HUD(); void setValue (const std::string& id, const MWMechanics::DynamicStat& value); void setFPS(float fps); void setTriangleCount(unsigned int count); @@ -43,6 +44,10 @@ namespace MWGui bool getWorldMouseOver() { return mWorldMouseOver; } + MyGUI::Widget* getEffectBox() { return mEffectBox; } + + void update(); + private: MyGUI::ProgressPtr mHealth, mMagicka, mStamina; MyGUI::Widget* mHealthFrame; @@ -51,7 +56,6 @@ namespace MWGui MyGUI::ProgressPtr mWeapStatus, mSpellStatus; MyGUI::Widget *mEffectBox, *mMinimapBox; MyGUI::Button* mMinimapButton; - MyGUI::ImageBox* mEffect1; MyGUI::ScrollView* mMinimap; MyGUI::ImageBox* mCompass; MyGUI::ImageBox* mCrosshair; @@ -85,6 +89,8 @@ namespace MWGui bool mWorldMouseOver; + SpellIcons* mSpellIcons; + void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp new file mode 100644 index 000000000..19b2a87ec --- /dev/null +++ b/apps/openmw/mwgui/spellicons.cpp @@ -0,0 +1,246 @@ +#include "spellicons.hpp" + +#include +#include +#include + +#include + +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" + +#include "../mwworld/player.hpp" +#include "../mwworld/class.hpp" + +#include "../mwmechanics/activespells.hpp" +#include "../mwmechanics/creaturestats.hpp" + +#include "tooltips.hpp" + + +namespace MWGui +{ + + void SpellIcons::updateWidgets(MyGUI::Widget *parent, bool adjustSize) + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + const MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + + std::map > effects; + + // add permanent spells + const MWMechanics::Spells& spells = stats.getSpells(); + for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find(it->first); + + // these are the spell types that are permanently in effect + if (!(spell->mData.mType == ESM::Spell::ST_Ability) + && !(spell->mData.mType == ESM::Spell::ST_Disease) + && !(spell->mData.mType == ESM::Spell::ST_Curse) + && !(spell->mData.mType == ESM::Spell::ST_Blight)) + continue; + ESM::EffectList list = spell->mEffects; + for (std::vector::const_iterator effectIt = list.mList.begin(); + effectIt != list.mList.end(); ++effectIt) + { + const ESM::MagicEffect* magicEffect = + MWBase::Environment::get().getWorld ()->getStore ().get().find(effectIt->mEffectID); + MagicEffectInfo effectInfo; + effectInfo.mSource = getSpellDisplayName (it->first); + effectInfo.mKey = MWMechanics::EffectKey (effectIt->mEffectID); + if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill) + effectInfo.mKey.mArg = effectIt->mSkill; + else if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute) + effectInfo.mKey.mArg = effectIt->mAttribute; + // just using the min magnitude here, permanent spells with a random magnitude just wouldn't make any sense + effectInfo.mMagnitude = effectIt->mMagnMin; + effectInfo.mPermanent = true; + + effects[effectIt->mEffectID].push_back (effectInfo); + } + } + + // add lasting effect spells/potions etc + const MWMechanics::ActiveSpells::TContainer& activeSpells = stats.getActiveSpells().getActiveSpells(); + for (MWMechanics::ActiveSpells::TContainer::const_iterator it = activeSpells.begin(); + it != activeSpells.end(); ++it) + { + ESM::EffectList list = getSpellEffectList(it->first); + + float timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor(); + + for (std::vector::const_iterator effectIt = list.mList.begin(); + effectIt != list.mList.end(); ++effectIt) + { + const ESM::MagicEffect* magicEffect = + MWBase::Environment::get().getWorld ()->getStore ().get().find(effectIt->mEffectID); + + MagicEffectInfo effectInfo; + effectInfo.mSource = getSpellDisplayName (it->first); + effectInfo.mKey = MWMechanics::EffectKey (effectIt->mEffectID); + if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill) + effectInfo.mKey.mArg = effectIt->mSkill; + else if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute) + effectInfo.mKey.mArg = effectIt->mAttribute; + effectInfo.mMagnitude = effectIt->mMagnMin + (effectIt->mMagnMax-effectIt->mMagnMin) * it->second.second; + effectInfo.mRemainingTime = effectIt->mDuration + + (it->second.first - MWBase::Environment::get().getWorld()->getTimeStamp())*3600/timeScale; + + effects[effectIt->mEffectID].push_back (effectInfo); + } + } + + parent->setVisible(effects.size() != 0); + + int w=2; + if (adjustSize) + { + int s = effects.size() * 16+4; + int diff = parent->getWidth() - s; + parent->setSize(s, parent->getHeight()); + parent->setPosition(parent->getLeft()+diff, parent->getTop()); + } + + + for (std::map >::const_iterator it = effects.begin(); it != effects.end(); ++it) + { + MyGUI::ImageBox* image; + if (mWidgetMap.find(it->first) == mWidgetMap.end()) + image = parent->createWidget + ("ImageBox", MyGUI::IntCoord(w,2,16,16), MyGUI::Align::Default); + else + image = mWidgetMap[it->first]; + mWidgetMap[it->first] = image; + image->setPosition(w,2); + image->setVisible(true); + + const ESM::MagicEffect* effect = + MWBase::Environment::get().getWorld ()->getStore ().get().find(it->first); + + std::string icon = effect->mIcon; + icon[icon.size()-3] = 'd'; + icon[icon.size()-2] = 'd'; + icon[icon.size()-1] = 's'; + icon = "icons\\" + icon; + + image->setImageTexture(icon); + w += 16; + + float remainingDuration = 0; + + std::string sourcesDescription; + + const float fadeTime = 5.f; + + for (std::vector::const_iterator effectIt = it->second.begin(); + effectIt != it->second.end(); ++effectIt) + { + if (effectIt != it->second.begin()) + sourcesDescription += "\n"; + + // if at least one of the effect sources is permanent, the effect will never wear off + if (effectIt->mPermanent) + remainingDuration = fadeTime; + else + remainingDuration = std::max(remainingDuration, effectIt->mRemainingTime); + + sourcesDescription += effectIt->mSource; + + if (effect->mData.mFlags & ESM::MagicEffect::TargetSkill) + sourcesDescription += " (" + + MWBase::Environment::get().getWindowManager()->getGameSettingString( + ESM::Skill::sSkillNameIds[effectIt->mKey.mArg], "") + ")"; + if (effect->mData.mFlags & ESM::MagicEffect::TargetAttribute) + sourcesDescription += " (" + + MWBase::Environment::get().getWindowManager()->getGameSettingString( + ESM::Attribute::sGmstAttributeIds[effectIt->mKey.mArg], "") + ")"; + + if (!(effect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) + { + std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); + std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); + + sourcesDescription += ": " + boost::lexical_cast(effectIt->mMagnitude); + sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? pts : pt); + } + } + + std::string name = ESM::MagicEffect::effectIdToString (it->first); + + ToolTipInfo tooltipInfo; + tooltipInfo.caption = "#{" + name + "}"; + tooltipInfo.icon = effect->mIcon; + tooltipInfo.text = sourcesDescription; + tooltipInfo.imageSize = 16; + tooltipInfo.wordWrap = false; + + image->setUserData(tooltipInfo); + image->setUserString("ToolTipType", "ToolTipInfo"); + + // Fade out during the last 5 seconds + image->setAlpha(std::min(remainingDuration/fadeTime, 1.f)); + } + + // hide inactive effects + for (std::map::iterator it = mWidgetMap.begin(); it != mWidgetMap.end(); ++it) + { + if (effects.find(it->first) == effects.end()) + it->second->setVisible(false); + } + + } + + + std::string SpellIcons::getSpellDisplayName (const std::string& id) + { + if (const ESM::Spell *spell = + MWBase::Environment::get().getWorld()->getStore().get().search (id)) + return spell->mName; + + if (const ESM::Potion *potion = + MWBase::Environment::get().getWorld()->getStore().get().search (id)) + return potion->mName; + + if (const ESM::Ingredient *ingredient = + MWBase::Environment::get().getWorld()->getStore().get().search (id)) + return ingredient->mName; + + throw std::runtime_error ("ID " + id + " has no display name"); + } + + ESM::EffectList SpellIcons::getSpellEffectList (const std::string& id) + { + if (const ESM::Spell *spell = + MWBase::Environment::get().getWorld()->getStore().get().search (id)) + return spell->mEffects; + + if (const ESM::Potion *potion = + MWBase::Environment::get().getWorld()->getStore().get().search (id)) + return potion->mEffects; + + if (const ESM::Ingredient *ingredient = + MWBase::Environment::get().getWorld()->getStore().get().search (id)) + { + const ESM::MagicEffect *magicEffect = + MWBase::Environment::get().getWorld()->getStore().get().find ( + ingredient->mData.mEffectID[0]); + + ESM::ENAMstruct effect; + effect.mEffectID = ingredient->mData.mEffectID[0]; + effect.mSkill = ingredient->mData.mSkills[0]; + effect.mAttribute = ingredient->mData.mAttributes[0]; + effect.mRange = 0; + effect.mArea = 0; + effect.mDuration = magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration ? 0 : 1; + effect.mMagnMin = 1; + effect.mMagnMax = 1; + ESM::EffectList result; + result.mList.push_back (effect); + return result; + } + throw std::runtime_error("ID " + id + " does not have effects"); + } + +} diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp new file mode 100644 index 000000000..af600e347 --- /dev/null +++ b/apps/openmw/mwgui/spellicons.hpp @@ -0,0 +1,47 @@ +#ifndef MWGUI_SPELLICONS_H +#define MWGUI_SPELLICONS_H + +#include + +#include "../mwmechanics/magiceffects.hpp" + +namespace MyGUI +{ + class Widget; + class ImageBox; +} +namespace ESM +{ + struct ENAMstruct; + struct EffectList; +} + +namespace MWGui +{ + + // information about a single magic effect source as required for display in the tooltip + struct MagicEffectInfo + { + MagicEffectInfo() : mPermanent(false) {} + std::string mSource; // display name for effect source (e.g. potion name) + MWMechanics::EffectKey mKey; + int mMagnitude; + float mRemainingTime; + bool mPermanent; // the effect is permanent + }; + + class SpellIcons + { + public: + void updateWidgets(MyGUI::Widget* parent, bool adjustSize); + + private: + std::string getSpellDisplayName (const std::string& id); + ESM::EffectList getSpellEffectList (const std::string& id); + + std::map mWidgetMap; + }; + +} + +#endif diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 47e1d739a..50691d554 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -19,6 +19,7 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/spellsuccess.hpp" +#include "spellicons.hpp" #include "inventorywindow.hpp" #include "confirmationdialog.hpp" @@ -51,6 +52,8 @@ namespace MWGui , mHeight(0) , mWidth(0) { + mSpellIcons = new SpellIcons(); + getWidget(mSpellView, "SpellView"); getWidget(mEffectBox, "EffectsBox"); @@ -61,6 +64,11 @@ namespace MWGui mMainWidget->castType()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize); } + SpellWindow::~SpellWindow() + { + delete mSpellIcons; + } + void SpellWindow::onPinToggled() { mWindowManager.setSpellVisibility(!mPinned); @@ -73,6 +81,8 @@ namespace MWGui void SpellWindow::updateSpells() { + mSpellIcons->updateWidgets(mEffectBox, false); + const int spellHeight = 18; mHeight = 0; diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index caa67fd74..1963d4346 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -5,10 +5,13 @@ namespace MWGui { + class SpellIcons; + class SpellWindow : public WindowPinnableBase { public: SpellWindow(MWBase::WindowManager& parWindowManager); + virtual ~SpellWindow(); void updateSpells(); @@ -33,6 +36,8 @@ namespace MWGui virtual void onPinToggled(); virtual void open(); + + SpellIcons* mSpellIcons; }; } diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index c7acf568d..b42f9ac25 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -127,9 +127,7 @@ void ToolTips::onFrame(float frameDuration) Widget* focus = InputManager::getInstance().getMouseFocusWidget(); if (focus == 0) - { return; - } IntSize tooltipSize; @@ -168,6 +166,10 @@ void ToolTips::onFrame(float frameDuration) mFocusObject = *focus->getUserData(); tooltipSize = getToolTipViaPtr(false); } + else if (type == "ToolTipInfo") + { + tooltipSize = createToolTip(*focus->getUserData()); + } else if (type == "AvatarItemSelection") { MyGUI::IntCoord avatarPos = mWindowManager->getInventoryWindow ()->getAvatarScreenCoord (); @@ -363,7 +365,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) std::string caption = info.caption; std::string image = info.icon; - int imageSize = (image != "") ? 32 : 0; + int imageSize = (image != "") ? info.imageSize : 0; std::string text = info.text; // remove the first newline (easier this way) @@ -403,7 +405,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) EditBox* captionWidget = mDynamicToolTipBox->createWidget("NormalText", IntCoord(0, 0, 300, 300), Align::Left | Align::Top, "ToolTipCaption"); captionWidget->setProperty("Static", "true"); - captionWidget->setCaption(caption); + captionWidget->setCaptionWithReplacing(caption); IntSize captionSize = captionWidget->getTextSize(); int captionHeight = std::max(caption != "" ? captionSize.height : 0, imageSize); @@ -411,7 +413,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) EditBox* textWidget = mDynamicToolTipBox->createWidget("SandText", IntCoord(0, captionHeight+imageCaptionVPadding, 300, 300-captionHeight-imageCaptionVPadding), Align::Stretch, "ToolTipText"); textWidget->setProperty("Static", "true"); textWidget->setProperty("MultiLine", "true"); - textWidget->setProperty("WordWrap", "true"); + textWidget->setProperty("WordWrap", info.wordWrap ? "true" : "false"); textWidget->setCaptionWithReplacing(text); textWidget->setTextAlign(Align::HCenter | Align::Top); IntSize textSize = textWidget->getTextSize(); diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 4048d0d5a..ba94915cc 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -15,11 +15,14 @@ namespace MWGui public: ToolTipInfo() : isPotion(false) + , imageSize(32) + , wordWrap(true) {} std::string caption; std::string text; std::string icon; + int imageSize; // enchantment (for cloth, armor, weapons) std::string enchant; @@ -28,6 +31,7 @@ namespace MWGui Widgets::SpellEffectList effects; bool isPotion; // potions do not show target in the tooltip + bool wordWrap; }; class ToolTips : public OEngine::GUI::Layout diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index f932c1f03..ade681963 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -421,17 +421,7 @@ void MWSpellEffect::updateWidgets() } if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute) { - static const char *attributes[8] = { - "sAttributeStrength", - "sAttributeIntelligence", - "sAttributeWillpower", - "sAttributeAgility", - "sAttributeSpeed", - "sAttributeEndurance", - "sAttributePersonality", - "sAttributeLuck" - }; - spellLine += " " + mWindowManager->getGameSettingString(attributes[mEffectParams.mAttribute], ""); + spellLine += " " + mWindowManager->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], ""); } if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 1138f62fa..0110171e6 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -54,6 +54,7 @@ #include "imagebutton.hpp" #include "exposedwindow.hpp" #include "cursor.hpp" +#include "spellicons.hpp" using namespace MWGui; @@ -270,6 +271,8 @@ void WindowManager::update() mHud->setTriangleCount(mTriangleCount); mHud->setBatchCount(mBatchCount); + mHud->update(); + mCursor->update(); } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index e2d64a855..4e8f12160 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -73,6 +73,7 @@ namespace MWGui class EnchantingDialog; class TrainingWindow; class Cursor; + class SpellIcons; class WindowManager : public MWBase::WindowManager { diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index ee1e9da36..933c5094d 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -274,4 +274,9 @@ namespace MWMechanics } return false; } + + const ActiveSpells::TContainer& ActiveSpells::getActiveSpells() const + { + return mSpells; + } } diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 6b832f4cd..05aa2bbdd 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -63,6 +63,8 @@ namespace MWMechanics const MagicEffects& getMagicEffects() const; + const TContainer& getActiveSpells() const; + TIterator begin() const; TIterator end() const; diff --git a/files/mygui/openmw_hud.layout b/files/mygui/openmw_hud.layout index e4c6f0765..382bc6dc9 100644 --- a/files/mygui/openmw_hud.layout +++ b/files/mygui/openmw_hud.layout @@ -61,10 +61,7 @@ - - + diff --git a/files/mygui/openmw_hud_box.skin.xml b/files/mygui/openmw_hud_box.skin.xml index 23480e8d3..f847ca51a 100644 --- a/files/mygui/openmw_hud_box.skin.xml +++ b/files/mygui/openmw_hud_box.skin.xml @@ -16,6 +16,10 @@ + + + + diff --git a/files/mygui/openmw_spell_window.layout b/files/mygui/openmw_spell_window.layout index 6c6629605..18a5af352 100644 --- a/files/mygui/openmw_spell_window.layout +++ b/files/mygui/openmw_spell_window.layout @@ -4,8 +4,8 @@ - - + + From 8e05c4159d309259cd31fd30181e1593d0e02ffb Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 12:17:37 +0100 Subject: [PATCH 091/151] Magic effect icons for permanent enchantments --- apps/openmw/mwgui/spellicons.cpp | 40 ++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 19b2a87ec..dcbbed49c 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -12,6 +12,7 @@ #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/inventorystore.hpp" #include "../mwmechanics/activespells.hpp" #include "../mwmechanics/creaturestats.hpp" @@ -29,6 +30,41 @@ namespace MWGui std::map > effects; + // add permanent item enchantments + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) + { + MWWorld::ContainerStoreIterator it = store.getSlot(slot); + if (it == store.end()) + continue; + std::string enchantment = MWWorld::Class::get(*it).getEnchantment(*it); + if (enchantment.empty()) + continue; + const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().get().find(enchantment); + if (enchant->mData.mType != ESM::Enchantment::ConstantEffect) + continue; + + const ESM::EffectList& list = enchant->mEffects; + for (std::vector::const_iterator effectIt = list.mList.begin(); + effectIt != list.mList.end(); ++effectIt) + { + const ESM::MagicEffect* magicEffect = + MWBase::Environment::get().getWorld ()->getStore ().get().find(effectIt->mEffectID); + + MagicEffectInfo effectInfo; + effectInfo.mSource = MWWorld::Class::get(*it).getName(*it); + effectInfo.mKey = MWMechanics::EffectKey (effectIt->mEffectID); + if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill) + effectInfo.mKey.mArg = effectIt->mSkill; + else if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute) + effectInfo.mKey.mArg = effectIt->mAttribute; + // just using the min magnitude here, permanent enchantments with a random magnitude just wouldn't make any sense + effectInfo.mMagnitude = effectIt->mMagnMin; + effectInfo.mPermanent = true; + effects[effectIt->mEffectID].push_back (effectInfo); + } + } + // add permanent spells const MWMechanics::Spells& spells = stats.getSpells(); for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) @@ -41,7 +77,7 @@ namespace MWGui && !(spell->mData.mType == ESM::Spell::ST_Curse) && !(spell->mData.mType == ESM::Spell::ST_Blight)) continue; - ESM::EffectList list = spell->mEffects; + const ESM::EffectList& list = spell->mEffects; for (std::vector::const_iterator effectIt = list.mList.begin(); effectIt != list.mList.end(); ++effectIt) { @@ -67,7 +103,7 @@ namespace MWGui for (MWMechanics::ActiveSpells::TContainer::const_iterator it = activeSpells.begin(); it != activeSpells.end(); ++it) { - ESM::EffectList list = getSpellEffectList(it->first); + const ESM::EffectList& list = getSpellEffectList(it->first); float timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor(); From 6f05c4229f9183c04687fba5cc172bddb6e475d5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 12:41:37 +0100 Subject: [PATCH 092/151] Implemented potion & ingredient effect stacking --- apps/openmw/mwmechanics/activespells.cpp | 32 +++++++++++++----------- apps/openmw/mwmechanics/activespells.hpp | 5 ++-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 933c5094d..9aca6b7b7 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -62,7 +62,7 @@ namespace MWMechanics for (TIterator iter (begin()); iter!=end(); ++iter) { - std::pair effects = getEffectList (iter->first); + std::pair > effects = getEffectList (iter->first); const MWWorld::TimeStamp& start = iter->second.first; float magnitude = iter->second.second; @@ -74,7 +74,7 @@ namespace MWMechanics { int duration = iter->mDuration; - if (effects.second) + if (effects.second.first) duration *= magnitude; MWWorld::TimeStamp end = start; @@ -85,7 +85,7 @@ namespace MWMechanics { EffectParam param; - if (effects.second) + if (effects.second.first) { const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find ( @@ -113,15 +113,15 @@ namespace MWMechanics } } - std::pair ActiveSpells::getEffectList (const std::string& id) const + std::pair > ActiveSpells::getEffectList (const std::string& id) const { if (const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().get().search (id)) - return std::make_pair (spell->mEffects, false); + return std::make_pair (spell->mEffects, std::make_pair(false, false)); if (const ESM::Potion *potion = MWBase::Environment::get().getWorld()->getStore().get().search (id)) - return std::make_pair (potion->mEffects, false); + return std::make_pair (potion->mEffects, std::make_pair(false, true)); if (const ESM::Ingredient *ingredient = MWBase::Environment::get().getWorld()->getStore().get().search (id)) @@ -140,11 +140,12 @@ namespace MWMechanics effect.mMagnMin = 1; effect.mMagnMax = 1; - std::pair result; - + std::pair > result; + result.second.second = true; + result.second.first = true; + result.first.mList.push_back (effect); - result.second = true; - + return result; } @@ -157,7 +158,8 @@ namespace MWMechanics bool ActiveSpells::addSpell (const std::string& id, const MWWorld::Ptr& actor) { - std::pair effects = getEffectList (id); + std::pair > effects = getEffectList (id); + bool stacks = effects.second.second; bool found = false; @@ -178,7 +180,7 @@ namespace MWMechanics float random = static_cast (std::rand()) / RAND_MAX; - if (effects.second) + if (effects.second.first) { // ingredient -> special treatment required. const CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor); @@ -194,7 +196,7 @@ namespace MWMechanics random *= 0.25 * x; } - if (iter==mSpells.end()) + if (iter==mSpells.end() || stacks) mSpells.insert (std::make_pair (id, std::make_pair (MWBase::Environment::get().getWorld()->getTimeStamp(), random))); else @@ -236,7 +238,7 @@ namespace MWMechanics double ActiveSpells::timeToExpire (const TIterator& iterator) const { - std::pair effects = getEffectList (iterator->first); + std::pair > effects = getEffectList (iterator->first); int duration = 0; @@ -247,7 +249,7 @@ namespace MWMechanics duration = iter->mDuration; } - if (effects.second) + if (effects.second.first) duration *= iterator->second.second; double scaledDuration = duration * diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 05aa2bbdd..8c859b2cb 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -30,7 +30,7 @@ namespace MWMechanics { public: - typedef std::map > TContainer; + typedef std::multimap > TContainer; typedef TContainer::const_iterator TIterator; private: @@ -44,7 +44,8 @@ namespace MWMechanics void rebuildEffects() const; - std::pair getEffectList (const std::string& id) const; + std::pair > getEffectList (const std::string& id) const; + ///< @return (EffectList, (isIngredient, stacks)) public: From 6037c44ea6850595bace11f5f0bde64f5ae8f31e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 12:41:57 +0100 Subject: [PATCH 093/151] Fix ingredient effect display --- apps/openmw/mwgui/spellicons.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index dcbbed49c..16e02ebba 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -124,6 +124,17 @@ namespace MWGui effectInfo.mRemainingTime = effectIt->mDuration + (it->second.first - MWBase::Environment::get().getWorld()->getTimeStamp())*3600/timeScale; + // ingredients need special casing for their magnitude / duration + /// \todo duplicated from ActiveSpells, helper function? + if (MWBase::Environment::get().getWorld()->getStore().get().search (it->first)) + { + effectInfo.mRemainingTime = effectIt->mDuration * it->second.second + + (it->second.first - MWBase::Environment::get().getWorld()->getTimeStamp())*3600/timeScale; + + effectInfo.mMagnitude = static_cast (0.05*it->second.second / (0.1 * magicEffect->mData.mBaseCost)); + } + + effects[effectIt->mEffectID].push_back (effectInfo); } } From 9a84f6744f561a4e8dd1e86d652602dae19ca330 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 13:11:02 +0100 Subject: [PATCH 094/151] Fix headers including whole MyGUI.h, forward declare where appropriate, and fix some deprecated types (WidgetPtr) --- apps/openmw/mwgui/alchemywindow.cpp | 2 +- apps/openmw/mwgui/birth.cpp | 12 +++--- apps/openmw/mwgui/birth.hpp | 4 +- apps/openmw/mwgui/class.cpp | 56 +++++++++++++------------- apps/openmw/mwgui/class.hpp | 18 ++++----- apps/openmw/mwgui/console.cpp | 4 +- apps/openmw/mwgui/console.hpp | 8 ++-- apps/openmw/mwgui/cursor.cpp | 4 +- apps/openmw/mwgui/dialogue.cpp | 6 +-- apps/openmw/mwgui/dialogue.hpp | 2 +- apps/openmw/mwgui/exposedwindow.cpp | 4 +- apps/openmw/mwgui/exposedwindow.hpp | 2 +- apps/openmw/mwgui/hud.cpp | 4 +- apps/openmw/mwgui/hud.hpp | 2 +- apps/openmw/mwgui/imagebutton.hpp | 2 +- apps/openmw/mwgui/journalwindow.hpp | 4 +- apps/openmw/mwgui/list.cpp | 5 ++- apps/openmw/mwgui/list.hpp | 7 +++- apps/openmw/mwgui/messagebox.cpp | 10 ++--- apps/openmw/mwgui/messagebox.hpp | 16 +++++--- apps/openmw/mwgui/race.cpp | 16 ++++---- apps/openmw/mwgui/race.hpp | 8 ++-- apps/openmw/mwgui/review.cpp | 6 +-- apps/openmw/mwgui/review.hpp | 2 +- apps/openmw/mwgui/stats_window.cpp | 4 +- apps/openmw/mwgui/stats_window.hpp | 4 +- apps/openmw/mwgui/text_input.cpp | 4 +- apps/openmw/mwgui/text_input.hpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 4 +- apps/openmw/mwgui/widgets.cpp | 47 +++++++++++---------- apps/openmw/mwgui/widgets.hpp | 22 ++++++---- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- libs/openengine/gui/manager.cpp | 9 +++-- libs/openengine/gui/manager.hpp | 2 + 34 files changed, 166 insertions(+), 138 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index db1a81c2c..fce612600 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -237,7 +237,7 @@ namespace MWGui Widgets::SpellEffectList _list = Widgets::MWEffectList::effectListFromESM(&list); effectsWidget->setEffectList(_list); - std::vector effectItems; + std::vector effectItems; effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0); effectsWidget->setCoord(coord); } diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 53e5c022d..4b07dd698 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -40,11 +40,11 @@ BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager) mBirthList->eventListMouseItemActivate += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth); mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth); - MyGUI::ButtonPtr backButton; + MyGUI::Button* backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked); @@ -55,7 +55,7 @@ BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager) void BirthDialog::setNextButtonShow(bool shown) { - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); if (shown) @@ -82,7 +82,7 @@ void BirthDialog::setBirthId(const std::string &birthId) if (boost::iequals(*mBirthList->getItemDataAt(i), birthId)) { mBirthList->setIndexSelected(i); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); break; } @@ -110,7 +110,7 @@ void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index) if (_index == MyGUI::ITEM_NONE) return; - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); const std::string *birthId = mBirthList->getItemDataAt(_index); @@ -159,7 +159,7 @@ void BirthDialog::updateBirths() void BirthDialog::updateSpells() { - for (std::vector::iterator it = mSpellItems.begin(); it != mSpellItems.end(); ++it) + for (std::vector::iterator it = mSpellItems.begin(); it != mSpellItems.end(); ++it) { MyGUI::Gui::getInstance().destroyWidget(*it); } diff --git a/apps/openmw/mwgui/birth.hpp b/apps/openmw/mwgui/birth.hpp index ad1c0b40f..d3f82dace 100644 --- a/apps/openmw/mwgui/birth.hpp +++ b/apps/openmw/mwgui/birth.hpp @@ -46,9 +46,9 @@ namespace MWGui void updateSpells(); MyGUI::ListBox* mBirthList; - MyGUI::WidgetPtr mSpellArea; + MyGUI::Widget* mSpellArea; MyGUI::ImageBox* mBirthImage; - std::vector mSpellItems; + std::vector mSpellItems; std::string mCurrentBirthId; }; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index f3bac898b..a2f09096a 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -31,11 +31,11 @@ GenerateClassResultDialog::GenerateClassResultDialog(MWBase::WindowManager& parW getWidget(mClassImage, "ClassImage"); getWidget(mClassName, "ClassName"); - MyGUI::ButtonPtr backButton; + MyGUI::Button* backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked); @@ -97,11 +97,11 @@ PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager) getWidget(mClassImage, "ClassImage"); - MyGUI::ButtonPtr backButton; + MyGUI::Button* backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked); @@ -111,7 +111,7 @@ PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager) void PickClassDialog::setNextButtonShow(bool shown) { - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); if (shown) @@ -138,7 +138,7 @@ void PickClassDialog::setClassId(const std::string &classId) if (boost::iequals(*mClassList->getItemDataAt(i), classId)) { mClassList->setIndexSelected(i); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); break; } @@ -166,7 +166,7 @@ void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index) if (_index == MyGUI::ITEM_NONE) return; - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); const std::string *classId = mClassList->getItemDataAt(_index); @@ -256,7 +256,7 @@ void InfoBoxDialog::fitToText(MyGUI::TextBox* widget) widget->setSize(size); } -void InfoBoxDialog::layoutVertically(MyGUI::WidgetPtr widget, int margin) +void InfoBoxDialog::layoutVertically(MyGUI::Widget* widget, int margin) { size_t count = widget->getChildCount(); int pos = 0; @@ -264,7 +264,7 @@ void InfoBoxDialog::layoutVertically(MyGUI::WidgetPtr widget, int margin) int width = 0; for (unsigned i = 0; i < count; ++i) { - MyGUI::WidgetPtr child = widget->getChildAt(i); + MyGUI::Widget* child = widget->getChildAt(i); if (!child->getVisible()) continue; @@ -302,7 +302,7 @@ std::string InfoBoxDialog::getText() const void InfoBoxDialog::setButtons(ButtonList &buttons) { - for (std::vector::iterator it = this->mButtons.begin(); it != this->mButtons.end(); ++it) + for (std::vector::iterator it = this->mButtons.begin(); it != this->mButtons.end(); ++it) { MyGUI::Gui::getInstance().destroyWidget(*it); } @@ -310,7 +310,7 @@ void InfoBoxDialog::setButtons(ButtonList &buttons) mCurrentButton = -1; // TODO: The buttons should be generated from a template in the layout file, ie. cloning an existing widget - MyGUI::ButtonPtr button; + MyGUI::Button* button; MyGUI::IntCoord coord = MyGUI::IntCoord(0, 0, mButtonBar->getWidth(), 10); ButtonList::const_iterator end = buttons.end(); for (ButtonList::const_iterator it = buttons.begin(); it != end; ++it) @@ -342,11 +342,11 @@ int InfoBoxDialog::getChosenButton() const return mCurrentButton; } -void InfoBoxDialog::onButtonClicked(MyGUI::WidgetPtr _sender) +void InfoBoxDialog::onButtonClicked(MyGUI::Widget* _sender) { - std::vector::const_iterator end = mButtons.end(); + std::vector::const_iterator end = mButtons.end(); int i = 0; - for (std::vector::const_iterator it = mButtons.begin(); it != end; ++it) + for (std::vector::const_iterator it = mButtons.begin(); it != end; ++it) { if (*it == _sender) { @@ -376,10 +376,10 @@ ClassChoiceDialog::ClassChoiceDialog(MWBase::WindowManager& parWindowManager) CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager) : WindowModal("openmw_chargen_create_class.layout", parWindowManager) - , mSpecDialog(nullptr) - , mAttribDialog(nullptr) - , mSkillDialog(nullptr) - , mDescDialog(nullptr) + , mSpecDialog(NULL) + , mAttribDialog(NULL) + , mSkillDialog(NULL) + , mDescDialog(NULL) { // Centre dialog center(); @@ -420,15 +420,15 @@ CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager) // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(mEditName); - MyGUI::ButtonPtr descriptionButton; + MyGUI::Button* descriptionButton; getWidget(descriptionButton, "DescriptionButton"); descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked); - MyGUI::ButtonPtr backButton; + MyGUI::Button* backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onOkClicked); @@ -518,7 +518,7 @@ std::vector CreateClassDialog::getMinorSkills() const void CreateClassDialog::setNextButtonShow(bool shown) { - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); if (shown) @@ -544,7 +544,7 @@ void CreateClassDialog::onDialogCancel() mDescDialog = 0; } -void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) +void CreateClassDialog::onSpecializationClicked(MyGUI::Widget* _sender) { delete mSpecDialog; mSpecDialog = new SelectSpecializationDialog(mWindowManager); @@ -694,7 +694,7 @@ SelectSpecializationDialog::SelectSpecializationDialog(MWBase::WindowManager& pa ToolTips::createSpecializationToolTip(mSpecialization1, magic, ESM::Class::Magic); ToolTips::createSpecializationToolTip(mSpecialization2, stealth, ESM::Class::Stealth); - MyGUI::ButtonPtr cancelButton; + MyGUI::Button* cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); @@ -706,7 +706,7 @@ SelectSpecializationDialog::~SelectSpecializationDialog() // widget controls -void SelectSpecializationDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) +void SelectSpecializationDialog::onSpecializationClicked(MyGUI::Widget* _sender) { if (_sender == mSpecialization0) mSpecializationId = ESM::Class::Combat; @@ -747,7 +747,7 @@ SelectAttributeDialog::SelectAttributeDialog(MWBase::WindowManager& parWindowMan ToolTips::createAttributeToolTip(attribute, attribute->getAttributeId()); } - MyGUI::ButtonPtr cancelButton; + MyGUI::Button* cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); @@ -840,7 +840,7 @@ SelectSkillDialog::SelectSkillDialog(MWBase::WindowManager& parWindowManager) } } - MyGUI::ButtonPtr cancelButton; + MyGUI::Button* cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); @@ -873,7 +873,7 @@ DescriptionDialog::DescriptionDialog(MWBase::WindowManager& parWindowManager) getWidget(mTextEdit, "TextEdit"); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked); okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", "")); diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 2662d94cc..8c60331d8 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_CLASS_H #define MWGUI_CLASS_H -#include + #include "widgets.hpp" #include "window_base.hpp" @@ -35,17 +35,17 @@ namespace MWGui EventHandle_Int eventButtonSelected; protected: - void onButtonClicked(MyGUI::WidgetPtr _sender); + void onButtonClicked(MyGUI::Widget* _sender); private: void fitToText(MyGUI::TextBox* widget); - void layoutVertically(MyGUI::WidgetPtr widget, int margin); + void layoutVertically(MyGUI::Widget* widget, int margin); int mCurrentButton; - MyGUI::WidgetPtr mTextBox; + MyGUI::Widget* mTextBox; MyGUI::TextBox* mText; - MyGUI::WidgetPtr mButtonBar; - std::vector mButtons; + MyGUI::Widget* mButtonBar; + std::vector mButtons; }; // Lets the player choose between 3 ways of creating a class @@ -235,7 +235,7 @@ namespace MWGui void onOkClicked(MyGUI::Widget* _sender); private: - MyGUI::EditPtr mTextEdit; + MyGUI::EditBox* mTextEdit; }; class CreateClassDialog : public WindowModal @@ -265,7 +265,7 @@ namespace MWGui void onOkClicked(MyGUI::Widget* _sender); void onBackClicked(MyGUI::Widget* _sender); - void onSpecializationClicked(MyGUI::WidgetPtr _sender); + void onSpecializationClicked(MyGUI::Widget* _sender); void onSpecializationSelected(); void onAttributeClicked(Widgets::MWAttributePtr _sender); void onAttributeSelected(); @@ -280,7 +280,7 @@ namespace MWGui void update(); private: - MyGUI::EditPtr mEditName; + MyGUI::EditBox* mEditName; MyGUI::TextBox* mSpecializationName; Widgets::MWAttributePtr mFavoriteAttribute0, mFavoriteAttribute1; Widgets::MWSkillPtr mMajorSkill[5]; diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index b2281d87e..1aebe57da 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -216,7 +216,7 @@ namespace MWGui } } - void Console::keyPress(MyGUI::WidgetPtr _sender, + void Console::keyPress(MyGUI::Widget* _sender, MyGUI::KeyCode key, MyGUI::Char _char) { @@ -266,7 +266,7 @@ namespace MWGui } } - void Console::acceptCommand(MyGUI::EditPtr _sender) + void Console::acceptCommand(MyGUI::EditBox* _sender) { const std::string &cm = command->getCaption(); if(cm.empty()) return; diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 1893b0148..b1d961ed2 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -55,8 +55,8 @@ namespace MWGui public: - MyGUI::EditPtr command; - MyGUI::EditPtr history; + MyGUI::EditBox* command; + MyGUI::EditBox* history; typedef std::list StringList; @@ -95,11 +95,11 @@ namespace MWGui private: - void keyPress(MyGUI::WidgetPtr _sender, + void keyPress(MyGUI::Widget* _sender, MyGUI::KeyCode key, MyGUI::Char _char); - void acceptCommand(MyGUI::EditPtr _sender); + void acceptCommand(MyGUI::EditBox* _sender); std::string complete( std::string input, std::vector &matches ); }; diff --git a/apps/openmw/mwgui/cursor.cpp b/apps/openmw/mwgui/cursor.cpp index 15f61d5b6..399695ae3 100644 --- a/apps/openmw/mwgui/cursor.cpp +++ b/apps/openmw/mwgui/cursor.cpp @@ -14,7 +14,7 @@ namespace MWGui ResourceImageSetPointerFix::ResourceImageSetPointerFix() : - mImageSet(nullptr) + mImageSet(NULL) { } @@ -50,7 +50,7 @@ namespace MWGui void ResourceImageSetPointerFix::setImage(MyGUI::ImageBox* _image) { - if (mImageSet != nullptr) + if (mImageSet != NULL) _image->setItemResourceInfo(mImageSet->getIndexInfo(0, 0)); } diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index c7918ceb7..859e3008c 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -151,7 +151,7 @@ DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager) getWidget(mTopicsList, "TopicsList"); mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic); - MyGUI::ButtonPtr byeButton; + MyGUI::Button* byeButton; getWidget(byeButton, "ByeButton"); byeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked); @@ -164,7 +164,7 @@ DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager) void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender) { MyGUI::ISubWidgetText* t = mHistory->getClient()->getSubWidgetText(); - if(t == nullptr) + if(t == NULL) return; const MyGUI::IntPoint& lastPressed = MyGUI::InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); @@ -381,7 +381,7 @@ std::string DialogueWindow::parseText(const std::string& text) std::vector hypertext = MWDialogue::ParseHyperText(text); size_t historySize = 0; - if(mHistory->getClient()->getSubWidgetText() != nullptr) + if(mHistory->getClient()->getSubWidgetText() != NULL) { historySize = mHistory->getOnlyText().size(); } diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 5c11c311a..e39cecc3c 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -113,7 +113,7 @@ namespace MWGui DialogueHistory* mHistory; Widgets::MWList* mTopicsList; MyGUI::ProgressPtr mDispositionBar; - MyGUI::EditPtr mDispositionText; + MyGUI::EditBox* mDispositionText; PersuasionDialog mPersuasionDialog; diff --git a/apps/openmw/mwgui/exposedwindow.cpp b/apps/openmw/mwgui/exposedwindow.cpp index fa37568d7..150a8c893 100644 --- a/apps/openmw/mwgui/exposedwindow.cpp +++ b/apps/openmw/mwgui/exposedwindow.cpp @@ -1,7 +1,5 @@ #include "exposedwindow.hpp" -#include "MyGUI_Window.h" - namespace MWGui { MyGUI::VectorWidgetPtr ExposedWindow::getSkinWidgetsByName (const std::string &name) @@ -16,7 +14,7 @@ namespace MWGui if (widgets.empty()) { MYGUI_ASSERT( ! _throw, "widget name '" << _name << "' not found in skin of layout '" << getName() << "'"); - return nullptr; + return NULL; } else { diff --git a/apps/openmw/mwgui/exposedwindow.hpp b/apps/openmw/mwgui/exposedwindow.hpp index 906d0b406..7df2fcb35 100644 --- a/apps/openmw/mwgui/exposedwindow.hpp +++ b/apps/openmw/mwgui/exposedwindow.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_EXPOSEDWINDOW_H #define MWGUI_EXPOSEDWINDOW_H -#include "MyGUI_Window.h" +#include namespace MWGui { diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index a2c3a318b..7cb0f3924 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -2,7 +2,9 @@ #include -#include +#include +#include +#include #include diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 013ad59f0..51dcffb09 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -60,7 +60,7 @@ namespace MWGui MyGUI::Widget* mDummy; - MyGUI::WidgetPtr mFpsBox; + MyGUI::Widget* mFpsBox; MyGUI::TextBox* mFpsCounter; MyGUI::TextBox* mTriangleCounter; MyGUI::TextBox* mBatchCounter; diff --git a/apps/openmw/mwgui/imagebutton.hpp b/apps/openmw/mwgui/imagebutton.hpp index 9fce12da1..f531e2246 100644 --- a/apps/openmw/mwgui/imagebutton.hpp +++ b/apps/openmw/mwgui/imagebutton.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_IMAGEBUTTON_H #define MWGUI_IMAGEBUTTON_H -#include "MyGUI_ImageBox.h" +#include namespace MWGui { diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 044a2b2a4..cd1ff7ebb 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -29,8 +29,8 @@ namespace MWGui void notifyNextPage(MyGUI::Widget* _sender); void notifyPrevPage(MyGUI::Widget* _sender); - MyGUI::EditPtr mLeftTextWidget; - MyGUI::EditPtr mRightTextWidget; + MyGUI::EditBox* mLeftTextWidget; + MyGUI::EditBox* mRightTextWidget; MWGui::ImageButton* mPrevBtn; MWGui::ImageButton* mNextBtn; std::vector mLeftPages; diff --git a/apps/openmw/mwgui/list.cpp b/apps/openmw/mwgui/list.cpp index 0bafced97..d60e9b687 100644 --- a/apps/openmw/mwgui/list.cpp +++ b/apps/openmw/mwgui/list.cpp @@ -1,6 +1,9 @@ #include "list.hpp" -#include +#include +#include +#include +#include using namespace MWGui; using namespace MWGui::Widgets; diff --git a/apps/openmw/mwgui/list.hpp b/apps/openmw/mwgui/list.hpp index d07d49de6..38797e779 100644 --- a/apps/openmw/mwgui/list.hpp +++ b/apps/openmw/mwgui/list.hpp @@ -1,7 +1,12 @@ #ifndef MWGUI_LIST_HPP #define MWGUI_LIST_HPP -#include +#include + +namespace MyGUI +{ + class ScrollView; +} namespace MWGui { diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 0ee042e32..b8a34c457 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -247,7 +247,7 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan std::vector::const_iterator it; for(it = buttons.begin(); it != buttons.end(); ++it) { - MyGUI::ButtonPtr button = mButtonsWidget->createWidget( + MyGUI::Button* button = mButtonsWidget->createWidget( MyGUI::WidgetStyle::Child, std::string("MW_Button"), dummyCoord, @@ -301,7 +301,7 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan MyGUI::IntSize buttonSize(0, buttonHeight); int left = (mainWidgetSize.width - buttonsWidth)/2 + buttonPadding; - std::vector::const_iterator button; + std::vector::const_iterator button; for(button = mButtons.begin(); button != mButtons.end(); ++button) { buttonCord.left = left; @@ -349,7 +349,7 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan int top = textButtonPadding + buttonTopPadding + textSize.height; - std::vector::const_iterator button; + std::vector::const_iterator button; for(button = mButtons.begin(); button != mButtons.end(); ++button) { buttonSize.width = (*button)->getTextSize().width + buttonPadding*2; @@ -371,7 +371,7 @@ void InteractiveMessageBox::enterPressed() { std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}")); - std::vector::const_iterator button; + std::vector::const_iterator button; for(button = mButtons.begin(); button != mButtons.end(); ++button) { if(Misc::StringUtils::lowerCase((*button)->getCaption()) == ok) @@ -393,7 +393,7 @@ void InteractiveMessageBox::buttonActivated (MyGUI::Widget* pressed) { mMarkedToDelete = true; int index = 0; - std::vector::const_iterator button; + std::vector::const_iterator button; for(button = mButtons.begin(); button != mButtons.end(); ++button) { if(*button == pressed) diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 4be8bc5b7..149aa7e7f 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -2,7 +2,6 @@ #define MWGUI_MESSAGE_BOX_H #include -#include #include "window_base.hpp" @@ -10,6 +9,13 @@ #undef MessageBox +namespace MyGUI +{ + class Widget; + class Button; + class EditBox; +} + namespace MWGui { class InteractiveMessageBox; @@ -61,7 +67,7 @@ namespace MWGui MessageBoxManager& mMessageBoxManager; int mHeight; const std::string& mMessage; - MyGUI::EditPtr mMessageWidget; + MyGUI::EditBox* mMessageWidget; int mFixedWidth; int mBottomPadding; int mNextBoxPadding; @@ -81,9 +87,9 @@ namespace MWGui void buttonActivated (MyGUI::Widget* _widget); MessageBoxManager& mMessageBoxManager; - MyGUI::EditPtr mMessageWidget; - MyGUI::WidgetPtr mButtonsWidget; - std::vector mButtons; + MyGUI::EditBox* mMessageWidget; + MyGUI::Widget* mButtonsWidget; + std::vector mButtons; int mTextButtonPadding; int mButtonPressed; diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 71a4d1b3e..1436995c5 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -41,7 +41,7 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) mHeadRotate->eventScrollChangePosition += MyGUI::newDelegate(this, &RaceDialog::onHeadRotate); // Set up next/previous buttons - MyGUI::ButtonPtr prevButton, nextButton; + MyGUI::Button *prevButton, *nextButton; setText("GenderChoiceT", mWindowManager.getGameSettingString("sRaceMenu2", "Change Sex")); getWidget(prevButton, "PrevGenderButton"); @@ -73,11 +73,11 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) setText("SpellPowerT", mWindowManager.getGameSettingString("sRaceMenu7", "Specials")); getWidget(mSpellPowerList, "SpellPowerList"); - MyGUI::ButtonPtr backButton; + MyGUI::Button* backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked); @@ -89,7 +89,7 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) void RaceDialog::setNextButtonShow(bool shown) { - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); if (shown) @@ -134,7 +134,7 @@ void RaceDialog::setRaceId(const std::string &raceId) if (boost::iequals(*mRaceList->getItemDataAt(i), raceId)) { mRaceList->setIndexSelected(i); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); break; } @@ -256,7 +256,7 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) if (_index == MyGUI::ITEM_NONE) return; - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); const std::string *raceId = mRaceList->getItemDataAt(_index); if (boost::iequals(mCurrentRaceId, *raceId)) @@ -331,7 +331,7 @@ void RaceDialog::updateRaces() void RaceDialog::updateSkills() { - for (std::vector::iterator it = mSkillItems.begin(); it != mSkillItems.end(); ++it) + for (std::vector::iterator it = mSkillItems.begin(); it != mSkillItems.end(); ++it) { MyGUI::Gui::getInstance().destroyWidget(*it); } @@ -369,7 +369,7 @@ void RaceDialog::updateSkills() void RaceDialog::updateSpellPowers() { - for (std::vector::iterator it = mSpellPowerItems.begin(); it != mSpellPowerItems.end(); ++it) + for (std::vector::iterator it = mSpellPowerItems.begin(); it != mSpellPowerItems.end(); ++it) { MyGUI::Gui::getInstance().destroyWidget(*it); } diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index 619556906..efd08f439 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -85,11 +85,11 @@ namespace MWGui MyGUI::ListBox* mRaceList; MyGUI::ScrollBar* mHeadRotate; - MyGUI::WidgetPtr mSkillList; - std::vector mSkillItems; + MyGUI::Widget* mSkillList; + std::vector mSkillItems; - MyGUI::WidgetPtr mSpellPowerList; - std::vector mSpellPowerItems; + MyGUI::Widget* mSpellPowerList; + std::vector mSpellPowerItems; int mGenderIndex, mFaceIndex, mHairIndex; int mFaceCount, mHairCount; diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 50dc26e42..50508cc5f 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -86,11 +86,11 @@ ReviewDialog::ReviewDialog(MWBase::WindowManager& parWindowManager) mSkillWidgetMap.insert(std::make_pair(i, static_cast (0))); } - MyGUI::ButtonPtr backButton; + MyGUI::Button* backButton; getWidget(backButton, "BackButton"); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBackClicked); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onOkClicked); } @@ -309,7 +309,7 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId void ReviewDialog::updateSkillArea() { - for (std::vector::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it) + for (std::vector::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it) { MyGUI::Gui::getInstance().destroyWidget(*it); } diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index aac609a64..4f41ec42d 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -91,7 +91,7 @@ namespace MWGui std::map mSkillWidgetMap; std::string mName, mRaceId, mBirthSignId; ESM::Class mKlass; - std::vector mSkillWidgets; //< Skills and other information + std::vector mSkillWidgets; //< Skills and other information }; } #endif diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 70ceed857..0fa4127b5 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -67,7 +67,7 @@ StatsWindow::StatsWindow (MWBase::WindowManager& parWindowManager) for (int i = 0; i < ESM::Skill::Length; ++i) { mSkillValues.insert(std::pair >(i, MWMechanics::Stat())); - mSkillWidgetMap.insert(std::pair(i, (MyGUI::TextBox*)nullptr)); + mSkillWidgetMap.insert(std::pair(i, (MyGUI::TextBox*)NULL)); } MyGUI::WindowPtr t = static_cast(mMainWidget); @@ -419,7 +419,7 @@ void StatsWindow::updateSkillArea() { mChanged = false; - for (std::vector::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it) + for (std::vector::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it) { MyGUI::Gui::getInstance().destroyWidget(*it); } diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index 6619680fa..3befc1f00 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -67,11 +67,11 @@ namespace MWGui SkillList mMajorSkills, mMinorSkills, mMiscSkills; std::map > mSkillValues; std::map mSkillWidgetMap; - std::map mFactionWidgetMap; + std::map mFactionWidgetMap; FactionList mFactions; ///< Stores a list of factions and the current rank std::string mBirthSignId; int mReputation, mBounty; - std::vector mSkillWidgets; //< Skills and other information + std::vector mSkillWidgets; //< Skills and other information std::set mExpelled; bool mChanged; diff --git a/apps/openmw/mwgui/text_input.cpp b/apps/openmw/mwgui/text_input.cpp index c19394833..9265cadf9 100644 --- a/apps/openmw/mwgui/text_input.cpp +++ b/apps/openmw/mwgui/text_input.cpp @@ -13,7 +13,7 @@ TextInputDialog::TextInputDialog(MWBase::WindowManager& parWindowManager) getWidget(mTextEdit, "TextEdit"); mTextEdit->eventEditSelectAccept += newDelegate(this, &TextInputDialog::onTextAccepted); - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked); @@ -23,7 +23,7 @@ TextInputDialog::TextInputDialog(MWBase::WindowManager& parWindowManager) void TextInputDialog::setNextButtonShow(bool shown) { - MyGUI::ButtonPtr okButton; + MyGUI::Button* okButton; getWidget(okButton, "OKButton"); if (shown) diff --git a/apps/openmw/mwgui/text_input.hpp b/apps/openmw/mwgui/text_input.hpp index 649990281..29de7388b 100644 --- a/apps/openmw/mwgui/text_input.hpp +++ b/apps/openmw/mwgui/text_input.hpp @@ -30,7 +30,7 @@ namespace MWGui void onTextAccepted(MyGUI::Edit* _sender); private: - MyGUI::EditPtr mTextEdit; + MyGUI::EditBox* mTextEdit; }; } #endif diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index c7acf568d..261a7f8bd 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -439,7 +439,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) effectsWidget->setWindowManager(mWindowManager); effectsWidget->setEffectList(info.effects); - std::vector effectItems; + std::vector effectItems; effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, info.isPotion ? Widgets::MWEffectList::EF_NoTarget : 0); totalSize.height += coord.top-6; totalSize.width = std::max(totalSize.width, coord.width); @@ -459,7 +459,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) enchantWidget->setWindowManager(mWindowManager); enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->mEffects)); - std::vector enchantEffectItems; + std::vector enchantEffectItems; int flag = (enchant->mData.mType == ESM::Enchantment::ConstantEffect) ? Widgets::MWEffectList::EF_Constant : 0; enchantWidget->createEffectWidgets(enchantEffectItems, enchantArea, coord, true, flag); totalSize.height += coord.top-6; diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index f932c1f03..8857ecfa3 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -2,6 +2,9 @@ #include +#include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" @@ -31,10 +34,10 @@ void MWGui::Widgets::fixTexturePath(std::string &path) /* MWSkill */ MWSkill::MWSkill() - : mManager(nullptr) + : mManager(NULL) , mSkillId(ESM::Skill::Length) - , mSkillNameWidget(nullptr) - , mSkillValueWidget(nullptr) + , mSkillNameWidget(NULL) + , mSkillValueWidget(NULL) { } @@ -103,7 +106,7 @@ void MWSkill::initialiseOverride() assignWidget(mSkillNameWidget, "StatName"); assignWidget(mSkillValueWidget, "StatValue"); - MyGUI::ButtonPtr button; + MyGUI::Button* button; assignWidget(button, "StatNameButton"); if (button) { @@ -123,10 +126,10 @@ void MWSkill::initialiseOverride() /* MWAttribute */ MWAttribute::MWAttribute() - : mManager(nullptr) + : mManager(NULL) , mId(-1) - , mAttributeNameWidget(nullptr) - , mAttributeValueWidget(nullptr) + , mAttributeNameWidget(NULL) + , mAttributeValueWidget(NULL) { } @@ -195,7 +198,7 @@ void MWAttribute::initialiseOverride() assignWidget(mAttributeNameWidget, "StatName"); assignWidget(mAttributeValueWidget, "StatValue"); - MyGUI::ButtonPtr button; + MyGUI::Button* button; assignWidget(button, "StatNameButton"); if (button) { @@ -215,8 +218,8 @@ void MWAttribute::initialiseOverride() /* MWSpell */ MWSpell::MWSpell() - : mWindowManager(nullptr) - , mSpellNameWidget(nullptr) + : mWindowManager(NULL) + , mSpellNameWidget(NULL) { } @@ -226,7 +229,7 @@ void MWSpell::setSpellId(const std::string &spellId) updateWidgets(); } -void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, int flags) +void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::Widget* creator, MyGUI::IntCoord &coord, int flags) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -234,7 +237,7 @@ void MWSpell::createEffectWidgets(std::vector &effects, MyGUI: const ESM::Spell *spell = store.get().search(mId); MYGUI_ASSERT(spell, "spell with id '" << mId << "' not found"); - MWSpellEffectPtr effect = nullptr; + MWSpellEffectPtr effect = NULL; std::vector::const_iterator end = spell->mEffects.mList.end(); for (std::vector::const_iterator it = spell->mEffects.mList.begin(); it != end; ++it) { @@ -286,7 +289,7 @@ MWSpell::~MWSpell() /* MWEffectList */ MWEffectList::MWEffectList() - : mWindowManager(nullptr) + : mWindowManager(NULL) , mEffectList(0) { } @@ -297,11 +300,11 @@ void MWEffectList::setEffectList(const SpellEffectList& list) updateWidgets(); } -void MWEffectList::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags) +void MWEffectList::createEffectWidgets(std::vector &effects, MyGUI::Widget* creator, MyGUI::IntCoord &coord, bool center, int flags) { // We don't know the width of all the elements beforehand, so we do it in // 2 steps: first, create all widgets and check their width.... - MWSpellEffectPtr effect = nullptr; + MWSpellEffectPtr effect = NULL; int maxwidth = coord.width; for (SpellEffectList::iterator it=mEffectList.begin(); @@ -320,7 +323,7 @@ void MWEffectList::createEffectWidgets(std::vector &effects, M } // ... then adjust the size for all widgets - for (std::vector::iterator it = effects.begin(); it != effects.end(); ++it) + for (std::vector::iterator it = effects.begin(); it != effects.end(); ++it) { effect = static_cast(*it); bool needcenter = center && (maxwidth > effect->getRequestedWidth()); @@ -375,9 +378,9 @@ SpellEffectList MWEffectList::effectListFromESM(const ESM::EffectList* effects) /* MWSpellEffect */ MWSpellEffect::MWSpellEffect() - : mWindowManager(nullptr) - , mImageWidget(nullptr) - , mTextWidget(nullptr) + : mWindowManager(NULL) + , mImageWidget(NULL) + , mTextWidget(NULL) , mRequestedWidth(0) { } @@ -495,9 +498,9 @@ void MWSpellEffect::initialiseOverride() MWDynamicStat::MWDynamicStat() : mValue(0) , mMax(1) -, mTextWidget(nullptr) -, mBarWidget(nullptr) -, mBarTextWidget(nullptr) +, mTextWidget(NULL) +, mBarWidget(NULL) +, mBarTextWidget(NULL) { } diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 7cbb5e53a..597bcbe32 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -2,11 +2,17 @@ #define MWGUI_WIDGETS_H #include "../mwworld/esmstore.hpp" - -#include - #include "../mwmechanics/stat.hpp" +#include +#include +#include + +namespace MyGUI +{ + class ImageBox; +} + namespace MWBase { class WindowManager; @@ -118,7 +124,8 @@ namespace MWGui MWBase::WindowManager *mManager; ESM::Skill::SkillEnum mSkillId; SkillValue mValue; - MyGUI::WidgetPtr mSkillNameWidget, mSkillValueWidget; + MyGUI::Widget* mSkillNameWidget; + MyGUI::Widget* mSkillValueWidget; }; typedef MWSkill* MWSkillPtr; @@ -160,7 +167,8 @@ namespace MWGui MWBase::WindowManager *mManager; int mId; AttributeValue mValue; - MyGUI::WidgetPtr mAttributeNameWidget, mAttributeValueWidget; + MyGUI::Widget* mAttributeNameWidget; + MyGUI::Widget* mAttributeValueWidget; }; typedef MWAttribute* MWAttributePtr; @@ -186,7 +194,7 @@ namespace MWGui * @param spell category, if this is 0, this means the spell effects are permanent and won't display e.g. duration * @param various flags, see MWEffectList::EffectFlags */ - void createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, int flags); + void createEffectWidgets(std::vector &effects, MyGUI::Widget* creator, MyGUI::IntCoord &coord, int flags); const std::string &getSpellId() const { return mId; } @@ -230,7 +238,7 @@ namespace MWGui * @param center the effect widgets horizontally * @param various flags, see MWEffectList::EffectFlags */ - void createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags); + void createEffectWidgets(std::vector &effects, MyGUI::Widget* creator, MyGUI::IntCoord &coord, bool center, int flags); protected: virtual ~MWEffectList(); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 1138f62fa..7d5b6af6e 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -3,7 +3,7 @@ #include #include -#include "MyGUI_UString.h" +#include #include #include diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index e5a164b81..07fbafa7d 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -1,9 +1,10 @@ -#include -#include -#include - #include "manager.hpp" +#include +#include + +#include + using namespace OEngine::GUI; /* diff --git a/libs/openengine/gui/manager.hpp b/libs/openengine/gui/manager.hpp index c0f98da88..9443fba01 100644 --- a/libs/openengine/gui/manager.hpp +++ b/libs/openengine/gui/manager.hpp @@ -1,6 +1,8 @@ #ifndef OENGINE_MYGUI_MANAGER_H #define OENGINE_MYGUI_MANAGER_H +#include + namespace MyGUI { class Gui; From e1882dce32c96ff773a1dbc5b92f7eef1cb71cde Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 3 Mar 2013 13:02:41 +0000 Subject: [PATCH 095/151] correcting a bug: player orientation wasn't stored correctly, and objects orientation wasn't properly retrived. --- apps/openmw/mwrender/renderingmanager.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index fe3dc776d..b214fd800 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -273,16 +273,21 @@ bool RenderingManager::rotateObject( const MWWorld::Ptr &ptr, Ogre::Vector3 &rot Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X); Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y); Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z); - Ogre::Quaternion newo = adjust ? (xr * yr * zr) * ptr.getRefData().getBaseNode()->getOrientation() : xr * yr * zr; - rot.x = newo.x; - rot.y = newo.y; - rot.z = newo.z; + + Ogre::Quaternion xref(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::UNIT_X); + Ogre::Quaternion yref(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::UNIT_Y); + Ogre::Quaternion zref(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); + + Ogre::Quaternion newo = adjust ? (xr * yr * zr) * (xref*yref*zref) : xr * yr * zr; + rot.x = newo.getPitch().valueRadians();// newo.x;Ogre::Quaternion:: + rot.y = newo.getYaw().valueRadians();//newo.y; + rot.z = newo.getRoll().valueRadians(); //newo.z; ptr.getRefData().getBaseNode()->setOrientation(newo); } else if(isPlayer) { rot.x = mPlayer->getPitch(); - rot.z = mPlayer->getYaw(); + rot.z = -mPlayer->getYaw(); } else if (adjust) { From 7fb2ff18a39d5347811ae6ca0cd7eca635688f58 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 3 Mar 2013 13:06:45 +0000 Subject: [PATCH 096/151] Fix bug induced by previous commit (player orientation wasn't stored correctly), and fix NPC not beeing able to move with certain angles (like angle Z 70) because the trace function was hitting NPC own hitboxes. The solution prposed here is a little hacky, but i works. Need a little clean up(mBody shouldn't be public) --- apps/openmw/mwworld/physicssystem.cpp | 15 ++++++++------- libs/openengine/bullet/physic.hpp | 3 ++- libs/openengine/bullet/trace.cpp | 11 ++++++++++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 65cbc1164..90c090f59 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -99,7 +99,7 @@ namespace MWWorld if(!physicActor || !physicActor->getCollisionMode()) { // FIXME: This works, but it's inconcsistent with how the rotations are applied elsewhere. Why? - return position + (Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)* + return position + (Ogre::Quaternion(Ogre::Radian( refpos.rot[2]), Ogre::Vector3::UNIT_Z)* Ogre::Quaternion(Ogre::Radian( refpos.rot[1]), Ogre::Vector3::UNIT_Y)* Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * movement; @@ -109,12 +109,13 @@ namespace MWWorld bool onground = false; float remainingTime = time; bool isInterior = !ptr.getCell()->isExterior(); - Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); + Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1); + physicActor->mBody->translate(btVector3(0,0,1000)); Ogre::Vector3 velocity; if(!gravity) { - velocity = (Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)* + velocity = (Ogre::Quaternion(Ogre::Radian( refpos.rot[2]), Ogre::Vector3::UNIT_Z)* Ogre::Quaternion(Ogre::Radian( refpos.rot[1]), Ogre::Vector3::UNIT_Y)* Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * movement / time; @@ -127,9 +128,7 @@ namespace MWWorld if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope) onground = true; } - - velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z) * - movement / time; + velocity = Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::UNIT_Z)*movement / time; velocity.z += physicActor->getVerticalForce(); } @@ -148,6 +147,7 @@ namespace MWWorld // trace to where character would go if there were no obstructions newtrace(&trace, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, isInterior, engine); newPosition = trace.endpos; + //std::cout << newPosition.x << " "; remainingTime = remainingTime * (1.0f-trace.fraction); // check for obstructions @@ -191,7 +191,8 @@ namespace MWWorld } physicActor->setOnGround(onground); physicActor->setVerticalForce(!onground ? clippedVelocity.z - time*627.2f : 0.0f); - + physicActor->mBody->translate(btVector3(0,0,-1000)); + //std::cout << position.x << " " << newPosition.x << " " << position.y << " " << newPosition.y << std::endl; return newPosition; } }; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index bd5d3d50a..6a7150fca 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -129,9 +129,10 @@ namespace Physic void operator delete (void * Data) { _aligned_free (Data); } #endif + OEngine::Physic::RigidBody* mBody; + private: - OEngine::Physic::RigidBody* mBody; Ogre::Vector3 mBoxScaledTranslation; btQuaternion mBoxRotationInverse; Ogre::Quaternion mBoxRotation; diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index 7664eb418..3abe13da4 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -8,6 +8,7 @@ #include "physic.hpp" +#define BIT(x) (1<<(x)) enum traceWorldType { @@ -24,6 +25,14 @@ enum collaborativePhysicsType Both_Physics = 3 // This object has both kinds of physics (example: activators) }; +enum collisiontypes { + COL_NOTHING = 0, //dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback); From ac0a23a68d644610789f00ad1912f5443aa88937 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 14:53:47 +0100 Subject: [PATCH 097/151] Fix initialization problem --- files/materials/objects.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 88ca2d152..6495b0cb4 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -146,7 +146,7 @@ #if VERTEX_LIGHTING float3 lightDir; float d; - + lightResult = float3(0,0,0); @shForeach(@shGlobalSettingString(num_lights)) lightDir = lightPosition[@shIterator].xyz - (shInputPosition.xyz * lightPosition[@shIterator].w); d = length(lightDir); From 5951abfae2ec518e03bb343d8958b7b72c68cfe6 Mon Sep 17 00:00:00 2001 From: gus Date: Sun, 3 Mar 2013 13:59:38 +0000 Subject: [PATCH 098/151] fix some script instructions --- apps/openmw/mwscript/transformationextensions.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 2dd8f3e16..8222ef150 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -148,15 +148,15 @@ namespace MWScript if (axis=="x") { - runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[0]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees()); } else if (axis=="y") { - runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[1]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees()); } else if (axis=="z") { - runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[2]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees()); } else throw std::runtime_error ("invalid ration axis: " + axis); @@ -241,15 +241,15 @@ namespace MWScript if(axis == "x") { - runtime.push(ptr.getCellRef().mPos.pos[0]); + runtime.push(ptr.getRefData().getPosition().pos[0]); } else if(axis == "y") { - runtime.push(ptr.getCellRef().mPos.pos[1]); + runtime.push(ptr.getRefData().getPosition().pos[1]); } else if(axis == "z") { - runtime.push(ptr.getCellRef().mPos.pos[2]); + runtime.push(ptr.getRefData().getPosition().pos[2]); } else throw std::runtime_error ("invalid axis: " + axis); From 11f21a19886fdb010fe6f67c1c42ececb95ee4b6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 15:10:40 +0100 Subject: [PATCH 099/151] Weather update should be before renderer update --- apps/openmw/mwworld/worldimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f8efcdbd4..cddcda68b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -974,6 +974,8 @@ namespace MWWorld void World::update (float duration, bool paused) { + mWeatherManager->update (duration); + mWorldScene->update (duration, paused); float pitch, yaw; @@ -981,8 +983,6 @@ namespace MWWorld mRendering->getPlayerData(eyepos, pitch, yaw); mPhysics->updatePlayerData(eyepos, pitch, yaw); - mWeatherManager->update (duration); - performUpdateSceneQueries (); updateWindowManager (); From 867b22ce19cad53e4e5ba3aaf9f2826b7273fe43 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 15:11:19 +0100 Subject: [PATCH 100/151] Fix a terrain glitch --- apps/openmw/mwrender/terrain.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 212dd94c3..438366873 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -42,7 +42,8 @@ namespace MWRender // We don't want any pixel error at all. Really, LOD makes no sense here - morrowind uses 65x65 verts in one cell, // so applying LOD is most certainly slower than doing no LOD at all. - mTerrainGlobals->setMaxPixelError(0); + // Setting this to 0 seems to cause glitches though. :/ + mTerrainGlobals->setMaxPixelError(1); mTerrainGlobals->setLayerBlendMapSize(32); From 002830e13bc8ce0f9a882b9b225959f3cbfb2120 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 15:11:45 +0100 Subject: [PATCH 101/151] Make sure render textures are inactive when in a cell without water --- apps/openmw/mwrender/refraction.cpp | 5 +++++ apps/openmw/mwrender/refraction.hpp | 1 + apps/openmw/mwrender/water.cpp | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index 15575362b..bb2d88865 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -99,4 +99,9 @@ namespace MWRender } } + void Refraction::setActive(bool active) + { + mRenderTarget->setActive(active); + } + } diff --git a/apps/openmw/mwrender/refraction.hpp b/apps/openmw/mwrender/refraction.hpp index de47d6e43..b9ab8deac 100644 --- a/apps/openmw/mwrender/refraction.hpp +++ b/apps/openmw/mwrender/refraction.hpp @@ -25,6 +25,7 @@ namespace MWRender void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); void setUnderwater(bool underwater) {mIsUnderwater = underwater;} + void setActive (bool active); void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index d112e17b2..c116a6384 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -372,9 +372,9 @@ void Water::updateVisible() { mWater->setVisible(mToggled && mActive); if (mReflection) - { mReflection->setActive(mToggled && mActive); - } + if (mRefraction) + mRefraction->setActive(mToggled && mActive); } void Water::update(float dt, Ogre::Vector3 player) @@ -424,6 +424,8 @@ void Water::applyRTT() mRefraction = new Refraction(mCamera); mRefraction->setHeight(mTop); } + + updateVisible(); } void Water::applyVisibilityMask() From f0e3463e9bb636e303b5d77834848f058e8b715a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 16:50:10 +0100 Subject: [PATCH 102/151] Disable assertion for comparing iterators from different containers (Bug #605) --- apps/openmw/mwworld/containerstore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index eb2a14d5b..8a7884e9e 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -548,7 +548,8 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStoreIterator::operator++ (int bool MWWorld::ContainerStoreIterator::isEqual (const ContainerStoreIterator& iter) const { - assert (mContainer==iter.mContainer); + if (mContainer!=iter.mContainer) + return false; if (mType!=iter.mType) return false; From c9fefc7f5d245541c5d24def1e26ac7bb3cd8776 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 19:28:11 +0100 Subject: [PATCH 103/151] Simpler, more lightweight underwater effect, changed colors to match vanilla better --- apps/openmw/mwgui/settingswindow.cpp | 13 ----- apps/openmw/mwgui/settingswindow.hpp | 1 - apps/openmw/mwrender/renderconst.hpp | 3 ++ apps/openmw/mwrender/renderingmanager.cpp | 40 ++++++--------- apps/openmw/mwrender/renderingmanager.hpp | 2 +- apps/openmw/mwrender/videoplayer.cpp | 6 ++- apps/openmw/mwrender/water.cpp | 24 --------- apps/openmw/mwrender/water.hpp | 3 +- files/CMakeLists.txt | 1 - files/materials/objects.shader | 58 ++++------------------ files/materials/openmw.configuration | 1 + files/materials/terrain.shader | 55 ++------------------ files/materials/underwater.h | 4 +- files/materials/water.mat | 8 --- files/materials/water.shader | 30 ++--------- files/mygui/openmw_settings_window.layout | 7 --- files/settings-default.cfg | 2 - files/water/underwater_dome.mesh | Bin 22585 -> 0 bytes 18 files changed, 46 insertions(+), 212 deletions(-) delete mode 100644 files/water/underwater_dome.mesh diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index ebeb42ab2..04856c3ed 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -129,7 +129,6 @@ namespace MWGui getWidget(mStaticsShadows, "StaticsShadows"); getWidget(mMiscShadows, "MiscShadows"); getWidget(mShadowsDebug, "ShadowsDebug"); - getWidget(mUnderwaterButton, "UnderwaterButton"); getWidget(mControlsBox, "ControlsBox"); getWidget(mResetControlsButton, "ResetControlsButton"); getWidget(mInvertYButton, "InvertYButton"); @@ -141,7 +140,6 @@ namespace MWGui mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mInvertYButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); - mUnderwaterButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled); mShaderModeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShaderModeToggled); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -236,7 +234,6 @@ namespace MWGui mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect statics", "Water") ? "#{sOn}" : "#{sOff}"); mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}"); mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}"); - mUnderwaterButton->setCaptionWithReplacing(Settings::Manager::getBool("underwater effect", "Water") ? "#{sOn}" : "#{sOff}"); mShadowsTextureSize->setCaption (Settings::Manager::getString ("texture size", "Shadows")); //mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}"); @@ -267,7 +264,6 @@ namespace MWGui if (!Settings::Manager::getBool("shaders", "Objects")) { mRefractionButton->setEnabled(false); - mUnderwaterButton->setEnabled (false); mShadowsEnabledButton->setEnabled(false); } @@ -389,10 +385,6 @@ namespace MWGui Settings::Manager::setBool("shader", "Water", newState); else if (_sender == mRefractionButton) Settings::Manager::setBool("refraction", "Water", newState); - else if (_sender == mUnderwaterButton) - { - Settings::Manager::setBool("underwater effect", "Water", newState); - } else if (_sender == mReflectObjectsButton) { Settings::Manager::setBool("reflect misc", "Water", newState); @@ -459,10 +451,6 @@ namespace MWGui { Settings::Manager::setBool("shaders", "Objects", false); - mUnderwaterButton->setCaptionWithReplacing("#{sOff}"); - - mUnderwaterButton->setEnabled(false); - // refraction needs shaders to display underwater fog mRefractionButton->setCaptionWithReplacing("#{sOff}"); mRefractionButton->setEnabled(false); @@ -485,7 +473,6 @@ namespace MWGui mReflectTerrainButton->setEnabled(true); mRefractionButton->setEnabled(true); - mUnderwaterButton->setEnabled(true); mShadowsEnabledButton->setEnabled(true); } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 55cc0a870..fc1ec9e36 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -50,7 +50,6 @@ namespace MWGui MyGUI::Button* mReflectTerrainButton; MyGUI::Button* mShadersButton; MyGUI::Button* mShaderModeButton; - MyGUI::Button* mUnderwaterButton; MyGUI::Button* mRefractionButton; MyGUI::Button* mShadowsEnabledButton; diff --git a/apps/openmw/mwrender/renderconst.hpp b/apps/openmw/mwrender/renderconst.hpp index cc3cbee29..1d2cdf1ea 100644 --- a/apps/openmw/mwrender/renderconst.hpp +++ b/apps/openmw/mwrender/renderconst.hpp @@ -56,6 +56,9 @@ enum VisibilityFlags RV_Debug = 512, + // overlays, we only want these on the main render target + RV_Overlay = 1024, + RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water }; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 943208a66..c8b5926d9 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -133,8 +133,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setGlobalSetting ("lighting", "true"); sh::Factory::getInstance ().setGlobalSetting ("num_lights", Settings::Manager::getString ("num lights", "Objects")); sh::Factory::getInstance ().setGlobalSetting ("terrain_num_lights", Settings::Manager::getString ("num lights", "Terrain")); - sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water")); sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true"); + sh::Factory::getInstance ().setGlobalSetting ("render_refraction", "false"); sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty (new sh::FloatValue(0.0))); sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(0))); @@ -355,16 +355,7 @@ void RenderingManager::update (float duration, bool paused) Ogre::ControllerManager::getSingleton().setTimeFactor(paused ? 0.f : 1.f); - /* - if (world->isUnderwater (world->getPlayer().getPlayer().getCell(), cam)) - { - mFogColour = Ogre::ColourValue(0.18039, 0.23137, 0.25490); - mFogStart = 0; - mFogEnd = 1500; - } - */ - - applyFog(); + applyFog(world->isUnderwater (world->getPlayer().getPlayer().getCell(), cam)); if(paused) { @@ -529,16 +520,20 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue mRendering.getCamera()->setFarClipDistance ( Settings::Manager::getFloat("max viewing distance", "Viewing distance") / density ); } -void RenderingManager::applyFog () +void RenderingManager::applyFog (bool underwater) { - mRendering.getScene()->setFog (FOG_LINEAR, mFogColour, 0, mFogStart, mFogEnd); - - mRendering.getViewport()->setBackgroundColour (mFogColour); - - mWater->setViewportBackground (mFogColour); - - sh::Factory::getInstance ().setSharedParameter ("viewportBackground", - sh::makeProperty (new sh::Vector3(mFogColour.r, mFogColour.g, mFogColour.b))); + if (!underwater) + { + mRendering.getScene()->setFog (FOG_LINEAR, mFogColour, 0, mFogStart, mFogEnd); + mRendering.getViewport()->setBackgroundColour (mFogColour); + mWater->setViewportBackground (mFogColour); + } + else + { + mRendering.getScene()->setFog (FOG_LINEAR, Ogre::ColourValue(0.18039, 0.23137, 0.25490), 0, 0, 1000); + mRendering.getViewport()->setBackgroundColour (Ogre::ColourValue(0.18039, 0.23137, 0.25490)); + mWater->setViewportBackground (Ogre::ColourValue(0.18039, 0.23137, 0.25490)); + } } void RenderingManager::setAmbientMode() @@ -784,11 +779,6 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec sh::Factory::getInstance ().setGlobalSetting ("refraction", Settings::Manager::getBool("refraction", "Water") ? "true" : "false"); rebuild = true; } - else if (it->second == "underwater effect" && it->first == "Water") - { - sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water")); - rebuild = true; - } else if (it->second == "shaders" && it->first == "Objects") { sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 02d796fdd..49cde25a3 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -208,7 +208,7 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList sh::Factory* mFactory; void setAmbientMode(); - void applyFog(); + void applyFog(bool underwater); void setMenuTransparency(float val); diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index a0dedb6bc..2cbc85cd3 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -17,6 +17,8 @@ #include "../mwsound/sound_decoder.hpp" #include "../mwsound/sound.hpp" +#include "renderconst.hpp" + #ifdef _WIN32 #include @@ -1067,9 +1069,9 @@ VideoPlayer::VideoPlayer(Ogre::SceneManager* sceneMgr) mBackgroundNode->attachObject(mBackgroundRectangle); mRectangle->setVisible(false); - mRectangle->setVisibilityFlags(0x1); + mRectangle->setVisibilityFlags(RV_Overlay); mBackgroundRectangle->setVisible(false); - mBackgroundRectangle->setVisibilityFlags(0x1); + mBackgroundRectangle->setVisibilityFlags(RV_Overlay); } VideoPlayer::~VideoPlayer() diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index c116a6384..49836535f 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -4,14 +4,10 @@ #include #include #include -#include -#include -#include #include #include "sky.hpp" #include "renderingmanager.hpp" -#include "compositors.hpp" #include "ripplesimulation.hpp" #include "refraction.hpp" @@ -224,16 +220,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend) : mWater->setMaterial(mMaterial); - /* - Ogre::Entity* underwaterDome = mSceneManager->createEntity ("underwater_dome.mesh"); - underwaterDome->setRenderQueueGroup (RQG_UnderWater); - mUnderwaterDome = mSceneManager->getRootSceneNode ()->createChildSceneNode (); - mUnderwaterDome->attachObject (underwaterDome); - mUnderwaterDome->setScale(10000,10000,10000); - mUnderwaterDome->setVisible(false); - underwaterDome->setMaterialName("Underwater_Dome"); - */ - setHeight(mTop); sh::MaterialInstance* m = sh::Factory::getInstance ().getMaterialInstance ("Water"); @@ -379,21 +365,11 @@ void Water::updateVisible() void Water::update(float dt, Ogre::Vector3 player) { - /* - Ogre::Vector3 pos = mCamera->getDerivedPosition (); - pos.y = -mWaterPlane.d; - mUnderwaterDome->setPosition (pos); - */ - mWaterTimer += dt; sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(mWaterTimer))); mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); - //if (player.y <= mTop) - { - //mSimulation->addImpulse(Ogre::Vector2(player.x, player.z)); - } mSimulation->update(dt, Ogre::Vector2(player.x, player.y)); if (mReflection) diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index ddf6ef7ab..633a30664 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -25,6 +25,7 @@ namespace Ogre class SceneNode; class Entity; class Vector3; + class Rectangle2D; struct RenderTargetEvent; } @@ -108,8 +109,6 @@ namespace MWRender { Ogre::SceneNode *mWaterNode; Ogre::Entity *mWater; - //Ogre::SceneNode* mUnderwaterDome; - bool mIsUnderwater; bool mActive; bool mToggled; diff --git a/files/CMakeLists.txt b/files/CMakeLists.txt index c29d917b8..9e65b516b 100644 --- a/files/CMakeLists.txt +++ b/files/CMakeLists.txt @@ -1,7 +1,6 @@ project(resources) set(WATER_FILES - underwater_dome.mesh water_nm.png circle.png ) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 6495b0cb4..37ff17843 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -16,7 +16,7 @@ #endif -#define UNDERWATER @shGlobalSettingBool(underwater_effects) && LIGHTING +#define UNDERWATER @shGlobalSettingBool(render_refraction) #define HAS_VERTEXCOLOR @shPropertyBool(has_vertex_colour) @@ -242,18 +242,8 @@ #endif #if UNDERWATER - - shUniform(float, waterLevel) @shSharedParameter(waterLevel) - - shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0) - - shSampler2D(causticMap) - - shUniform(float, waterTimer) @shSharedParameter(waterTimer) - shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight) + shUniform(float, waterLevel) @shSharedParameter(waterLevel) shUniform(float, waterEnabled) @shSharedParameter(waterEnabled) - - shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) #endif #if VERTEX_LIGHTING @@ -305,13 +295,7 @@ #endif #if UNDERWATER - float3 waterEyePos = float3(1,1,1); - // NOTE: this calculation would be wrong for non-uniform scaling - float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); - waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,0,1), waterLevel); - caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); - if (worldPos.z >= waterLevel || waterEnabled != 1.f) - caustics = float3(1,1,1); + float3 waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,0,1), waterLevel); #endif #if !VERTEX_LIGHTING @@ -358,41 +342,17 @@ #if FOG float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); - #if UNDERWATER - // regular fog only if fragment is above water - if (worldPos.z > waterLevel || waterEnabled != 1.f) - #endif + +#if UNDERWATER + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, UNDERWATER_COLOUR, shSaturate(length(waterEyePos-worldPos) / VISIBILITY)); +#else shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); +#endif + #endif // prevent negative colour output (for example with negative lights) shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); - -#if UNDERWATER - float fogAmount = (cameraPos.z > waterLevel) - ? shSaturate(length(waterEyePos-worldPos) / VISIBILITY) - : shSaturate(length(cameraPos.xyz-worldPos)/ VISIBILITY); - - float3 eyeVec = normalize(cameraPos.xyz-worldPos); - - float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); - waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = float3(0.0,1.0,0.85) *waterSunGradient * 0.5; - - float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); - waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = ( float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); - watercolour = (cameraPos.z <= waterLevel) ? watercolour : watercolour*0.3; - - - float darkness = VISIBILITY*2.0; - darkness = clamp((waterEyePos.z - waterLevel + darkness)/darkness,0.2,1.0); - watercolour *= darkness; - - float isUnderwater = (worldPos.z < waterLevel) ? 1.0 : 0.0; - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater * waterEnabled); -#endif } #endif diff --git a/files/materials/openmw.configuration b/files/materials/openmw.configuration index 21ac9416b..b953a9131 100644 --- a/files/materials/openmw.configuration +++ b/files/materials/openmw.configuration @@ -8,6 +8,7 @@ configuration water_reflection configuration water_refraction { viewproj_fix true + render_refraction true } configuration local_map diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index ea54bb24c..af5be42cd 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -21,7 +21,7 @@ #define NEED_DEPTH 1 #endif -#define UNDERWATER @shGlobalSettingBool(underwater_effects) && LIGHTING +#define UNDERWATER @shGlobalSettingBool(render_refraction) #define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix) @@ -210,14 +210,6 @@ #if UNDERWATER shUniform(float, waterLevel) @shSharedParameter(waterLevel) - shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0) - - shSampler2D(causticMap) - - shUniform(float, waterTimer) @shSharedParameter(waterTimer) - shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight) - - shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) #endif @@ -242,17 +234,7 @@ float3 caustics = float3(1,1,1); #if UNDERWATER - - float3 waterEyePos = float3(1,1,1); - // NOTE: this calculation would be wrong for non-uniform scaling - float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); - waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,0,1), waterLevel); - caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); - if (worldPos.z >= waterLevel) - caustics = float3(1,1,1); - - - + float3 waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,0,1), waterLevel); #endif @@ -353,41 +335,14 @@ float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); #if UNDERWATER - // regular fog only if fragment is above water - if (worldPos.z > waterLevel) - #endif + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, UNDERWATER_COLOUR, shSaturate(length(waterEyePos-worldPos) / VISIBILITY)); + #else shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); + #endif #endif // prevent negative colour output (for example with negative lights) shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); - -#if UNDERWATER - float fogAmount = (cameraPos.z > waterLevel) - ? shSaturate(length(waterEyePos-worldPos) / VISIBILITY) - : shSaturate(length(cameraPos.xyz-worldPos)/ VISIBILITY); - - float3 eyeVec = normalize(cameraPos.xyz-worldPos); - - float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); - waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; - - float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); - waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - float3 waterext = float3(0.6, 0.9, 1.0);//water extinction - watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); - watercolour = (cameraPos.z <= waterLevel) ? watercolour : watercolour*0.3; - - - float darkness = VISIBILITY*2.0; - darkness = clamp((waterEyePos.z - waterLevel + darkness)/darkness,0.2,1.0); - watercolour *= darkness; - - float isUnderwater = (worldPos.z < waterLevel) ? 1.0 : 0.0; - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); -#endif } #endif diff --git a/files/materials/underwater.h b/files/materials/underwater.h index a760202fa..8474f299d 100644 --- a/files/materials/underwater.h +++ b/files/materials/underwater.h @@ -1,4 +1,6 @@ -#define VISIBILITY 1500.0 // how far you can look through water +#define UNDERWATER_COLOUR float3(0.18039, 0.23137, 0.25490) + +#define VISIBILITY 1000.0 // how far you can look through water #define BIG_WAVES_X 0.3 // strength of big waves #define BIG_WAVES_Y 0.3 diff --git a/files/materials/water.mat b/files/materials/water.mat index 372058f0a..3ea6a2c2b 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -56,11 +56,3 @@ material Water } } } - - -material Underwater_Dome -{ - parent openmw_objects_base - - depth_write off -} diff --git a/files/materials/water.shader b/files/materials/water.shader index 59b9e5a43..793cdc95e 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -272,38 +272,16 @@ #if REFRACTION shOutputColour(0).xyz = shLerp( shLerp(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpecular.xyz; #else - shOutputColour(0).xyz = reflection + specular * sunSpecular.xyz; + shOutputColour(0).xyz = shLerp(reflection, float3(0.18039, 0.23137, 0.25490), (1.0-fresnel)*0.5) + specular * sunSpecular.xyz; #endif // fog - if (isUnderwater == 1) - { - float waterSunGradient = dot(-vVec, -lVec); - waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; - - float waterGradient = dot(-vVec, float3(0.0,-1.0,0.0)); - waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - float3 waterext = float3(0.6, 0.9, 1.0);//water extinction - watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); - - float darkness = VISIBILITY*2.0; - darkness = clamp((cameraPos.z+darkness)/darkness,0.2,1.0); - - - float fog = shSaturate(length(cameraPos.xyz-position.xyz) / VISIBILITY); - shOutputColour(0).xyz = shLerp(shOutputColour(0).xyz, watercolour * darkness, shSaturate(fog / waterext)); - } - else - { - float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); - } + float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); #if REFRACTION shOutputColour(0).w = 1; #else - shOutputColour(0).w = shSaturate(fresnel + specular); + shOutputColour(0).w = shSaturate(fresnel*2 + specular); #endif } diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 00d4eea11..693c5a9cb 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -280,13 +280,6 @@ - - - - - - - diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 044cc3406..2dee5ac88 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -138,8 +138,6 @@ reflect small statics = false reflect actors = false reflect misc = false -underwater effect = false - [Sound] # Device name. Blank means default device = diff --git a/files/water/underwater_dome.mesh b/files/water/underwater_dome.mesh deleted file mode 100644 index 64ca569c22a04110e7913505c427f0087cef51c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22585 zcmZu(b$k`a_uVA~0)Zewf`tIVH8>=125SjW+?@cyr4-i&cUoH9DH@h)b7#(6nb{a=Th@;5+ofUjPhF#WbR81?Q`-Sy#mcu% zX_Sa>YT&olJS~<+ zy2gyGZY|GNU+?($h3k2zEG&=VcRp_TS;{G=>=c3eBV5;FgXH-vPr7e}JfG#!Q_Jd& z8Be=f;rYquJ$1AEX||!B-UX{Gmd^bGuKL~pB5M%{m(M#{5fzvH^q@JA`{6{fAle}?Pj z)7q$&+fwVB_q$2`^NV|UCbmwH`U$7<>!Jgjs7Z#uly48a;yN7I#WN@>LA6*~-Ws^D zj1G+%s-D+KuCuKBRqA`5M|rMnd?xirtMv)Osp-$ptMJd~rGBT*WjyT{mzMg&Mg-|YHi52D)W^`TQa^V>faj0ljimmZOX>87+3_k{(N$93-)F2Vhi@t=-@WUq+b>6u ze)xEg>b>MwwXbe+56A!F^cU8yK2cJC=idSPUXueV+l8r8p13v2_3xcTDeqU=?cRSe zPW8MDWj)^2PwFpR>Zb>0xTa42T};Y*eog5rQuKEzUzMwy`{M?G zT{Q14b*|e}SCt`|r2bzAYg$hdhe-W@*ZS%&1sGYV{TMrFItni2<&ksp?(@IO@i+g-@ zli_a^)E0BDM;5719YU1)D;IoKJyII_N!2z|e?zXV5xv4ZQom+Yu)Fg7q`F$!cZ$4V z`>CI1&BLXA?@P>gf9{?_=dS-u<@hyJ`d_`#1XsY)Nz(sRf8TM>tsbD8HM@`b*G%+# zXKS3Rooln`x77PgR^c*%I&bCcD(9lHGJeC_UvX{Ba$Ux6;L-|Kj_@E|)i|#*3|T1i zBX9pC%DCer^JCk@7S`j=Idsce$JN@CaWem6-)2yG2WOJ`_n^jL>%`{VI{4Z?m9^Ia zncpi@=2La%=9l@M`OGA1aYO+<^08ax&VEVw(|b%A)h9OPPxxOaah=tvTScAFX^Fb? zG>NP))WiDuEo6NelI0)E|NF|iP?MRe)8gc^e%;vAPI;o*d&-B+P(MxFVJ)5>sny>T zWqsoM$$5JAb7xr}hZfyw?T@afvz8sAo}^4I>+j7CUDfHf-DUk9@OihD=}j};EN5F; z|2XPX!Go(6ddT`cZDWF!v_*T}V@_pdUHzPl={JwQ+t+Yj@HAf&s6oW zez87zykTx5sUMm;z!STyw=ObzlB{2BA9=j$U_EJH&XN9}WdmC3^FJy1vVWAAb~VY4v-WQ5X8@zRH(1gYYZt(O%cJ ziGzh-u5J0O{PogmzkW{??FRYD^|Qj<0>aPb^>4T{?n|k6wtc0l_(cl8Gp_b^WlOhC z_#JsO+8r3_t5-#QQ2lchl5$?d>;ER@yxz8ab-!Vs6zu|^&ueH@8hJjiYLmY%e&e0G zd-tP@>m#pLSR-j4uVep7r(cG@R^%P~$7{&&$Q4@X;{qWj;>{`(e zul-)PB6~~44gV)7(4vKzx4eS`IbH03_)-RbT*YDO`k@-RU&3RJn&rCAE zc^0cf!oZnoBBJ1au`ORygsrB@QImcCj zdB=qxymt7msQ53uX6fHt*J*c1>@)dAJKgS=FyR-kYf^R4_tx%F#qORH{_@%*Z)xE# zuMKMS)W!a^#Qu}N^aFYvE-n1!^~$_KdUdv~io7TPxek!`^bffX6p87hE2@WLzgeH_ z0C`XUkn6zjWryoDsqTyYX8Y*JkoWZOxDI^U-%0;e=dmL1$$zc`+Zf+*8}0k$hN)@y*+1Gp+I{wqen9JlAlQ#2 zns%T1p&vlIPyNsjC<*->&Eun~AL^I(fp%Z~NB9BerM$Z42_H?n&+(xjK)cWJDLOEd zC+zPcy6MoQn(Ge7m;9sM=lIeOSm7z9|1R#UY4_c_1l2TV9yMIYUeOw;aje$o%1-RJzIAF%y>O}$`za?O5oe$x-2-RJzKACP2z zLp`FGpQha>Kj;V0?vo$%1LFQ|rS~>Yp=tNYFUBdf`{Wn>fNbtgI^c(tns%T3r5`}M zPySws>h1{}+DETz?5}C}$zR4nwEN^Q{Q&Z}#fVgzaUtt7PGnrj`iv9X7wf6}7R#j> z7qUL%IL3vn&p2_|h(Y?utWZt=mF;63$GDB{V;tAvRD1nH=3vdZjQwMr#<+~}8{@PF zHJW2?Wz(Ej)DQc|xQqH>9Ol=wp58byNHeaYei>&muA+V!XJt+wsrP=(s5$RBK3sno zH*tIzM}<_Wq~qoWYQ{wzU&cv{i#WbhqN{lB{99gUXq!&cu5o^h!ura%hx3DRP?mjR z+OI+y&A5j1i*XL)8qP1qIj*OLbjjSQHTlQ+N&km&3+E@}n5k_;^@e=@nsEu|H{%q> zC7j=kQ@;8J>!`9RgkR(b$C+^l`N25kHo`NcRRbW=LLVX&`e z+(3SE92hr{pNu2o|Mu6xt9>-%0`i-20^F>?}9YIWaN%Go}~NvzNIF;41KJFVV+*-y&ZKkqzb{}_kue2`K1 zy5=wC)DPo4)~9|L=XLudn_l%WK+36K`kySPei=ue|2da#5RhKVIX;Y2SQpo`(El9wlSWmipPA5>ih7G7rP&lfTTveEFxN9($sUl=I({ zbe24hLH;t2lUTU7F4-cS{C7L}ue|)v)V-OW-#3!{m)wobf8<8~?h=u@A$}kHcRTp6y!_w&zLNfKR2lN$?cl%i^8aI{ ziaPRRaq{0y{`dNi|H{k%MUP79fA-Ng7`&rANhIX~!Mf&a?O|C#v< z=obZYk^gQ7|6N}GXIYb5S6i8#{C7L}@AC3LZL1u5cda1u-|gVP%gg_2WrOtQv>C{M zw}byKFaOsU3)CxKry>8{4*t8m{7+LYKv#L-PyWX{`0w)ae}9)0I_^nw@;~0e{|GPt zPs~lKeLwnW*ncUv?Z3-w|EIWpbop~hrF{KXDUDvzJCOEY^kdt9<+cB(&jspceS>KKErqf6HP2WqfJ>2R#kZJ31Di{kJ$jmrv0}Z_Fv{F?f=7L#dW_S6>0x1hy9oNP5WP~Ng2JX zTxHsSi~O+dzwm?hzeeqFeWGn7?Z4%)|H3cY|JeA-x<>kXwEvdF{tJI;|7-7v)N{Ht zqy4wYf7|{Gf5rYcsiy-+MQQl|Qs4IfHTh5fe_F+|+Lb?AW8Ibdw*L?Ck{=dvG+y9sOMgRYLx{SKQ>HHf0 zzsyhD|Cjkm|3CS^>2$gSxitKLi~P6!f0^I(|Icg;&_ix#lle{l+y1}sgZ_VkMgIEl zLYXxDf8m$y|10vJ{{Q~Pe)`#@w6gw?pSJ%m{G|WCZndv|Wcq9P|8DZ%_Wy<7^#7-9 zPofKt@zsd?rQDAHrJV8qmU*VGhZunCBcE@_|BCAim&X_8gakq$BzF+KaBtPz4Oy2sszjUkpFi4FZyNt zf9PgPeQSBBM%*vsW5@q8K8*iU-ASb*%NEv%|7Coc2SD7fxxO?0zx6Rdzf4+EBkq^^ zVaNZP_JQ$#uHbaKW9|wX^TKk(|C;uN@qcXBKpix*l1AJw^V5$1HSH7Q|L6l5b&mm& z8gYlrZ#({%`OWx0wsw$CdA6QL+%NpF>VNhQ*5JL=xAT8epLu|7 zpHu1r!+z4>z3|`8|4Du30qzB*(u;pVtXT4cw9n4}N&A=w==M5=9y`3V2JfYRcK%QL z$2>rjmwvi=x7HfG7ya1zKhY2K0A+prbY!MR8oU?%+W9}xFY^FP!;{GW_3^8lBZ`XY`Gm+_^2;QRvbWqvRZ5co8y?&Dip zgZDDO?EIgmePJG;Sh=J+^l1@Ue>gww{GZHE<^jr&_tDW=@@ep1=C_^ylljd&z|}iR zbdP~K#lDaqcK%QJ!8}0PN=fu6BZ~&_E!uxO|0n!n9-#IzQ;&*GFa8htY3KihpUeaF zNowlNT~lfBUifY2|AgPn0~GIS=ws!QG5;^+cK%<=nFr|5;fr#kocCfBApm7xMt2&mXGD9-TGfeh=+G^8m2>!e8bArq8*r z4mSM>^Yg#GFYbfE?hAjJ2YB}Rj*6%~LL=^%`u6^?)Mp;xN~?I~>*=ZC_j~9+a32eC zztm?QpnHLTRA|A$8gak0kMSqserX@`0ACV!tNV33XvF=}KYM>x`o}y#?D+#K%ZBFC zKkA2h0L1;GALaor)jg)Ndg^J!{T}*P_Wr8qw^NN0R`=1TRHrVHvi`{W{NMhmj1Thw z-*r5%CQYlP5%|M&3|Q&5{~%zsxUt ze^cfc^8gJx-cc(`6c+!7^OO8T+%NNU*vYHzv8^7cDGNh2;(nRm_Wq>IZ{`8se4nVQ zR0`G@SK$Zwg}7h%!8|~AzvpU;Uyw%JFZ{Ci7lmKU18jG{QWIcb8Gn(V_Wq&plX-vx zQSVfRr~Vpozwq1M9~6GK7`ZgQzwt@Me(=?Z`=y*?jJRLQaT`;7*LziBw6DZ}d_Kz& z_sjEHzWT;Xl@U1`#QoAfmLu+$_OU$E`$Uy>Vp{P($$yq3?w9_tyveJ3s%^eZ8gakq zhvkU-ML#V6`@#+N?0PowKdE1qBkmXdvfLVfNtKSzr4jeb_^=#tzl;ydU#C5zemk6B z>>tOM<%s)bd|4jT?wI;Ju$V^NFY|-{hPYqm2k(p5-LJaOEv>PCFZKohW+3jD`Ni@^ zpFHaAfN+htU*;#v5%C13hPYq&%lp~=$16|A-cJ6zk@xfRUrpK8Qq8E-%*+26<^df1SDqp+^}b7#lmBi9 z|JD8F168jNb)EcoBk$+szZx`ag6dEu(#e0fga7Jtj~U80V`V4*-N^fS`LCM(zE}lz zs_5ju8+ku3|5b~$Yt*}-(mKum`0vK~2rvIt#|LpLHe)d-|J@G$tCj8Cs$WzAC;#2Z z`^o&ekn4--SWRm;fjLVTwn`{q{N8ZoN|A-Ph z-l`&JlRE8xJo5ft`|nES^G5yi-p6VG-H7|W_TQDP!()~Aaq@5WpLqbp{a*X;y1L<} zdUD_2Y5(2G`+M!bT6pffD)Bsx)Bd}W_xIX=HS^Rlm5?rj)Baly`>$5U>`|E`gPiu? zLfr4Q|El1FZEE16>`wb{IqbhG@NB(m8Jf#!|1HG*Ui+_({kTkpoyhC7|CYo4t6hC( ztL>gbPWx{m?)Tb%m1oB!HSJz;r~S7a_Fw(*;}F%OO&Q(ffA-%(-0!vjszO|AwN-~Z z?Z1V%-)sL>tVgM`(T+dut4%Bt}{}$qY zsSp2OUrc)5mETiF)<3Qn%mZNG&+Gr|8Dqw{23HJs`u`T5ci9I;s2|Yo_=cBygW|--*Wi> zs{FYLs@8#=PXFIR+%Mw`|6c`+nx&$%Wq11jmc##7UuQ2<U4)w z%J;JWH~)X_!@X|A{lYK!|0-_YRTYc;I`f~l|L;cJFZ_i6?<%(bfvR=K*XjSe5%&wf z;s3k3#=cTB-Xw9x|8B(nQqJp_?Jw1dv!*ltcO&kX=kq$~c~i2J?qzk1msR$UBE?Tr5|NBpm&_sv(~Wzy)h|BL@E#QicqcpWxps#@MSo!;`l z_}@a@FZPAkhzY}0?}dTR_}@a@FY}Yv!zJ3N*f$xS@xO(*U*Ne<9`crzwnFK;O=)_rLqL;RCfH&E8>3PFRz_0&u|?tk;@zZ$1o3o zxL^3oYmPr3M#Rktb>{yp^4`w>>7&QmyGHc(_vZg%=m#P0m-<`>{1dZBY+Rnong6pK z`9B>Ny5Ci=UP@>F&m!;b{GTpd#$T0=OySJ`S%~{ZKU@bkXDFe1HuQ7m|19#J`4z4M zzRMb@nZuI{|LFfS4}iGeoBz|5O7~T1HYIcB|19#J`5mqUcl{=+hWC7(`9BMBzc>G< zC-0rDV#9o$`9F)iXZ+7~;NZO#s_DR_&itQ+xL@Wc*MT3V#i;|we7@!XT*w2E_snl| z9VmNbrz%iL_P53VXP%k7XMUXPz|4P+s>-91IP-rNd2i?clz+R6>eDsTng4T>_sq|6 z9oTmDt_rDaI`e;S@}Bv9t^+<*UaH6yhBN=~M%*vu^aHw}eDkF*iu)5>Uzi6#-0#i* zt4i1Is&jvQR*w9?g}C3F|Cjdd?)FJJ^8Xg%e(4|mfJJdf70)*~^8Xg%e$fy8fGqoW zs>g5Se1tduZz1j%{n8IeJuyyoTk%dg^8Xg%eiR$MgdpBoo3L z{Xbpc#cfyP@q3ha|L+{~0Eqj&`+vId)gbjE{~?^u`?mk*LEJC;VI0tSe1uxj>9}(2 z|9P`uBD7)ziB-lw<$TqTg@t|LLrCVpYVeJ3N2m-T$)?_j~vM^!Q$z zRmxWnlw<$TLfr4&|5K$4C#Wx{5`|xkk2%hW`@Q>rDrCWNwQlNj<=FqT5chlc|5UDH zm(;cjua#r}&yBcW_{liH|I|Iz?b18t*#C1Q?)UEhxq8RHR0jrqQt<5zd;eeddAU9? z53p^`E2S%ZkaF_ho(G1#|F72m^+5Txd?n@f{=dZ7_Wr;6ZoySGs_zpiXaDSZXxRJz zYEi3Gs>{IpQf}}6OMQF)Uv0awUv+MOQ_30td-tL2{eRsrPrPcK<+7C9`~Om(qV_+sdS(AOF8Ek?H_ez@BiyM zb0(-cyLL*sz5g#c4txJ!zYXuFdZgGU<;-t+^Kj%p^8jOqHdZq({3Yeg|1l51=iB@L zI&^4hm9N5TDJTEEc{qFjUyn>otERtPB<1%0ztp$)|MiH~r(I9)$-5GKY>b@;@b3TX zL-k{D&S#?Xp8vUxJfP$JkM10kO`ZL-jk3>u#Mu0|?EQaTaMNSgQcop0zs~kC59m1m zqw|bIe&Fq3@?XyX*!;Kb{eOM=d@I##`b6^Id;W*~x2PZTf6x8F>P6L=(O9|_h!ufE=`5()1{zs=dy-mHlwNK99aei_ilzBgU|6ix>vqw!|c%1zAp8p~L zz2|>aVfQg*2A(JX<$RpYfA9Gp6?XExs#E?RJ^w@g zyY2mdwIcelx>Wla`R_gdL;icu|G4t{zEPt~y>p)bqy2Z=`~R-z?zc(}eIxC2*nfFG z^8g9wo~rVf9@G9y`?wF_IRB?MUb?4Z3f`jq_n!Zw{kQD>f7N==HFd1+1=@en5BC8a z=l@jPkaKE(t>bb&lKSO7vE%%oj!Sl2MSa>s`>*W%f7*YG{Kxq}J-XgLwX^wlIe+Z1 z|1!SJ1DIvp>O=bt%6tBg`v8vffBNkHIF;_sGC7~k`DNRGnP1EUY&{aIYCf7x`>*W% zf7*YUpUeZ?Y_?c6FFTp`U)lTrwEr@{Y5x~T%uw6<45j^7KkdIo{?q=?7}r7-?;Wh{b5~ybFZ^X5pv|Rl6*%mr z%W?jf{=diT|8E}mn@SaN&c%H{t{=Al501+Izpm*&UfoYO+Qof8wvYCg`+oNRziyvq zp}OIh{@eNALf8l7zMt3sUudmV`FfRcp8uu)FYjm3{~xnugL?l%6X*F~`v0O|`v0Fk zZBYdZ^q2F$93R{Nm+@g9;9P=7ZOc0G+xg!)*avi+|J70D_p6|jv%a1GWt`_Y|Ev2{ zIHoE;U*aM=*Jpa%5U;4-R|4Fjvs&d*B&h!6_|3yEH|D($!s+3C; zWPHefp3`ug|5tmPKTyRlZFZjjXZ$bY!#u!)c6U^&^|9a1|6lJkm+`;H-v8HI3f)i} zQZ7)4{}t^&^8noUxA*^b@hg{AyMt2|=7r+?;{4#gzrFvj{UXk*+S`Xa&;K+2_t^XY z`rc2c)PcNhzMcPn*Yg15e-F>MF#ez4;+UE>JHmPXpYgx&gYkd!JqJ|keL>Fi|BU~I zUyT3%-nLuCx4P{@+%NpMrKtSpr>&i8+q|C8}y9^gvV7phTsU-%c_-v43#&!c>DYvuvm*I%lH!V?wG{m?#ee(~H7 z=LhouD{8-1n&u1Qh=l;ll<^g6UH?_O*y>IXT+4+BIAM*gsmz#Rbsf%L&*gxh0csI`F=I`|3tsc1H8SRQC~>bMsfY&_%ILPcz;?A?iZ*t%p9)Z_sja;80Ua_ z?w{*B^8lkurqj3fO_lYP^MiQ+$NSH!x`DI*<^t#Y&D{SJ{xc7-bYk(JKs;{{-4Zm<^j^b_0ucoz!t#26aIr=j`xpUy)q@&Cjw45-!JC= zpYV%$fR8R;9ar_T#9!nm^8k+bhh4vR_tEuh-v9P~u)Y5${Kk6#5yKXkI=nRE_ez~J zEnGg2DaDOO9M+oDvBqT0hWPO1iw@kSQb)Yw4fZY9Hc^MS$SZ2NCna2 z3cw1G3ZN$yffXU;M-Rh+;gIs7=MlgNNO_?V7tjSM6q-^%1t||SsDT<%ZfLd=uo9$P z&~_z!LX66gDhXCLs^D8%u!>O?wUuC1qZ*#-60Bx?hhK{j{Lc6utq2$V-l&e&RTQjl zM55Id1S5?a=uLUS8b(d@vYcQ|qZWE!RJh3sbF{B^xOHF`HAk{((ngW|bs)?30 z12%(H11)Y2Yz`?BJ!t`K0jWBA*b>+h()Z|jD_|=~-$5g-fvq7`gQnU5+d!%c4Ymcg zg;WKaZ3k=zsWPt*x>_J!07HTwbkLF$Po_6PQd)C0dX05||r zceG$2a3G{^XxSj(AV^)&;=#bdkh-8JLx4jdbw&?|0*6BCgq{xr4ucd8jSL44htv_8 z8UY*usRK0lGw^3f?V;HiU<{-vXgda<5Mv~y7{QUoD17T@!BNI&)E*%?+8BeU4i_9_ zjK!}F6C7)dLo0>~jx)xibwdQl8xzp#!GaTviRjHB!HLEs^m3r!Bx5pqKR|G@F$G%b zFF3`R3T^choN7#i7W)cLGk$?~`w0GG{EE*n#&qCx<2T$*GkypD4rv-{&H&DUG!;*r z37iRO3Vvx8a2BM=Xu)jYY)F&PvN^yxkS3zVbAfXqO+ZiP0p~#)j~>nk&WAJ(JzoG^ z0BI~VvJkis(imuJ5pWTt(a_*x;9^LlpxGtBC6Go!+e`2XF_uDFBDmD}1K(OK_=m9! zwHFC4GnV723k8=OEAVRz1Xma<(Te$kD~(lX-8{in#%i>BuHb4T7QLAx7;CISFJ}v` zG1j8@vjo=~>!6jHg6oVwp{*H$e;Vtd#oq4F=Kzwp^$Yy@sJ{>I&UBMuk` zX+3Ig0&arzC!Y8Z@E=I)@JpM4n<1@53$_5aKw5*AZ3S+H6pI#b18#$~8a>$#+zx3K zdbk6)1JX+LJRTSiX$3Um2D%|Fho&r`1!);H=mB~l{Q=GH1nz{i6x!a2Pl&M#(oVr$ z#%_GeBe>g0Ky6Df!PtYRx&`+bd+}@Wf_sg9XvGe}ea3#YZoA-q;{aN{P4Iwm5WU$d zc+fb6UTzUQWE@8CHwzv%jzBB_2p%zxLR*^zj~d6I#W=xZ#&KwOqu_Dl1U|=&lfaY4 zzqmVQoC2PLbPP3515ZObiYJ}{o`G}(zjPLO7Sds~;2iKAq(f-gdEj|S2hrjSzzdKL zpeGlB7a{FO4=({PLE49&Uj|-=v=WZZcok9tGQxFmSjxQEtV6uf8L zN2@Og-ZvhgH|GT(7!T3QbAk_zN9g@o!AHhpXyuIHVS#qWXdA>Bt$J^(*Jx`!Tq1b&2c7d`(3`~>L^H1Zkv8PaWN>I?7-q+8J7SKwDj zH=$X>yovw6;x2?Pt{GyOkN`l_Ok#e)H;GA1AM-Qn5Pi&~<|jOhnAG$&KjJrtzGgD> z1Ad#B%uH^+N1KSrO+WJ;+Dh~@Qo zOX!H0+6*wCLwCdgGmZHIIwhtt)8doHOb1M7rpH}?83+u76oC2}fEggA#&a_QGeSy* z-^&Ed1j!%m$PCO3DJ9w$1Pp?d0`1NM%mT>|{mBZ<3Mo1InGKi?QZn>EJ1{#WU+5(V zFbAZh&{r@p7?Kb4m=l;2QW9u31Q-GdcSZ>A;GaVZF^Rd%-1t^b!Q5sZ)D9NRV}|0X zIRrz^y!f^3f_cq+Xhk-`d}e;ME~{XEvjAG1MX-Qb5WNW!ENB)&FEa}kG7F>knFI@) zMWB_8fapX#9cA76tEPeVyIafSQ=7M zJh2S045T9XrLw@XkP4#(<$&cN6++9(1It4yh!$4>R)AChJ*fz+2q`~$7!C}Fln*_R z07gK{3yrvdE=Zx!lmaS9d7wcJ)R1yRtCfJ2AmxI#E8#B0z?l$SiIvSN_?8x|Vpc_M zC0Nz0hNrp&tC`>7*CGVJGrvbG!UexKtD|)l1*@BpXmtg_NV5idQ(mx!Srff1Cs@<0 zh2EDHtY!WHt&|b`!K@8!l@_dR)`1pF3Dz;|Lc3vtbzfU5SI2A!YzV0i zYBmBkf>aw%Yz%A+=?DB$6JQfawa|j5z^0IDqGip1%^=l4i<<+RLyAOCS^!%>s*WDE z1h$0qJ$l{>*b35j&`4`wYe?0gsW!kikg7t1ZGmkeRe@I90oy^U3~jf=U5F6{shvrT zGTY-@Z3Ww#9ZgIx7%&zE7 zGr_KAH}tZpU^lZndf!B_yV(O;X)M^o>lg!EJ{Q$wq<`ih9zu**eDzw#4aH=^CTI?%0&HM%0 z?IZY$`71uZnA3sN&EIf0&HNqsJEUo-IRiKY(o{TgCU7RCDfp#Xz*&$cqXn~pvms4F z%jN**K$?ga&jrqfGyy%C2b>3KJbE}EI3LnD^n3wu0i?0e$U@*kNMoR>MZiUnMni*( zfr}xHf>xIRmp~c`Z7;!Hh_MvX5|g;p`~%-wEcl1H47C>tE;E{n=9~Z3j|k~ zE76Mif-B8cXx%))Rpx56damGVGZwv>BN%J0K`&+nmP zftw+%MGLk7w?JBhmTd)Yg%pbxZv$?Fv>H9x4%`lD6?(V>xC7Ek^gJFI4`~H7;s&}Q zEr+Hopap3eH0S|(ApHTY?gZ|Hv=rLjiMtSE7o?pgahJIp-|`6VHWN_W5==1n;HhrG zJ?38gTD;(1b01o-zowhA6J522S^1P_^q(fiGUhs`6< z%0Gff%%jlOCc&fTF=#PP@R)fV+TAF4+&qELaq}ebr1>xIj+v)`ryw0e&C|fskdESs zXMkrQ9l#_K-vRMT?Jl+lmHE0173r)8(O^%ybfs>w0#|SA;t|z*G=LL^CrG^P4K39 z3$?Eb-ZF3FsaFJVn|JVQmj&;bchQPVf_Ke(Xx&A@d**$#`hwtn^8tEuUhskW5WPGn z_|SZW-k%kGWIl#g&Imp>6QQlsf{Er6Xz`Tb6Z0vwds6VJ`3#?@=5ye4^9Amnm@k1Z zAw5COSHM@067j^>z}Ju-b~&9{3*8ee~o5@B^fK z=;24;M@VfBV3xC41h(X8~f5dMPGa--s0l!Vmfc)}%w27D=dFOX% zD={td(QnZQVgT~gZ_qblD&((UqtC>Y$ZNlXE{J|cGUFw5L`-HRHJ(Fv#H5Cg@d7#} v`k>)yEBP7BmK(q3#+8S#_{TVTwg0fL{9zXSn>Lo@!Z(bi*@*vNLjL~%QsK$) From f1d35b73b80c361724efe518de3742f998bd3103 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 Mar 2013 19:52:20 +0100 Subject: [PATCH 104/151] Cleanup --- apps/openmw/mwrender/localmap.hpp | 3 --- apps/openmw/mwrender/refraction.cpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 14 -------------- apps/openmw/mwrender/renderingmanager.hpp | 2 -- apps/openmw/mwrender/terrainmaterial.cpp | 6 ------ apps/openmw/mwrender/water.cpp | 17 ++++++++--------- files/materials/objects.shader | 13 ++----------- files/materials/terrain.shader | 7 ++----- files/settings-default.cfg | 6 +++--- 9 files changed, 16 insertions(+), 54 deletions(-) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 9c82258f9..72e637d9a 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -117,9 +117,6 @@ namespace MWRender int mCellX, mCellY; Ogre::AxisAlignedBox mBounds; std::string mInteriorName; - - // maps texture name to according camera settings - std::map mCameraSettings; }; } diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index bb2d88865..d590dbf4c 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -33,7 +33,7 @@ namespace MWRender vp->setShadowsEnabled(false); vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Sky); vp->setMaterialScheme("water_refraction"); - vp->setBackgroundColour (Ogre::ColourValue(0.180, 0.235, 0.22352)); + vp->setBackgroundColour (Ogre::ColourValue(0.18039, 0.23137, 0.25490)); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c8b5926d9..382ec6557 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -121,9 +121,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const //mRendering.getScene()->setCameraRelativeRendering(true); // disable unsupported effects - //const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); - if (!waterShaderSupported()) - Settings::Manager::setBool("shader", "Water", false); if (!Settings::Manager::getBool("shaders", "Objects")) Settings::Manager::setBool("enabled", "Shadows", false); @@ -504,9 +501,6 @@ void RenderingManager::configureFog(MWWorld::Ptr::CellStore &mCell) color.setAsABGR (mCell.mCell->mAmbi.mFog); configureFog(mCell.mCell->mAmbi.mFogDensity, color); - - //if (mWater) - // mWater->setViewportBackground (Ogre::ColourValue(0.8f, 0.9f, 1.0f)); } void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour) @@ -854,14 +848,6 @@ void RenderingManager::windowClosed(Ogre::RenderWindow* rw) Ogre::Root::getSingleton ().queueEndRendering (); } -bool RenderingManager::waterShaderSupported() -{ - //const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); - //if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) - //return false; - return true; -} - void RenderingManager::applyCompositors() { } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 49cde25a3..e40672ada 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -184,8 +184,6 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList Ogre::Viewport* getViewport() { return mRendering.getViewport(); } - static bool waterShaderSupported(); - void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y); ///< see MWRender::LocalMap::getInteriorMapPosition diff --git a/apps/openmw/mwrender/terrainmaterial.cpp b/apps/openmw/mwrender/terrainmaterial.cpp index d5e531f86..8a568883d 100644 --- a/apps/openmw/mwrender/terrainmaterial.cpp +++ b/apps/openmw/mwrender/terrainmaterial.cpp @@ -119,10 +119,6 @@ namespace MWRender shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); } - // caustics - sh::MaterialInstanceTextureUnit* caustics = p->createTextureUnit ("causticMap"); - caustics->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue("water_nm.png"))); - p->mShaderProperties.setProperty ("shadowtexture_offset", sh::makeProperty(new sh::StringValue( Ogre::StringConverter::toString(numBlendTextures + numLayers + 2)))); @@ -156,8 +152,6 @@ namespace MWRender // shadow --freeTextureUnits; - --freeTextureUnits; // caustics - // each layer needs 1.25 units (1xdiffusespec, 0.25xblend) return static_cast(freeTextureUnits / (1.25f)); } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 49836535f..2801e6494 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -210,6 +210,7 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend) : mWater = mSceneMgr->createEntity("water"); mWater->setVisibilityFlags(RV_Water); mWater->setCastShadows(false); + mWater->setRenderQueueGroup(RQG_Alpha); mWaterNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); @@ -380,6 +381,8 @@ void Water::applyRTT() { delete mReflection; mReflection = NULL; + delete mRefraction; + mRefraction = NULL; // Create rendertarget for reflection //int rttsize = Settings::Manager::getInt("rtt size", "Water"); @@ -389,16 +392,12 @@ void Water::applyRTT() mReflection = new PlaneReflection(mSceneMgr, mSky); mReflection->setParentCamera (mCamera); mReflection->setHeight(mTop); - } - mWater->setRenderQueueGroup(RQG_Alpha); - delete mRefraction; - mRefraction = NULL; - - if (Settings::Manager::getBool("refraction", "Water")) - { - mRefraction = new Refraction(mCamera); - mRefraction->setHeight(mTop); + if (Settings::Manager::getBool("refraction", "Water")) + { + mRefraction = new Refraction(mCamera); + mRefraction->setHeight(mTop); + } } updateVisible(); diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 37ff17843..7c7a604cc 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -260,13 +260,6 @@ float3 lightDir; float3 diffuse = float3(0,0,0); float d; - -#if HAS_VERTEXCOLOR - // ambient vertex colour tracking, FFP behaviour - //float3 ambient = colourPassthrough.xyz * lightAmbient.xyz; -#else - //float3 ambient = materialAmbient.xyz * lightAmbient.xyz; -#endif // shadows only for the first (directional) light #if SHADOWS @@ -288,8 +281,6 @@ - float3 caustics = float3(1,1,1); - #if (UNDERWATER) || (FOG) float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz; #endif @@ -311,10 +302,10 @@ #if @shIterator == 0 #if (SHADOWS || SHADOWS_PSSM) - diffuse += materialDiffuse.xyz * lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * shadow * caustics; + diffuse += materialDiffuse.xyz * lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * shadow; #else - diffuse += materialDiffuse.xyz * lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * caustics; + diffuse += materialDiffuse.xyz * lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0); #endif diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index af5be42cd..0120629fc 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -230,9 +230,6 @@ #endif - - float3 caustics = float3(1,1,1); - #if UNDERWATER float3 waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,0,1), waterLevel); #endif @@ -312,10 +309,10 @@ #if @shIterator == 0 #if (SHADOWS || SHADOWS_PSSM) - diffuse += lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * shadow * caustics; + diffuse += lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * shadow; #else - diffuse += lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * caustics; + diffuse += lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0); #endif diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 2dee5ac88..6ff7fb432 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -94,7 +94,7 @@ fps = 0 crosshair = true [Objects] -shaders = false +shaders = true # Max. number of lights that affect objects. Setting to 1 will only reflect sunlight # Note: has no effect when shaders are turned off @@ -127,9 +127,9 @@ fog end factor = 1.0 num lights = 8 [Water] -shader = false +shader = true -refraction = false +refraction = true rtt size = 512 reflect terrain = true From 5e50436a946f7efd9bb1fe281fd0a0ceb7513369 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 3 Mar 2013 14:19:02 -0800 Subject: [PATCH 105/151] Convert some BooleanValues to StringValues --- components/nifogre/ogre_nif_loader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 9652fd605..17cac7345 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -752,10 +752,10 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String instance->setProperty("alpha_rejection", sh::makeProperty(new sh::StringValue(reject))); } - instance->setProperty("transparent_sorting", sh::makeProperty(new sh::BooleanValue(!((alphaFlags>>13)&1)))); + instance->setProperty("transparent_sorting", sh::makeProperty(new sh::StringValue(!((alphaFlags>>13)&1) ? "on" : "off"))); - instance->setProperty("depth_check", sh::makeProperty(new sh::BooleanValue(depthFlags&1))); - instance->setProperty("depth_write", sh::makeProperty(new sh::BooleanValue((depthFlags>>1)&1))); + 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"))); // depth_func??? sh::Factory::getInstance()._ensureMaterial(matname, "Default"); From 8e076386994bf6e16deeaeea39a8c753a96489fa Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Mon, 4 Mar 2013 12:21:38 +0100 Subject: [PATCH 106/151] Update the trading offer on "max sale" button click --- apps/openmw/mwgui/tradewindow.cpp | 61 +++++++++++++++---------------- apps/openmw/mwgui/tradewindow.hpp | 4 ++ 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 290310760..e3cf8ea3a 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -64,6 +64,7 @@ namespace MWGui mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked); mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked); + mMaxSaleButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onMaxSaleButtonClicked); mIncreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onIncreaseButtonPressed); mIncreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased); mDecreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonPressed); @@ -191,21 +192,7 @@ namespace MWGui } // check if the merchant can afford this - int merchantgold; - if (mPtr.getTypeName() == typeid(ESM::NPC).name()) - { - MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->mBase->mNpdt52.mGold == -10) - merchantgold = ref->mBase->mNpdt12.mGold; - else - merchantgold = ref->mBase->mNpdt52.mGold; - } - else // ESM::Creature - { - MWWorld::LiveCellRef* ref = mPtr.get(); - merchantgold = ref->mBase->mData.mGold; - } - if (mCurrentBalance > 0 && merchantgold < mCurrentBalance) + if (mCurrentBalance > 0 && getMerchantGold() < mCurrentBalance) { // user notification MWBase::Environment::get().getWindowManager()-> @@ -293,6 +280,12 @@ namespace MWGui mWindowManager.removeGuiMode(GM_Barter); } + void TradeWindow::onMaxSaleButtonClicked(MyGUI::Widget* _sender) + { + mCurrentBalance = getMerchantGold(); + updateLabels(); + } + void TradeWindow::onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) { mBalanceButtonsState = BBS_Increase; @@ -341,22 +334,7 @@ namespace MWGui mTotalBalance->setCaption(boost::lexical_cast(-mCurrentBalance)); } - int merchantgold; - if (mPtr.getTypeName() == typeid(ESM::NPC).name()) - { - MWWorld::LiveCellRef* ref = mPtr.get(); - if (ref->mBase->mNpdt52.mGold == -10) - merchantgold = ref->mBase->mNpdt12.mGold; - else - merchantgold = ref->mBase->mNpdt52.mGold; - } - else // ESM::Creature - { - MWWorld::LiveCellRef* ref = mPtr.get(); - merchantgold = ref->mBase->mData.mGold; - } - - mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + boost::lexical_cast(merchantgold)); + mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + boost::lexical_cast(getMerchantGold())); } std::vector TradeWindow::getEquippedItems() @@ -468,4 +446,25 @@ namespace MWGui mWindowManager.removeGuiMode(GM_Barter); mWindowManager.removeGuiMode(GM_Dialogue); } + + int TradeWindow::getMerchantGold() + { + int merchantGold; + + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) + { + MWWorld::LiveCellRef* ref = mPtr.get(); + if (ref->mBase->mNpdt52.mGold == -10) + merchantGold = ref->mBase->mNpdt12.mGold; + else + merchantGold = ref->mBase->mNpdt52.mGold; + } + else // ESM::Creature + { + MWWorld::LiveCellRef* ref = mPtr.get(); + merchantGold = ref->mBase->mData.mGold; + } + + return merchantGold; + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index c1d31917b..ea749f5a2 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -74,6 +74,7 @@ namespace MWGui void onFilterChanged(MyGUI::Widget* _sender); void onOfferButtonClicked(MyGUI::Widget* _sender); void onCancelButtonClicked(MyGUI::Widget* _sender); + void onMaxSaleButtonClicked(MyGUI::Widget* _sender); void onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onBalanceButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); @@ -93,6 +94,9 @@ namespace MWGui void updateLabels(); virtual void onReferenceUnavailable(); + + private: + int getMerchantGold(); }; } From 215d45aaf7e83fdc1cd1b9957a3c0e53ac80c57a Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Mon, 4 Mar 2013 12:17:48 +0100 Subject: [PATCH 107/151] Make trade window's "max sale" button clickable The HBox widget above it was stealing the input events. --- files/mygui/openmw_trade_window.layout | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/files/mygui/openmw_trade_window.layout b/files/mygui/openmw_trade_window.layout index d38377f98..ecc794c92 100644 --- a/files/mygui/openmw_trade_window.layout +++ b/files/mygui/openmw_trade_window.layout @@ -51,10 +51,6 @@ - - - - @@ -66,6 +62,10 @@ + + + + From 48b3f1e0cf1e118480d795bf797d0c4fbacc8e2b Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 4 Mar 2013 12:08:35 +0000 Subject: [PATCH 108/151] Clean up. But still a little hacky --- apps/openmw/mwworld/physicssystem.cpp | 6 ++---- libs/openengine/bullet/physic.cpp | 4 ++++ libs/openengine/bullet/physic.hpp | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 90c090f59..316e57b78 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -110,7 +110,7 @@ namespace MWWorld float remainingTime = time; bool isInterior = !ptr.getCell()->isExterior(); Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1); - physicActor->mBody->translate(btVector3(0,0,1000)); + physicActor->enableCollisions(false); Ogre::Vector3 velocity; if(!gravity) @@ -147,7 +147,6 @@ namespace MWWorld // trace to where character would go if there were no obstructions newtrace(&trace, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, isInterior, engine); newPosition = trace.endpos; - //std::cout << newPosition.x << " "; remainingTime = remainingTime * (1.0f-trace.fraction); // check for obstructions @@ -191,8 +190,7 @@ namespace MWWorld } physicActor->setOnGround(onground); physicActor->setVerticalForce(!onground ? clippedVelocity.z - time*627.2f : 0.0f); - physicActor->mBody->translate(btVector3(0,0,-1000)); - //std::cout << position.x << " " << newPosition.x << " " << position.y << " " << newPosition.y << std::endl; + physicActor->enableCollisions(true); return newPosition; } }; diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index f993ce68e..677d75f33 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -37,6 +37,8 @@ namespace Physic Ogre::Quaternion inverse = mBoxRotation.Inverse(); mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w); mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map + //mBody->setCollisionFlags(COL_NOTHING); + //mBody->setMas } PhysicActor::~PhysicActor() @@ -50,6 +52,8 @@ namespace Physic void PhysicActor::enableCollisions(bool collision) { + if(collision && !collisionMode) mBody->translate(btVector3(0,0,-1000)); + if(!collision && collisionMode) mBody->translate(btVector3(0,0,1000)); collisionMode = collision; } diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 6a7150fca..e579e3546 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -129,10 +129,10 @@ namespace Physic void operator delete (void * Data) { _aligned_free (Data); } #endif - OEngine::Physic::RigidBody* mBody; private: - + + OEngine::Physic::RigidBody* mBody; Ogre::Vector3 mBoxScaledTranslation; btQuaternion mBoxRotationInverse; Ogre::Quaternion mBoxRotation; From 3384d92761a921562b7ec0b15444007ef11fd18e Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 4 Mar 2013 12:28:43 +0000 Subject: [PATCH 109/151] oups introduced a bug.. --- apps/openmw/mwscript/transformationextensions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 8222ef150..d86a6e348 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -119,15 +119,15 @@ namespace MWScript if (axis == "x") { - runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[0]).valueDegrees()); } else if (axis == "y") { - runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[1]).valueDegrees()); } else if (axis == "z") { - runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees()); + runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[2]).valueDegrees()); } else throw std::runtime_error ("invalid ration axis: " + axis); From 65081f5520b733b235b87a9b98e5f6afbb331962 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 4 Mar 2013 13:59:06 +0100 Subject: [PATCH 110/151] added variant class --- apps/opencs/view/world/vartypedelegate.hpp | 2 + components/CMakeLists.txt | 2 +- components/esm/defs.hpp | 12 - components/esm/loadglob.hpp | 1 + components/esm/loadgmst.hpp | 1 + components/esm/loadinfo.hpp | 1 + components/esm/variant.cpp | 256 ++++++++++++++++++++ components/esm/variant.hpp | 85 +++++++ components/esm/variantimp.cpp | 262 +++++++++++++++++++++ components/esm/variantimp.hpp | 179 ++++++++++++++ 10 files changed, 788 insertions(+), 13 deletions(-) create mode 100644 components/esm/variant.cpp create mode 100644 components/esm/variant.hpp create mode 100644 components/esm/variantimp.cpp create mode 100644 components/esm/variantimp.hpp diff --git a/apps/opencs/view/world/vartypedelegate.hpp b/apps/opencs/view/world/vartypedelegate.hpp index 621dd316b..c8493f029 100644 --- a/apps/opencs/view/world/vartypedelegate.hpp +++ b/apps/opencs/view/world/vartypedelegate.hpp @@ -1,6 +1,8 @@ #ifndef CSV_WORLD_VARTYPEDELEGATE_H #define CSV_WORLD_VARTYPEDELEGATE_H +#include + #include "enumdelegate.hpp" namespace CSVWorld diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 00342e2ac..0c75123cb 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -39,7 +39,7 @@ add_component_dir (esm loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat - loadweap records aipackage effectlist spelllist + loadweap records aipackage effectlist spelllist variant variantimp ) add_component_dir (misc diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 143d90034..bd86f9ba0 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -9,18 +9,6 @@ namespace ESM // Pixel color value. Standard four-byte rr,gg,bb,aa format. typedef int32_t Color; -enum VarType -{ - VT_Unknown, - VT_None, - VT_Short, // stored as a float, kinda - VT_Int, - VT_Long, // stored as a float - VT_Float, - VT_String, - VT_Ignored -}; - enum Specialization { SPC_Combat = 0, diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 6111648a6..96d2fcaf4 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -4,6 +4,7 @@ #include #include "defs.hpp" +#include "variant.hpp" namespace ESM { diff --git a/components/esm/loadgmst.hpp b/components/esm/loadgmst.hpp index f7aec5c76..12f212081 100644 --- a/components/esm/loadgmst.hpp +++ b/components/esm/loadgmst.hpp @@ -4,6 +4,7 @@ #include #include "defs.hpp" +#include "variant.hpp" namespace ESM { diff --git a/components/esm/loadinfo.hpp b/components/esm/loadinfo.hpp index f1decb9c6..ca08c3b55 100644 --- a/components/esm/loadinfo.hpp +++ b/components/esm/loadinfo.hpp @@ -5,6 +5,7 @@ #include #include "defs.hpp" +#include "variant.hpp" namespace ESM { diff --git a/components/esm/variant.cpp b/components/esm/variant.cpp new file mode 100644 index 000000000..bf8d2069b --- /dev/null +++ b/components/esm/variant.cpp @@ -0,0 +1,256 @@ +#include "variant.hpp" + +#include +#include + +#include "esmreader.hpp" +#include "variantimp.hpp" + +ESM::Variant::Variant() : mType (VT_None), mData (0) {} + +ESM::Variant::~Variant() +{ + delete mData; +} + +ESM::Variant& ESM::Variant::operator= (const Variant& variant) +{ + if (&variant!=this) + { + VariantDataBase *newData = variant.mData ? variant.mData->clone() : 0; + + delete mData; + + mType = variant.mType; + mData = newData; + } + + return *this; +} + +ESM::Variant::Variant (const Variant& variant) +: mType (variant.mType), mData (variant.mData ? variant.mData->clone() : 0) +{} + +ESM::VarType ESM::Variant::getType() const +{ + return mType; +} + +std::string ESM::Variant::toString() const +{ + if (!mData) + throw std::runtime_error ("can not convert empty variant to string"); + + return mData->getString(); +} + +int ESM::Variant::getInteger() const +{ + if (!mData) + throw std::runtime_error ("can not convert empty variant to integer"); + + return mData->getInteger(); +} + +float ESM::Variant::getFloat() const +{ + if (!mData) + throw std::runtime_error ("can not convert empty variant to float"); + + return mData->getFloat(); +} + +void ESM::Variant::read (ESMReader& esm, Format format) +{ + // type + VarType type = VT_Unknown; + + if (format==Format_Global) + { + std::string typeId = esm.getHNString ("FNAM"); + + if (typeId == "s") + type = VT_Short; + else if (typeId == "l") + type = VT_Long; + else if (typeId == "f") + type = VT_Float; + else + esm.fail ("illegal global variable type " + typeId); + } + else // GMST + { + esm.getSubName(); + NAME name = esm.retSubName(); + + if (name=="STRV") + { + type = VT_String; + } + else if (name=="INTV") + { + type = VT_Int; + } + else if (name=="FLTV") + { + type = VT_Float; + } + else + esm.fail ("invalid subrecord: " + name.toString()); + } + + setType (type); + + // data + if (mData) + mData->read (esm, format, mType); +} + +void ESM::Variant::write (ESMWriter& esm, Format format) const +{ + if (mType==VT_Unknown) + { + throw std::runtime_error ("can not serialise variant of unknown type"); + } + else if (mType==VT_None) + { + if (format==Format_Global) + throw std::runtime_error ("can not serialise variant of type none to global format"); + + // nothing to do here for GMST format + } + else + mData->write (esm, format, mType); +} + +void ESM::Variant::write (std::ostream& stream) const +{ + switch (mType) + { + case VT_Unknown: + + stream << "variant unknown"; + break; + + case VT_None: + + stream << "variant none"; + break; + + case VT_Short: + + stream << "variant short: " << mData->getInteger(); + break; + + case VT_Int: + + stream << "variant int: " << mData->getInteger(); + break; + + case VT_Long: + + stream << "variant long: " << mData->getInteger(); + break; + + case VT_Float: + + stream << "variant float: " << mData->getFloat(); + break; + + case VT_String: + + stream << "variant string: \"" << mData->getString() << "\2"; + break; + } +} + +void ESM::Variant::setType (VarType type) +{ + if (type!=mType) + { + VariantDataBase *newData = 0; + + switch (type) + { + case VT_Unknown: + case VT_None: + + break; // no data + + case VT_Short: + case VT_Int: + case VT_Long: + + newData = new VariantIntegerData (mData); + break; + + case VT_Float: + + newData = new VariantFloatData (mData); + break; + + case VT_String: + + newData = new VariantStringData (mData); + break; + } + + delete mData; + mData = newData; + mType = type; + } +} + +void ESM::Variant::setString (const std::string& value) +{ + if (!mData) + throw std::runtime_error ("can not assign string to empty variant"); + + mData->setString (value); +} + +void ESM::Variant::setInteger (int value) +{ + if (!mData) + throw std::runtime_error ("can not assign integer to empty variant"); + + mData->setInteger (value); +} + +void ESM::Variant::setFloat (float value) +{ + if (!mData) + throw std::runtime_error ("can not assign float to empty variant"); + + mData->setFloat (value); +} + +bool ESM::Variant::isEqual (const Variant& value) const +{ + if (mType!=value.mType) + return false; + + if (!mData) + return true; + + assert (value.mData); + + return mData->isEqual (*value.mData); +} + +std::ostream& ESM::operator<< (std::ostream& stream, const Variant& value) +{ + value.write (stream); + return stream; +} + +bool ESM::operator== (const Variant& left, const Variant& right) +{ + return left.isEqual (right); +} + +bool ESM::operator!= (const Variant& left, const Variant& right) +{ + return !(left==right); +} \ No newline at end of file diff --git a/components/esm/variant.hpp b/components/esm/variant.hpp new file mode 100644 index 000000000..b50bb1d2f --- /dev/null +++ b/components/esm/variant.hpp @@ -0,0 +1,85 @@ +#ifndef OPENMW_ESM_VARIANT_H +#define OPENMW_ESM_VARIANT_H + +#include +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + enum VarType + { + VT_Unknown, + VT_None, + VT_Short, // stored as a float, kinda + VT_Int, + VT_Long, // stored as a float + VT_Float, + VT_String + }; + + class VariantDataBase; + + class Variant + { + VarType mType; + VariantDataBase *mData; + + public: + + enum Format + { + Format_Global, + Format_Gmst + }; + + Variant(); + + ~Variant(); + + Variant& operator= (const Variant& variant); + + Variant (const Variant& variant); + + VarType getType() const; + + std::string toString() const; + ///< Will throw an exception, if value can not be represented as a string. + + int getInteger() const; + ///< Will throw an exception, if value can not be represented as an integer (implicit + /// casting of float values is permitted). + + float getFloat() const; + ///< Will throw an exception, if value can not be represented as a float value. + + void read (ESMReader& esm, Format format); + + void write (ESMWriter& esm, Format format) const; + + void write (std::ostream& stream) const; + ///< Write in text format. + + void setType (VarType type); + + void setString (const std::string& value); + ///< Will throw an exception, if type is not compatible with string. + + void setInteger (int value); + ///< Will throw an exception, if type is not compatible with integer. + + void setFloat (float value); + ///< Will throw an exception, if type is not compatible with float. + + bool isEqual (const Variant& value) const; + }; + + std::ostream& operator<<(std::ostream& stream, const Variant& value); + + bool operator== (const Variant& left, const Variant& right); + bool operator!= (const Variant& left, const Variant& right); +} + +#endif \ No newline at end of file diff --git a/components/esm/variantimp.cpp b/components/esm/variantimp.cpp new file mode 100644 index 000000000..e99cc50b5 --- /dev/null +++ b/components/esm/variantimp.cpp @@ -0,0 +1,262 @@ + +#include "variantimp.hpp" + +#include + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +ESM::VariantDataBase::~VariantDataBase() {} + +std::string ESM::VariantDataBase::getString (bool default_) const +{ + if (default_) + return ""; + + throw std::runtime_error ("can not convert variant to string"); +} + +int ESM::VariantDataBase::getInteger (bool default_) const +{ + if (default_) + return 0; + + throw std::runtime_error ("can not convert variant to integer"); +} + +float ESM::VariantDataBase::getFloat (bool default_) const +{ + if (default_) + return 0; + + throw std::runtime_error ("can not convert variant to float"); +} + +void ESM::VariantDataBase::setString (const std::string& value) +{ + throw std::runtime_error ("conversion of string to variant not possible"); +} + +void ESM::VariantDataBase::setInteger (int value) +{ + throw std::runtime_error ("conversion of integer to variant not possible"); +} + +void ESM::VariantDataBase::setFloat (float value) +{ + throw std::runtime_error ("conversion of float to variant not possible"); +} + + + +ESM::VariantStringData::VariantStringData (const VariantDataBase *data) +{ + if (data) + mValue = data->getString (true); +} + +ESM::VariantDataBase *ESM::VariantStringData::clone() const +{ + return new VariantStringData (*this); +} + +std::string ESM::VariantStringData::getString (bool default_) const +{ + return mValue; +} + +void ESM::VariantStringData::setString (const std::string& value) +{ + mValue = value; +} + +void ESM::VariantStringData::read (ESMReader& esm, Variant::Format format, VarType type) +{ + if (type!=VT_String) + throw std::logic_error ("not a string type"); + + if (format==Variant::Format_Global) + esm.fail ("global variables of type string not supported"); + + // GMST + mValue = esm.getHString(); +} + +void ESM::VariantStringData::write (ESMWriter& esm, Variant::Format format, VarType type) const +{ + if (type!=VT_String) + throw std::logic_error ("not a string type"); + + if (format==Variant::Format_Global) + throw std::runtime_error ("global variables of type string not supported"); + + // GMST + esm.writeHNString ("STRV", mValue); +} + +bool ESM::VariantStringData::isEqual (const VariantDataBase& value) const +{ + return dynamic_cast (value).mValue==mValue; +} + + + +ESM::VariantIntegerData::VariantIntegerData (const VariantDataBase *data) : mValue (0) +{ + if (data) + mValue = data->getInteger (true); +} + +ESM::VariantDataBase *ESM::VariantIntegerData::clone() const +{ + return new VariantIntegerData (*this); +} + +int ESM::VariantIntegerData::getInteger (bool default_) const +{ + return mValue; +} + +float ESM::VariantIntegerData::getFloat (bool default_) const +{ + return mValue; +} + +void ESM::VariantIntegerData::setInteger (int value) +{ + mValue = value; +} + +void ESM::VariantIntegerData::setFloat (float value) +{ + mValue = static_cast (value); +} + +void ESM::VariantIntegerData::read (ESMReader& esm, Variant::Format format, VarType type) +{ + if (type!=VT_Short && type!=VT_Long && type!=VT_Int) + throw std::logic_error ("not an integer type"); + + if (format==Variant::Format_Global) + { + float value; + esm.getHNT (value, "FLTV"); + + if (type==VT_Short) + { + if (value!=value) + mValue = 0; // nan + else + mValue = static_cast (value); + } + else if (type==VT_Long) + mValue = static_cast (value); + else + esm.fail ("unsupported global variable integer type"); + } + else // GMST + { + if (type==VT_Int) + esm.fail ("unsupported global variable integer type"); + + esm.getHT (mValue); + } +} + +void ESM::VariantIntegerData::write (ESMWriter& esm, Variant::Format format, VarType type) const +{ + if (type!=VT_Short && type!=VT_Long && type!=VT_Int) + throw std::logic_error ("not an integer type"); + + if (format==Variant::Format_Global) + { + if (type==VT_Short || type==VT_Long) + { + float value = mValue; + esm.writeHNString ("FNAM", type==VT_Short ? "s" : "l"); + esm.writeHNT ("FLTV", value); + } + else + throw std::runtime_error ("unsupported global variable integer type"); + } + else // GMST + { + if (type==VT_Int) + throw std::runtime_error ("unsupported global variable integer type"); + + esm.writeHNT ("INTV", mValue); + } +} + +bool ESM::VariantIntegerData::isEqual (const VariantDataBase& value) const +{ + return dynamic_cast (value).mValue==mValue; +} + + +ESM::VariantFloatData::VariantFloatData (const VariantDataBase *data) : mValue (0) +{ + if (data) + mValue = data->getFloat (true); +} + +ESM::VariantDataBase *ESM::VariantFloatData::clone() const +{ + return new VariantFloatData (*this); +} + +int ESM::VariantFloatData::getInteger (bool default_) const +{ + return static_cast (mValue); +} + +float ESM::VariantFloatData::getFloat (bool default_) const +{ + return mValue; +} + +void ESM::VariantFloatData::setInteger (int value) +{ + mValue = value; +} + +void ESM::VariantFloatData::setFloat (float value) +{ + mValue = value; +} + +void ESM::VariantFloatData::read (ESMReader& esm, Variant::Format format, VarType type) +{ + if (type!=VT_Float) + throw std::logic_error ("not a float type"); + + if (format==Variant::Format_Global) + { + esm.getHNT (mValue, "FLTV"); + } + else // GMST + { + esm.getHT (mValue); + } +} + +void ESM::VariantFloatData::write (ESMWriter& esm, Variant::Format format, VarType type) const +{ + if (type!=VT_Float) + throw std::logic_error ("not a float type"); + + if (format==Variant::Format_Global) + { + esm.writeHNString ("FNAM", "f"); + esm.writeHNT ("FLTV", mValue); + } + else // GMST + { + esm.writeHNT ("INTV", mValue); + } +} + +bool ESM::VariantFloatData::isEqual (const VariantDataBase& value) const +{ + return dynamic_cast (value).mValue==mValue; +} \ No newline at end of file diff --git a/components/esm/variantimp.hpp b/components/esm/variantimp.hpp new file mode 100644 index 000000000..1dc20c21f --- /dev/null +++ b/components/esm/variantimp.hpp @@ -0,0 +1,179 @@ +#ifndef OPENMW_ESM_VARIANTIMP_H +#define OPENMW_ESM_VARIANTIMP_H + +#include + +#include "variant.hpp" + +namespace ESM +{ + class VariantDataBase + { + public: + + virtual ~VariantDataBase(); + + virtual VariantDataBase *clone() const = 0; + + virtual std::string getString (bool default_ = false) const; + ///< Will throw an exception, if value can not be represented as a string. + /// + /// \note Numeric values are not converted to strings. + /// + /// \param default_ Return a default value instead of throwing an exception. + /// + /// Default-implementation: throw an exception. + + virtual int getInteger (bool default_ = false) const; + ///< Will throw an exception, if value can not be represented as an integer (implicit + /// casting of float values is permitted). + /// + /// \param default_ Return a default value instead of throwing an exception. + /// + /// Default-implementation: throw an exception. + + virtual float getFloat (bool default_ = false) const; + ///< Will throw an exception, if value can not be represented as a float value. + /// + /// \param default_ Return a default value instead of throwing an exception. + /// + /// Default-implementation: throw an exception. + + virtual void setString (const std::string& value); + ///< Will throw an exception, if type is not compatible with string. + /// + /// Default-implementation: throw an exception. + + virtual void setInteger (int value); + ///< Will throw an exception, if type is not compatible with integer. + /// + /// Default-implementation: throw an exception. + + virtual void setFloat (float value); + ///< Will throw an exception, if type is not compatible with float. + /// + /// Default-implementation: throw an exception. + + virtual void read (ESMReader& esm, Variant::Format format, VarType type) = 0; + ///< If \a type is not supported by \a format, an exception is thrown via ESMReader::fail + + virtual void write (ESMWriter& esm, Variant::Format format, VarType type) const = 0; + ///< If \a type is not supported by \a format, an exception is thrown. + + virtual bool isEqual (const VariantDataBase& value) const = 0; + ///< If the (C++) type of \a value does not match the type of *this, an exception is thrown. + + }; + + class VariantStringData : public VariantDataBase + { + std::string mValue; + + public: + + VariantStringData (const VariantDataBase *data = 0); + ///< Calling the constructor with an incompatible data type will result in a silent + /// default initialisation. + + virtual VariantDataBase *clone() const; + + virtual std::string getString (bool default_ = false) const; + ///< Will throw an exception, if value can not be represented as a string. + /// + /// \note Numeric values are not converted to strings. + /// + /// \param default_ Return a default value instead of throwing an exception. + + virtual void setString (const std::string& value); + ///< Will throw an exception, if type is not compatible with string. + + virtual void read (ESMReader& esm, Variant::Format format, VarType type); + ///< If \a type is not supported by \a format, an exception is thrown via ESMReader::fail + + virtual void write (ESMWriter& esm, Variant::Format format, VarType type) const; + ///< If \a type is not supported by \a format, an exception is thrown. + + virtual bool isEqual (const VariantDataBase& value) const; + ///< If the (C++) type of \a value does not match the type of *this, an exception is thrown. + }; + + class VariantIntegerData : public VariantDataBase + { + int mValue; + + public: + + VariantIntegerData (const VariantDataBase *data = 0); + ///< Calling the constructor with an incompatible data type will result in a silent + /// default initialisation. + + virtual VariantDataBase *clone() const; + + virtual int getInteger (bool default_ = false) const; + ///< Will throw an exception, if value can not be represented as an integer (implicit + /// casting of float values is permitted). + /// + /// \param default_ Return a default value instead of throwing an exception. + + virtual float getFloat (bool default_ = false) const; + ///< Will throw an exception, if value can not be represented as a float value. + /// + /// \param default_ Return a default value instead of throwing an exception. + + virtual void setInteger (int value); + ///< Will throw an exception, if type is not compatible with integer. + + virtual void setFloat (float value); + ///< Will throw an exception, if type is not compatible with float. + + virtual void read (ESMReader& esm, Variant::Format format, VarType type); + ///< If \a type is not supported by \a format, an exception is thrown via ESMReader::fail + + virtual void write (ESMWriter& esm, Variant::Format format, VarType type) const; + ///< If \a type is not supported by \a format, an exception is thrown. + + virtual bool isEqual (const VariantDataBase& value) const; + ///< If the (C++) type of \a value does not match the type of *this, an exception is thrown. + }; + + class VariantFloatData : public VariantDataBase + { + float mValue; + + public: + + VariantFloatData (const VariantDataBase *data = 0); + ///< Calling the constructor with an incompatible data type will result in a silent + /// default initialisation. + + virtual VariantDataBase *clone() const; + + virtual int getInteger (bool default_ = false) const; + ///< Will throw an exception, if value can not be represented as an integer (implicit + /// casting of float values is permitted). + /// + /// \param default_ Return a default value instead of throwing an exception. + + virtual float getFloat (bool default_ = false) const; + ///< Will throw an exception, if value can not be represented as a float value. + /// + /// \param default_ Return a default value instead of throwing an exception. + + virtual void setInteger (int value); + ///< Will throw an exception, if type is not compatible with integer. + + virtual void setFloat (float value); + ///< Will throw an exception, if type is not compatible with float. + + virtual void read (ESMReader& esm, Variant::Format format, VarType type); + ///< If \a type is not supported by \a format, an exception is thrown via ESMReader::fail + + virtual void write (ESMWriter& esm, Variant::Format format, VarType type) const; + ///< If \a type is not supported by \a format, an exception is thrown. + + virtual bool isEqual (const VariantDataBase& value) const; + ///< If the (C++) type of \a value does not match the type of *this, an exception is thrown. + }; +} + +#endif From a1ac20c6f398ef38ff2797a6ab0ba6ed264c0e2e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 4 Mar 2013 14:32:59 +0100 Subject: [PATCH 111/151] changed global variable records to new variant type --- apps/esmtool/record.cpp | 4 +-- apps/opencs/model/doc/document.cpp | 12 ++++--- apps/opencs/model/world/columns.hpp | 4 +-- apps/openmw/mwworld/globals.cpp | 11 +++---- components/esm/loadglob.cpp | 49 ++++------------------------- components/esm/loadglob.hpp | 4 +-- 6 files changed, 22 insertions(+), 62 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index a732f1938..929201417 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -713,9 +713,7 @@ void Record::print() template<> void Record::print() { - // nothing to print (well, nothing that's correct anyway) - std::cout << " Type: " << mData.mType << std::endl; - std::cout << " Value: " << mData.mValue << std::endl; + std::cout << " " << mData.mValue << std::endl; } template<> diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index b361577be..f6df1f499 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -154,8 +154,7 @@ void CSMDoc::Document::addOptionalGlobals() { ESM::Global global; global.mId = sGlobals[i]; - global.mType = ESM::VT_Int; - global.mValue = 0; + global.mValue.setType (ESM::VT_Int); addOptionalGlobal (global); } } @@ -192,9 +191,14 @@ void CSMDoc::Document::createBase() for (int i=0; sGlobals[i]; ++i) { ESM::Global record; + record.mId = sGlobals[i]; - record.mValue = i==0 ? 1 : 0; - record.mType = ESM::VT_Float; + + record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Int); + + if (i==0) + record.mValue.setInteger (1); + getData().getGlobals().add (record); } } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 2d81a24e9..8855edc46 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -12,13 +12,13 @@ namespace CSMWorld virtual QVariant get (const Record& record) const { - return record.get().mValue; + return record.get().mValue.getFloat(); } virtual void set (Record& record, const QVariant& data) { ESXRecordT record2 = record.get(); - record2.mValue = data.toFloat(); + record2.mValue.setFloat (data.toFloat()); record.setModified (record2); } diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp index 8742dd892..9e57910ee 100644 --- a/apps/openmw/mwworld/globals.cpp +++ b/apps/openmw/mwworld/globals.cpp @@ -47,27 +47,24 @@ namespace MWWorld char type = ' '; Data value; - switch (iter->mType) + switch (iter->mValue.getType()) { case ESM::VT_Short: type = 's'; - value.mShort = *reinterpret_cast ( - &iter->mValue); + value.mShort = iter->mValue.getInteger(); break; case ESM::VT_Long: type = 'l'; - value.mLong = *reinterpret_cast ( - &iter->mValue); + value.mLong = iter->mValue.getInteger(); break; case ESM::VT_Float: type = 'f'; - value.mFloat = *reinterpret_cast ( - &iter->mValue); + value.mFloat = iter->mValue.getFloat(); break; default: diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index 9e20578ce..0cb6d0a41 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -6,60 +6,23 @@ namespace ESM { -void Global::load(ESMReader &esm) -{ - std::string tmp = esm.getHNString("FNAM"); - if (tmp == "s") - mType = VT_Short; - else if (tmp == "l") - mType = VT_Long; - else if (tmp == "f") - mType = VT_Float; - else - esm.fail("Illegal global variable type " + tmp); - - // Note: Both floats and longs are represented as floats. - esm.getHNT(mValue, "FLTV"); - - if (mType==VT_Short) + void Global::load(ESMReader &esm) { - if (mValue!=mValue) - mValue = 0; // nan - else - mValue = static_cast (mValue); + mValue.read (esm, ESM::Variant::Format_Global); } -} -void Global::save(ESMWriter &esm) -{ - switch(mType) + void Global::save(ESMWriter &esm) { - case VT_Short: - esm.writeHNString("FNAM", "s"); - break; - - case VT_Long: - esm.writeHNString("FNAM", "l"); - break; - - case VT_Float: - esm.writeHNString("FNAM", "f"); - break; - - default: - return; + mValue.write (esm, ESM::Variant::Format_Global); } - esm.writeHNT("FLTV", mValue); -} void Global::blank() { - mValue = 0; - mType = VT_Float; + mValue.setType (ESM::VT_None); } bool operator== (const Global& left, const Global& right) { - return left.mId==right.mId && left.mValue==right.mValue && left.mType==right.mType; + return left.mId==right.mId && left.mValue==right.mValue; } } diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 96d2fcaf4..72e16c0ce 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -3,7 +3,6 @@ #include -#include "defs.hpp" #include "variant.hpp" namespace ESM @@ -19,8 +18,7 @@ class ESMWriter; struct Global { std::string mId; - float mValue; - VarType mType; + Variant mValue; void load(ESMReader &esm); void save(ESMWriter &esm); From cab5315a8e6ff5c785930787051e14084db5cc20 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 4 Mar 2013 16:28:20 +0100 Subject: [PATCH 112/151] Disable mipmaps generation --- apps/openmw/mwrender/renderingmanager.cpp | 3 ++- files/settings-default.cfg | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 382ec6557..3f559c9fd 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -100,7 +100,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mFactory->loadAllFiles(); // Set default mipmap level (NB some APIs ignore this) - TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General")); + // Mipmap generation is currently disabled because it causes issues on Intel/AMD + //TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General")); // Set default texture filtering options TextureFilterOptions tfo; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 6ff7fb432..69aa20883 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -52,7 +52,8 @@ texture filtering = anisotropic anisotropy = 4 # Number of texture mipmaps to generate -num mipmaps = 5 +# This setting is currently ignored due to mipmap generation problems on Intel/AMD +#num mipmaps = 5 shader mode = From ca707aa65f6d16126cb33f63f6096691af61531a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 4 Mar 2013 16:57:00 +0100 Subject: [PATCH 113/151] Transparency should be evaluated per subentity, not per NIF --- apps/openmw/mwrender/activatoranimation.cpp | 19 +++-------- apps/openmw/mwrender/creatureanimation.cpp | 18 ++--------- apps/openmw/mwrender/npcanimation.cpp | 36 ++++----------------- apps/openmw/mwrender/objects.cpp | 30 +++++++---------- 4 files changed, 24 insertions(+), 79 deletions(-) diff --git a/apps/openmw/mwrender/activatoranimation.cpp b/apps/openmw/mwrender/activatoranimation.cpp index 0dc16ecb6..961c07003 100644 --- a/apps/openmw/mwrender/activatoranimation.cpp +++ b/apps/openmw/mwrender/activatoranimation.cpp @@ -30,24 +30,13 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) { Ogre::Entity *ent = mEntityList.mEntities[i]; - bool transparent = false; - for(unsigned int j=0;!transparent && j < ent->getNumSubEntities(); ++j) + for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) { - Ogre::MaterialPtr mat = ent->getSubEntity(j)->getMaterial(); - Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); - while(!transparent && techIt.hasMoreElements()) - { - Ogre::Technique* tech = techIt.getNext(); - Ogre::Technique::PassIterator passIt = tech->getPassIterator(); - while(!transparent && passIt.hasMoreElements()) - { - Ogre::Pass* pass = passIt.getNext(); - transparent = pass->isTransparent(); - } - } + Ogre::SubEntity* subEnt = ent->getSubEntity(j); + subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } + ent->setVisibilityFlags(RV_Misc); - ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } setAnimationSource(mesh); } diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 73bb80547..22f84ee01 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -31,23 +31,11 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) Ogre::Entity *ent = mEntityList.mEntities[i]; ent->setVisibilityFlags(RV_Actors); - bool transparent = false; - for(unsigned int j=0;!transparent && j < ent->getNumSubEntities(); ++j) + for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) { - Ogre::MaterialPtr mat = ent->getSubEntity(j)->getMaterial(); - Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); - while(!transparent && techIt.hasMoreElements()) - { - Ogre::Technique* tech = techIt.getNext(); - Ogre::Technique::PassIterator passIt = tech->getPassIterator(); - while(!transparent && passIt.hasMoreElements()) - { - Ogre::Pass* pass = passIt.getNext(); - transparent = pass->isTransparent(); - } - } + Ogre::SubEntity* subEnt = ent->getSubEntity(j); + subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } - ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } std::vector names; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 33addd284..a7d5c22af 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -107,23 +107,11 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor if (mVisibilityFlags != 0) base->setVisibilityFlags(mVisibilityFlags); - bool transparent = false; - for(unsigned int j=0;!transparent && j < base->getNumSubEntities();++j) + for(unsigned int j=0; j < base->getNumSubEntities(); ++j) { - Ogre::MaterialPtr mat = base->getSubEntity(j)->getMaterial(); - Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); - while(!transparent && techIt.hasMoreElements()) - { - Ogre::Technique* tech = techIt.getNext(); - Ogre::Technique::PassIterator passIt = tech->getPassIterator(); - while(!transparent && passIt.hasMoreElements()) - { - Ogre::Pass* pass = passIt.getNext(); - transparent = pass->isTransparent(); - } - } + Ogre::SubEntity* subEnt = base->getSubEntity(j); + subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } - base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } std::vector skelnames(1, smodel); @@ -326,23 +314,11 @@ NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int if (mVisibilityFlags != 0) parts[i]->setVisibilityFlags(mVisibilityFlags); - bool transparent = false; - for(unsigned int j=0;!transparent && j < parts[i]->getNumSubEntities();++j) + for(unsigned int j=0; j < parts[i]->getNumSubEntities(); ++j) { - Ogre::MaterialPtr mat = parts[i]->getSubEntity(j)->getMaterial(); - Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); - while(!transparent && techIt.hasMoreElements()) - { - Ogre::Technique* tech = techIt.getNext(); - Ogre::Technique::PassIterator passIt = tech->getPassIterator(); - while(!transparent && passIt.hasMoreElements()) - { - Ogre::Pass* pass = passIt.getNext(); - transparent = pass->isTransparent(); - } - } + Ogre::SubEntity* subEnt = parts[i]->getSubEntity(j); + subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } - parts[i]->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } if(entities.mSkelBase) { diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 525dcdcc4..cb1dfa75b 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -129,36 +129,28 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; mBounds[ptr.getCell()].merge(bounds); - bool transparent = false; - for(size_t i = 0;!transparent && i < entities.mEntities.size();i++) + bool anyTransparency = false; + for(size_t i = 0;!anyTransparency && i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; - for(unsigned int i=0;!transparent && i < ent->getNumSubEntities(); ++i) + for(unsigned int i=0;!anyTransparency && i < ent->getNumSubEntities(); ++i) { - Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial(); - Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); - while(!transparent && techIt.hasMoreElements()) - { - Ogre::Technique* tech = techIt.getNext(); - Ogre::Technique::PassIterator passIt = tech->getPassIterator(); - while(!transparent && passIt.hasMoreElements()) - { - Ogre::Pass* pass = passIt.getNext(); - transparent = pass->isTransparent(); - } - } + anyTransparency = ent->getSubEntity(i)->getMaterial()->isTransparent(); } } - if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent) + if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || anyTransparency) { for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; - + for(unsigned int i=0; i < ent->getNumSubEntities(); ++i) + { + Ogre::SubEntity* subEnt = ent->getSubEntity(i); + subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); + } ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); - ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } } else @@ -203,7 +195,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool sg->setCastShadows(true); - sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); + sg->setRenderQueueGroup(RQG_Main); std::vector::reverse_iterator iter = entities.mEntities.rbegin(); while(iter != entities.mEntities.rend()) From d5c6c221c102699e548256721aa6ac4d06f9dae9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 4 Mar 2013 17:28:01 +0100 Subject: [PATCH 114/151] Books/scrolls: Fix the take button incorrectly showing --- apps/openmw/mwgui/inventorywindow.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 40771af16..4a0234644 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -160,11 +160,8 @@ namespace MWGui // the "Take" button should not be visible. // NOTE: the take button is "reset" when the window opens, so we can safely do the following // without screwing up future book windows - if (mDragAndDrop->mDraggedFrom == this) - { - mWindowManager.getBookWindow()->setTakeButtonShow(false); - mWindowManager.getScrollWindow()->setTakeButtonShow(false); - } + mWindowManager.getBookWindow()->setTakeButtonShow(false); + mWindowManager.getScrollWindow()->setTakeButtonShow(false); mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); From 9f0bd95ef1122883e1e8e5e9542c9d93ba9ed7f5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 4 Mar 2013 17:57:35 +0100 Subject: [PATCH 115/151] Added BM trees to transparency overrides --- files/transparency-overrides.cfg | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/files/transparency-overrides.cfg b/files/transparency-overrides.cfg index 299792be1..65f9b477a 100644 --- a/files/transparency-overrides.cfg +++ b/files/transparency-overrides.cfg @@ -572,3 +572,52 @@ [textures\tx_velothi_glyph00.dds] alphaRejectValue = 128 + + + +# Bloodmoon + +[textures\tx_bm_holly_01.dds] + alphaRejectValue = 128 + +[textures\tx_bm_holly_snow_01.dds] + alphaRejectValue = 128 + +[textures\tx_bm_pine_04a.dds] + alphaRejectValue = 128 + +[textures\tx_bm_pine_03a.dds] + alphaRejectValue = 128 + +[textures\tx_bm_pine_02a.dds] + alphaRejectValue = 128 + +[textures\tx_bm_pine_01a.dds] + alphaRejectValue = 128 + +[textures\tx_bm_shrub_02.dds] + alphaRejectValue = 128 + +[textures\tx_bm_shrub_01.dds] + alphaRejectValue = 128 + +[textures\tx_bm_snow_pine_01a.dds] + alphaRejectValue = 128 + +[textures\tx_bm_snow_pine_02a.dds] + alphaRejectValue = 128 + +[textures\tx_bm_snow_pine_03a.dds] + alphaRejectValue = 128 + +[textures\tx_bm_snow_pine_04a.dds] + alphaRejectValue = 128 + +[textures\tx_bm_deadpine_01.dds] + alphaRejectValue = 128 + +[textures\tx_bm_shrub_snow_02.dds] + alphaRejectValue = 128 + +[textures\tx_bm_s_deadpine_01.dds] + alphaRejectValue = 128 From 2f14f26b96cbe5c0cf79c9a35840bcde862a9966 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 4 Mar 2013 10:35:13 -0800 Subject: [PATCH 116/151] Use the full unique mesh name for the material instead of the NIF name --- components/nifogre/ogrenifloader.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 44a8e48cd..6f7afee43 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -993,7 +993,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } } - std::string matname = NIFMaterialLoader::getMaterial(shape, mName, mGroup, + std::string matname = NIFMaterialLoader::getMaterial(shape, mesh->getName(), mGroup, texprop, matprop, alphaprop, vertprop, zprop, specprop); if(matname.length() > 0) @@ -1001,12 +1001,12 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } bool findTriShape(Ogre::Mesh *mesh, const Nif::Node *node, - const Nif::NiTexturingProperty *texprop=NULL, - const Nif::NiMaterialProperty *matprop=NULL, - const Nif::NiAlphaProperty *alphaprop=NULL, - const Nif::NiVertexColorProperty *vertprop=NULL, - const Nif::NiZBufferProperty *zprop=NULL, - const Nif::NiSpecularProperty *specprop=NULL) + const Nif::NiTexturingProperty *texprop, + const Nif::NiMaterialProperty *matprop, + const Nif::NiAlphaProperty *alphaprop, + const Nif::NiVertexColorProperty *vertprop, + const Nif::NiZBufferProperty *zprop, + const Nif::NiSpecularProperty *specprop) { // Scan the property list for material information const Nif::PropertyList &proplist = node->props; @@ -1081,7 +1081,7 @@ public: } const Nif::Node *node = dynamic_cast(nif->getRecord(0)); - findTriShape(mesh, node); + findTriShape(mesh, node, NULL, NULL, NULL, NULL, NULL, NULL); } void createMeshes(const Nif::Node *node, MeshInfoList &meshes, int flags=0) From fb5213a754cab17c457c649bdb089f96ed519424 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 5 Mar 2013 02:17:28 +0100 Subject: [PATCH 117/151] Made the GraphicsPage use a .ui file and added support for custom res --- apps/launcher/graphicspage.cpp | 137 ++++++++++++++++--------------- apps/launcher/graphicspage.hpp | 21 ++--- apps/launcher/ui/graphicspage.ui | 22 +++-- 3 files changed, 92 insertions(+), 88 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 741aacc9d..590504354 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -30,48 +30,17 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &g , mGraphicsSettings(graphicsSetting) , QWidget(parent) { - QGroupBox *rendererGroup = new QGroupBox(tr("Renderer"), this); + setupUi(this); - QLabel *rendererLabel = new QLabel(tr("Rendering Subsystem:"), rendererGroup); - mRendererComboBox = new QComboBox(rendererGroup); + // Set the maximum res we can set in windowed mode + QRect res = QApplication::desktop()->screenGeometry(); + customWidthSpinBox->setMaximum(res.width()); + customHeightSpinBox->setMaximum(res.height()); - // Layout for the combobox and label - QGridLayout *renderSystemLayout = new QGridLayout(); - renderSystemLayout->addWidget(rendererLabel, 0, 0, 1, 1); - renderSystemLayout->addWidget(mRendererComboBox, 0, 1, 1, 1); + connect(rendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&))); + connect(fullScreenCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotFullScreenChanged(int))); + connect(standardRadioButton, SIGNAL(toggled(bool)), this, SLOT(slotStandardToggled(bool))); - // Display - QGroupBox *displayGroup = new QGroupBox(tr("Display"), this); - - mVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), displayGroup); - mFullScreenCheckBox = new QCheckBox(tr("Full Screen"), displayGroup); - - QLabel *antiAliasingLabel = new QLabel(tr("Antialiasing:"), displayGroup); - QLabel *resolutionLabel = new QLabel(tr("Resolution:"), displayGroup); - - mResolutionComboBox = new QComboBox(displayGroup); - mAntiAliasingComboBox = new QComboBox(displayGroup); - - QVBoxLayout *rendererGroupLayout = new QVBoxLayout(rendererGroup); - rendererGroupLayout->addLayout(renderSystemLayout); - - QGridLayout *displayGroupLayout = new QGridLayout(displayGroup); - displayGroupLayout->addWidget(mVSyncCheckBox, 0, 0, 1, 1); - displayGroupLayout->addWidget(mFullScreenCheckBox, 1, 0, 1, 1); - displayGroupLayout->addWidget(antiAliasingLabel, 2, 0, 1, 1); - displayGroupLayout->addWidget(mAntiAliasingComboBox, 2, 1, 1, 1); - displayGroupLayout->addWidget(resolutionLabel, 3, 0, 1, 1); - displayGroupLayout->addWidget(mResolutionComboBox, 3, 1, 1, 1); - - // Layout for the whole page - QVBoxLayout *pageLayout = new QVBoxLayout(this); - QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding); - - pageLayout->addWidget(rendererGroup); - pageLayout->addWidget(displayGroup); - pageLayout->addItem(vSpacer1); - - connect(mRendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&))); } bool GraphicsPage::setupOgre() @@ -138,7 +107,7 @@ bool GraphicsPage::setupOgre() for (Ogre::RenderSystemList::const_iterator r = renderers.begin(); r != renderers.end(); ++r) { mSelectedRenderSystem = *r; - mRendererComboBox->addItem((*r)->getName().c_str()); + rendererComboBox->addItem((*r)->getName().c_str()); } QString openGLName = QString("OpenGL Rendering Subsystem"); @@ -160,21 +129,21 @@ bool GraphicsPage::setupOgre() } // Now fill the GUI elements - int index = mRendererComboBox->findText(mGraphicsSettings.value(QString("Video/render system"))); + int index = rendererComboBox->findText(mGraphicsSettings.value(QString("Video/render system"))); if ( index != -1) { - mRendererComboBox->setCurrentIndex(index); + rendererComboBox->setCurrentIndex(index); } else { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - mRendererComboBox->setCurrentIndex(mRendererComboBox->findText(direct3DName)); + rendererComboBox->setCurrentIndex(rendererComboBox->findText(direct3DName)); #else - mRendererComboBox->setCurrentIndex(mRendererComboBox->findText(openGLName)); + rendererComboBox->setCurrentIndex(rendererComboBox->findText(openGLName)); #endif } - mAntiAliasingComboBox->clear(); - mResolutionComboBox->clear(); - mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); - mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); + antiAliasingComboBox->clear(); + resolutionComboBox->clear(); + antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); + resolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); // Load the rest of the values loadSettings(); @@ -184,38 +153,46 @@ bool GraphicsPage::setupOgre() void GraphicsPage::loadSettings() { if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true")) - mVSyncCheckBox->setCheckState(Qt::Checked); + vSyncCheckBox->setCheckState(Qt::Checked); if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true")) - mFullScreenCheckBox->setCheckState(Qt::Checked); + fullScreenCheckBox->setCheckState(Qt::Checked); - int aaIndex = mAntiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); + int aaIndex = antiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); if (aaIndex != -1) - mAntiAliasingComboBox->setCurrentIndex(aaIndex); + antiAliasingComboBox->setCurrentIndex(aaIndex); - QString resolution = mGraphicsSettings.value(QString("Video/resolution x")); - resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); + QString width = mGraphicsSettings.value(QString("Video/resolution x")); + QString height = mGraphicsSettings.value(QString("Video/resolution y")); + QString resolution = width + QString(" x ") + height; - int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); + int resIndex = resolutionComboBox->findText(resolution, Qt::MatchStartsWith); - if (resIndex != -1) - mResolutionComboBox->setCurrentIndex(resIndex); + if (resIndex != -1) { + standardRadioButton->toggle(); + resolutionComboBox->setCurrentIndex(resIndex); + } else { + customRadioButton->toggle(); + customWidthSpinBox->setValue(width.toInt()); + customHeightSpinBox->setValue(height.toInt()); + + } } void GraphicsPage::saveSettings() { - mVSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true")) + vSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true")) : mGraphicsSettings.setValue(QString("Video/vsync"), QString("false")); - mFullScreenCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("true")) + fullScreenCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("true")) : mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("false")); - mGraphicsSettings.setValue(QString("Video/antialiasing"), mAntiAliasingComboBox->currentText()); - mGraphicsSettings.setValue(QString("Video/render system"), mRendererComboBox->currentText()); + mGraphicsSettings.setValue(QString("Video/antialiasing"), antiAliasingComboBox->currentText()); + mGraphicsSettings.setValue(QString("Video/render system"), rendererComboBox->currentText()); QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); - if (resolutionRe.exactMatch(mResolutionComboBox->currentText().simplified())) { + if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) { mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); } @@ -277,6 +254,7 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) // remove extra tokens after the resolution (for example bpp, can be there or not depending on rendersystem) QStringList tokens = qval.split(" ", QString::SkipEmptyParts); assert (tokens.size() >= 3); + QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2); QString aspect = getAspect(tokens.at(0).toInt(),tokens.at(2).toInt()); @@ -304,9 +282,36 @@ void GraphicsPage::rendererChanged(const QString &renderer) { mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString()); - mAntiAliasingComboBox->clear(); - mResolutionComboBox->clear(); + antiAliasingComboBox->clear(); + resolutionComboBox->clear(); - mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); - mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); + antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); + resolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); +} + +void GraphicsPage::slotFullScreenChanged(int state) +{ + if (state == Qt::Checked) { + standardRadioButton->toggle(); + customRadioButton->setEnabled(false); + customWidthSpinBox->setEnabled(false); + customHeightSpinBox->setEnabled(false); + } else { + customRadioButton->setEnabled(true); + customWidthSpinBox->setEnabled(true); + customHeightSpinBox->setEnabled(true); + } +} + +void GraphicsPage::slotStandardToggled(bool checked) +{ + if (checked) { + resolutionComboBox->setEnabled(true); + customWidthSpinBox->setEnabled(false); + customHeightSpinBox->setEnabled(false); + } else { + resolutionComboBox->setEnabled(false); + customWidthSpinBox->setEnabled(true); + customHeightSpinBox->setEnabled(true); + } } diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 48b9ff785..21039af43 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -16,16 +16,13 @@ # include "OgreD3D9Plugin.h" #endif -class QComboBox; -class QCheckBox; -class QStackedWidget; -class QSettings; +#include "ui_graphicspage.h" class GraphicsSettings; namespace Files { struct ConfigurationManager; } -class GraphicsPage : public QWidget +class GraphicsPage : public QWidget, private Ui::GraphicsPage { Q_OBJECT @@ -38,6 +35,10 @@ public: public slots: void rendererChanged(const QString &renderer); +private slots: + void slotFullScreenChanged(int state); + void slotStandardToggled(bool checked); + private: Ogre::Root *mOgre; Ogre::RenderSystem *mSelectedRenderSystem; @@ -50,22 +51,12 @@ private: Ogre::D3D9Plugin* mD3D9Plugin; #endif - QComboBox *mRendererComboBox; - - QStackedWidget *mDisplayStackedWidget; - - QComboBox *mAntiAliasingComboBox; - QComboBox *mResolutionComboBox; - QCheckBox *mVSyncCheckBox; - QCheckBox *mFullScreenCheckBox; - Files::ConfigurationManager &mCfgMgr; GraphicsSettings &mGraphicsSettings; QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); QStringList getAvailableResolutions(Ogre::RenderSystem *renderer); - void createPages(); void loadSettings(); }; diff --git a/apps/launcher/ui/graphicspage.ui b/apps/launcher/ui/graphicspage.ui index e04cd5855..5c330cebd 100644 --- a/apps/launcher/ui/graphicspage.ui +++ b/apps/launcher/ui/graphicspage.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 332 + 297 @@ -33,7 +33,7 @@ - GroupBox + Display @@ -73,9 +73,13 @@ - + - + + + 800 + + @@ -85,7 +89,11 @@ - + + + 600 + + @@ -101,7 +109,7 @@ Standard: - + true From 4c9d0563fe4d96f3ca50489b3ea2d4abbf48a44d Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 5 Mar 2013 03:13:39 +0100 Subject: [PATCH 118/151] WIP: Implementing the .ui for the DataFilesPage --- apps/launcher/CMakeLists.txt | 13 +- apps/launcher/datafilespage.cpp | 272 +++++++++--------- apps/launcher/datafilespage.hpp | 19 +- apps/launcher/maindialog.cpp | 9 +- components/CMakeLists.txt | 2 +- .../fileorderlist}/utils/comboboxlineedit.cpp | 0 .../fileorderlist}/utils/comboboxlineedit.hpp | 0 .../fileorderlist}/utils/profilescombobox.cpp | 0 .../fileorderlist}/utils/profilescombobox.hpp | 0 9 files changed, 155 insertions(+), 160 deletions(-) rename {apps/launcher => components/fileorderlist}/utils/comboboxlineedit.cpp (100%) rename {apps/launcher => components/fileorderlist}/utils/comboboxlineedit.hpp (100%) rename {apps/launcher => components/fileorderlist}/utils/profilescombobox.cpp (100%) rename {apps/launcher => components/fileorderlist}/utils/profilescombobox.hpp (100%) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 206e94794..a1c228945 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -12,8 +12,6 @@ set(LAUNCHER settings/launchersettings.cpp utils/checkablemessagebox.cpp - utils/comboboxlineedit.cpp - utils/profilescombobox.cpp utils/textinputdialog.cpp launcher.rc @@ -33,8 +31,6 @@ set(LAUNCHER_HEADER settings/settingsbase.hpp utils/checkablemessagebox.hpp - utils/comboboxlineedit.hpp - utils/profilescombobox.hpp utils/textinputdialog.hpp ) @@ -49,15 +45,14 @@ set(LAUNCHER_HEADER_MOC model/pluginsproxymodel.hpp utils/checkablemessagebox.hpp - utils/comboboxlineedit.hpp - utils/profilescombobox.hpp utils/textinputdialog.hpp ) set(LAUNCHER_UI - ./ui/graphicspage.ui - ./ui/mainwindow.ui - ./ui/playpage.ui + ui/datafilespage.ui + ui/graphicspage.ui + ui/mainwindow.ui + ui/playpage.ui ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index dd45c6602..d7dccbab6 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -10,13 +10,13 @@ #include #include +#include #include "model/pluginsproxymodel.hpp" #include "settings/gamesettings.hpp" #include "settings/launchersettings.hpp" -#include "utils/profilescombobox.hpp" #include "utils/textinputdialog.hpp" using namespace ESM; @@ -40,6 +40,8 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam , mLauncherSettings(launcherSettings) , QWidget(parent) { + setupUi(this); + // Models mDataFilesModel = new DataFilesModel(this); @@ -57,113 +59,117 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mFilterProxyModel->setDynamicSortFilter(true); mFilterProxyModel->setSourceModel(mPluginsProxyModel); - // Filter toolbar - QLabel *filterLabel = new QLabel(tr("&Filter:"), this); - LineEdit *filterLineEdit = new LineEdit(this); - filterLabel->setBuddy(filterLineEdit); - - QToolBar *filterToolBar = new QToolBar(this); - filterToolBar->setMovable(false); - - // Create a container widget and a layout to get the spacer to work - QWidget *filterWidget = new QWidget(this); - QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget); - QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - filterLayout->addItem(hSpacer1); - filterLayout->addWidget(filterLabel); - filterLayout->addWidget(filterLineEdit); - - filterToolBar->addWidget(filterWidget); - QCheckBox checkBox; unsigned int height = checkBox.sizeHint().height() + 4; - mMastersTable = new QTableView(this); - mMastersTable->setModel(mMastersProxyModel); - mMastersTable->setObjectName("MastersTable"); - mMastersTable->setContextMenuPolicy(Qt::CustomContextMenu); - mMastersTable->setSortingEnabled(false); - mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mMastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection); - mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mMastersTable->setAlternatingRowColors(true); - mMastersTable->horizontalHeader()->setStretchLastSection(true); - mMastersTable->horizontalHeader()->hide(); + mastersTable->setModel(mMastersProxyModel); + mastersTable->setObjectName("MastersTable"); + mastersTable->setContextMenuPolicy(Qt::CustomContextMenu); + mastersTable->setSortingEnabled(false); + mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); + mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + mastersTable->setAlternatingRowColors(true); + mastersTable->horizontalHeader()->setStretchLastSection(true); + mastersTable->horizontalHeader()->hide(); // Set the row height to the size of the checkboxes - mMastersTable->verticalHeader()->setDefaultSectionSize(height); - mMastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - mMastersTable->verticalHeader()->hide(); + mastersTable->verticalHeader()->setDefaultSectionSize(height); + mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + mastersTable->verticalHeader()->hide(); - mPluginsTable = new QTableView(this); - mPluginsTable->setModel(mFilterProxyModel); - mPluginsTable->setObjectName("PluginsTable"); - mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); - mPluginsTable->setSortingEnabled(false); - mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mPluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); - mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mPluginsTable->setAlternatingRowColors(true); - mPluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); - mPluginsTable->horizontalHeader()->setStretchLastSection(true); - mPluginsTable->horizontalHeader()->hide(); + pluginsTable->setModel(mFilterProxyModel); + pluginsTable->setObjectName("PluginsTable"); + pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); + pluginsTable->setSortingEnabled(false); + pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + pluginsTable->setAlternatingRowColors(true); + pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + pluginsTable->horizontalHeader()->setStretchLastSection(true); + pluginsTable->horizontalHeader()->hide(); - mPluginsTable->verticalHeader()->setDefaultSectionSize(height); - mPluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + pluginsTable->verticalHeader()->setDefaultSectionSize(height); + pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - // Add both tables to a splitter - mSplitter = new QSplitter(this); - mSplitter->setOrientation(Qt::Horizontal); - mSplitter->setChildrenCollapsible(false); // Don't allow the widgets to be hidden - mSplitter->addWidget(mMastersTable); - mSplitter->addWidget(mPluginsTable); - - // Adjust the default widget widths inside the splitter + // Adjust the tableview widths inside the splitter QList sizeList; sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt(); sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt(); - mSplitter->setSizes(sizeList); + splitter->setSizes(sizeList); - // Bottom part with profile options - QLabel *profileLabel = new QLabel(tr("Current Profile: "), this); +// // Filter toolbar +// QLabel *filterLabel = new QLabel(tr("&Filter:"), this); +// LineEdit *filterLineEdit = new LineEdit(this); +// filterLabel->setBuddy(filterLineEdit); - mProfilesComboBox = new ProfilesComboBox(this); - mProfilesComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); - mProfilesComboBox->setInsertPolicy(QComboBox::NoInsert); - mProfilesComboBox->setDuplicatesEnabled(false); - mProfilesComboBox->setEditEnabled(false); +// QToolBar *filterToolBar = new QToolBar(this); +// filterToolBar->setMovable(false); - mProfileToolBar = new QToolBar(this); - mProfileToolBar->setMovable(false); - mProfileToolBar->setIconSize(QSize(16, 16)); +// // Create a container widget and a layout to get the spacer to work +// QWidget *filterWidget = new QWidget(this); +// QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget); +// QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - mProfileToolBar->addWidget(profileLabel); - mProfileToolBar->addWidget(mProfilesComboBox); +// filterLayout->addItem(hSpacer1); +// filterLayout->addWidget(filterLabel); +// filterLayout->addWidget(filterLineEdit); - QVBoxLayout *pageLayout = new QVBoxLayout(this); +// filterToolBar->addWidget(filterWidget); - pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(mSplitter); - pageLayout->addWidget(mProfileToolBar); + + +// // Add both tables to a splitter +// mSplitter = new QSplitter(this); +// mSplitter->setOrientation(Qt::Horizontal); +// mSplitter->setChildrenCollapsible(false); // Don't allow the widgets to be hidden +// mSplitter->addWidget(mastersTable); +// mSplitter->addWidget(pluginsTable); + + + +// + +// // Bottom part with profile options +// QLabel *profileLabel = new QLabel(tr("Current Profile: "), this); + +// profilesComboBox = new ProfilesComboBox(this); +// profilesComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); +// profilesComboBox->setInsertPolicy(QComboBox::NoInsert); +// profilesComboBox->setDuplicatesEnabled(false); +// profilesComboBox->setEditEnabled(false); + +// mProfileToolBar = new QToolBar(this); +// mProfileToolBar->setMovable(false); +// mProfileToolBar->setIconSize(QSize(16, 16)); + +// mProfileToolBar->addWidget(profileLabel); +// mProfileToolBar->addWidget(profilesComboBox); + +// QVBoxLayout *pageLayout = new QVBoxLayout(this); + +// pageLayout->addWidget(filterToolBar); +// pageLayout->addWidget(mSplitter); +// pageLayout->addWidget(mProfileToolBar); // Create a dialog for the new profile name input mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); - connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); - connect(mMastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + connect(pluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + 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(mSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter())); + connect(splitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter())); createActions(); setupDataFiles(); @@ -188,9 +194,9 @@ void DataFilesPage::createActions() connect(mDeleteProfileAction, SIGNAL(triggered()), this, SLOT(deleteProfile())); // Add the newly created actions to the toolbar - mProfileToolBar->addSeparator(); - mProfileToolBar->addAction(mNewProfileAction); - mProfileToolBar->addAction(mDeleteProfileAction); +// mProfileToolBar->addSeparator(); +// mProfileToolBar->addAction(mNewProfileAction); +// mProfileToolBar->addAction(mDeleteProfileAction); // Context menu actions mCheckAction = new QAction(tr("Check Selection"), this); @@ -226,25 +232,25 @@ void DataFilesPage::setupDataFiles() QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); if (!profiles.isEmpty()) - mProfilesComboBox->addItems(profiles); + profilesComboBox->addItems(profiles); // Add the current profile if empty - if (mProfilesComboBox->findText(profile) == -1) - mProfilesComboBox->addItem(profile); + if (profilesComboBox->findText(profile) == -1) + profilesComboBox->addItem(profile); - if (mProfilesComboBox->findText(QString("Default")) == -1) - mProfilesComboBox->addItem(QString("Default")); + if (profilesComboBox->findText(QString("Default")) == -1) + profilesComboBox->addItem(QString("Default")); if (profile.isEmpty() || profile == QLatin1String("Default")) { - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(QString("Default"))); + profilesComboBox->setCurrentIndex(profilesComboBox->findText(QString("Default"))); } else { - mProfilesComboBox->setEditEnabled(true); - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); + profilesComboBox->setEditEnabled(true); + profilesComboBox->setCurrentIndex(profilesComboBox->findText(profile)); } // We do this here to prevent deletion of profiles when initializing the combobox - connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); - connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); + connect(profilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); + connect(profilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); loadSettings(); @@ -283,7 +289,7 @@ void DataFilesPage::saveSettings() QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); if (profile.isEmpty()) { - profile = mProfilesComboBox->currentText(); + profile = profilesComboBox->currentText(); mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile); } @@ -313,8 +319,8 @@ void DataFilesPage::newProfile() { if (mNewProfileDialog->exec() == QDialog::Accepted) { QString profile = mNewProfileDialog->lineEdit()->text(); - mProfilesComboBox->addItem(profile); - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); + profilesComboBox->addItem(profile); + profilesComboBox->setCurrentIndex(profilesComboBox->findText(profile)); } } @@ -326,7 +332,7 @@ void DataFilesPage::updateOkButton(const QString &text) return; } - (mProfilesComboBox->findText(text) == -1) + (profilesComboBox->findText(text) == -1) ? mNewProfileDialog->setOkButtonEnabled(true) : mNewProfileDialog->setOkButtonEnabled(false); } @@ -335,7 +341,7 @@ void DataFilesPage::updateSplitter() { // Sigh, update the saved splitter size in settings only when moved // Since getting mSplitter->sizes() if page is hidden returns invalid values - QList sizes = mSplitter->sizes(); + QList sizes = splitter->sizes(); mLauncherSettings.setValue(QString("General/MastersTable/width"), QString::number(sizes.at(0))); mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1))); @@ -344,28 +350,28 @@ void DataFilesPage::updateSplitter() void DataFilesPage::updateViews() { // Ensure the columns are hidden because sort() re-enables them - mMastersTable->setColumnHidden(1, true); - mMastersTable->setColumnHidden(2, true); - mMastersTable->setColumnHidden(3, true); - mMastersTable->setColumnHidden(4, true); - mMastersTable->setColumnHidden(5, true); - mMastersTable->setColumnHidden(6, true); - mMastersTable->setColumnHidden(7, true); - mMastersTable->setColumnHidden(8, true); + mastersTable->setColumnHidden(1, true); + mastersTable->setColumnHidden(2, true); + mastersTable->setColumnHidden(3, true); + mastersTable->setColumnHidden(4, true); + mastersTable->setColumnHidden(5, true); + mastersTable->setColumnHidden(6, true); + mastersTable->setColumnHidden(7, true); + mastersTable->setColumnHidden(8, true); - mPluginsTable->setColumnHidden(1, true); - mPluginsTable->setColumnHidden(2, true); - mPluginsTable->setColumnHidden(3, true); - mPluginsTable->setColumnHidden(4, true); - mPluginsTable->setColumnHidden(5, true); - mPluginsTable->setColumnHidden(6, true); - mPluginsTable->setColumnHidden(7, true); - mPluginsTable->setColumnHidden(8, true); + pluginsTable->setColumnHidden(1, true); + pluginsTable->setColumnHidden(2, true); + pluginsTable->setColumnHidden(3, true); + pluginsTable->setColumnHidden(4, true); + pluginsTable->setColumnHidden(5, true); + pluginsTable->setColumnHidden(6, true); + pluginsTable->setColumnHidden(7, true); + pluginsTable->setColumnHidden(8, true); } void DataFilesPage::deleteProfile() { - QString profile = mProfilesComboBox->currentText(); + QString profile = profilesComboBox->currentText(); if (profile.isEmpty()) return; @@ -386,26 +392,26 @@ void DataFilesPage::deleteProfile() mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); // Remove the profile from the combobox - mProfilesComboBox->removeItem(mProfilesComboBox->findText(profile)); + profilesComboBox->removeItem(profilesComboBox->findText(profile)); } } void DataFilesPage::check() { - if (mPluginsTable->hasFocus()) + if (pluginsTable->hasFocus()) setPluginsCheckstates(Qt::Checked); - if (mMastersTable->hasFocus()) + if (mastersTable->hasFocus()) setMastersCheckstates(Qt::Checked); } void DataFilesPage::uncheck() { - if (mPluginsTable->hasFocus()) + if (pluginsTable->hasFocus()) setPluginsCheckstates(Qt::Unchecked); - if (mMastersTable->hasFocus()) + if (mastersTable->hasFocus()) setMastersCheckstates(Qt::Unchecked); } @@ -414,16 +420,16 @@ void DataFilesPage::refresh() // mDataFilesModel->sort(0); // Refresh the plugins table - mPluginsTable->scrollToTop(); + pluginsTable->scrollToTop(); } void DataFilesPage::setMastersCheckstates(Qt::CheckState state) { - if (!mMastersTable->selectionModel()->hasSelection()) { + if (!mastersTable->selectionModel()->hasSelection()) { return; } - QModelIndexList indexes = mMastersTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes(); foreach (const QModelIndex &index, indexes) { @@ -441,11 +447,11 @@ void DataFilesPage::setMastersCheckstates(Qt::CheckState state) void DataFilesPage::setPluginsCheckstates(Qt::CheckState state) { - if (!mPluginsTable->selectionModel()->hasSelection()) { + if (!pluginsTable->selectionModel()->hasSelection()) { return; } - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes(); foreach (const QModelIndex &index, indexes) { @@ -509,16 +515,16 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre // Prevent the deletion of the default profile if (current == QLatin1String("Default")) { mDeleteProfileAction->setEnabled(false); - mProfilesComboBox->setEditEnabled(false); + profilesComboBox->setEditEnabled(false); } else { mDeleteProfileAction->setEnabled(true); - mProfilesComboBox->setEditEnabled(true); + profilesComboBox->setEditEnabled(true); } if (previous.isEmpty()) return; - if (mProfilesComboBox->findText(previous) == -1) + if (profilesComboBox->findText(previous) == -1) return; // Profile was deleted // Store the previous profile @@ -543,7 +549,7 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre mLauncherSettings.remove(QString("Profiles/") + previous + QString("/plugin")); // Remove the profile from the combobox - mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); + profilesComboBox->removeItem(profilesComboBox->findText(previous)); loadSettings(); @@ -558,11 +564,11 @@ void DataFilesPage::showContextMenu(const QPoint &point) return; if (object->objectName() == QLatin1String("PluginsTable")) { - if (!mPluginsTable->selectionModel()->hasSelection()) + if (!pluginsTable->selectionModel()->hasSelection()) return; - QPoint globalPos = mPluginsTable->mapToGlobal(point); - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QPoint globalPos = pluginsTable->mapToGlobal(point); + QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes(); // Show the check/uncheck actions depending on the state of the selected items mUncheckAction->setEnabled(false); @@ -589,11 +595,11 @@ void DataFilesPage::showContextMenu(const QPoint &point) } if (object->objectName() == QLatin1String("MastersTable")) { - if (!mMastersTable->selectionModel()->hasSelection()) + if (!mastersTable->selectionModel()->hasSelection()) return; - QPoint globalPos = mMastersTable->mapToGlobal(point); - QModelIndexList indexes = mMastersTable->selectionModel()->selectedIndexes(); + QPoint globalPos = mastersTable->mapToGlobal(point); + QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes(); // Show the check/uncheck actions depending on the state of the selected items mUncheckAction->setEnabled(false); diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index dd69d7489..e98b09aef 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -4,33 +4,28 @@ #include #include -class QTableView; +#include "ui_datafilespage.h" + class QSortFilterProxyModel; class QAction; -class QToolBar; -class QSplitter; class QMenu; -class ProfilesComboBox; class DataFilesModel; class TextInputDialog; -class ProfilesComboBox; class GameSettings; class LauncherSettings; class PluginsProxyModel; namespace Files { struct ConfigurationManager; } -class DataFilesPage : public QWidget +class DataFilesPage : public QWidget, private Ui::DataFilesPage { Q_OBJECT public: DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0); - ProfilesComboBox *mProfilesComboBox; - void writeConfig(QString profile = QString()); void saveSettings(); @@ -60,13 +55,13 @@ private: QSortFilterProxyModel *mFilterProxyModel; - QTableView *mMastersTable; - QTableView *mPluginsTable; +// QTableView *mMastersTable; +// QTableView *mPluginsTable; - QToolBar *mProfileToolBar; +// QToolBar *mProfileToolBar; QMenu *mContextMenu; - QSplitter *mSplitter; +// QSplitter *mSplitter; QAction *mNewProfileAction; QAction *mDeleteProfileAction; diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 5621b75c0..cab763b10 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -3,7 +3,6 @@ #include #include "utils/checkablemessagebox.hpp" -#include "utils/profilescombobox.hpp" #include "playpage.hpp" #include "graphicspage.hpp" @@ -94,8 +93,8 @@ void MainDialog::createPages() mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage - mPlayPage->setProfilesComboBoxModel(mDataFilesPage->mProfilesComboBox->model()); - mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); +// mPlayPage->setProfilesComboBoxModel(mDataFilesPage->mProfilesComboBox->model()); +// mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); @@ -107,8 +106,8 @@ void MainDialog::createPages() connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play())); - connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); - connect(mDataFilesPage->mProfilesComboBox, SIGNAL(currentIndexChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); +// connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); +// connect(mDataFilesPage->mProfilesComboBox, SIGNAL(currentIndexChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 00342e2ac..7c52ab12c 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -71,7 +71,7 @@ find_package(Qt4 COMPONENTS QtCore QtGui) if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) add_component_qt_dir (fileorderlist datafileslist model/modelitem model/datafilesmodel model/esm/esmfile - utils/filedialog utils/lineedit utils/naturalsort + utils/profilescombobox utils/comboboxlineedit utils/lineedit utils/naturalsort ) include(${QT_USE_FILE}) diff --git a/apps/launcher/utils/comboboxlineedit.cpp b/components/fileorderlist/utils/comboboxlineedit.cpp similarity index 100% rename from apps/launcher/utils/comboboxlineedit.cpp rename to components/fileorderlist/utils/comboboxlineedit.cpp diff --git a/apps/launcher/utils/comboboxlineedit.hpp b/components/fileorderlist/utils/comboboxlineedit.hpp similarity index 100% rename from apps/launcher/utils/comboboxlineedit.hpp rename to components/fileorderlist/utils/comboboxlineedit.hpp diff --git a/apps/launcher/utils/profilescombobox.cpp b/components/fileorderlist/utils/profilescombobox.cpp similarity index 100% rename from apps/launcher/utils/profilescombobox.cpp rename to components/fileorderlist/utils/profilescombobox.cpp diff --git a/apps/launcher/utils/profilescombobox.hpp b/components/fileorderlist/utils/profilescombobox.hpp similarity index 100% rename from apps/launcher/utils/profilescombobox.hpp rename to components/fileorderlist/utils/profilescombobox.hpp From 75cf009101828d8f83c98eb0915bede65c1c54dd Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 5 Mar 2013 03:47:57 +0100 Subject: [PATCH 119/151] Finished implementing the .ui file for the DataFilesPage --- apps/launcher/datafilespage.cpp | 32 ++++++++++++++++++++++++++------ apps/launcher/datafilespage.hpp | 12 +++++++++++- apps/launcher/maindialog.cpp | 8 ++++---- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index d7dccbab6..069cdd9ac 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -157,6 +157,8 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam // Create a dialog for the new profile name input mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); + connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int))); + connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); @@ -182,7 +184,7 @@ void DataFilesPage::createActions() refreshAction->setShortcut(QKeySequence(tr("F5"))); connect(refreshAction, SIGNAL(triggered()), this, SLOT(refresh())); - // Profile actions + // We can't create actions inside the .ui file mNewProfileAction = new QAction(QIcon::fromTheme("document-new"), tr("&New Profile"), this); mNewProfileAction->setToolTip(tr("New Profile")); mNewProfileAction->setShortcut(QKeySequence(tr("Ctrl+N"))); @@ -190,13 +192,11 @@ void DataFilesPage::createActions() mDeleteProfileAction = new QAction(QIcon::fromTheme("edit-delete"), tr("Delete Profile"), this); mDeleteProfileAction->setToolTip(tr("Delete Profile")); - mDeleteProfileAction->setShortcut(QKeySequence(tr("Delete"))); connect(mDeleteProfileAction, SIGNAL(triggered()), this, SLOT(deleteProfile())); - // Add the newly created actions to the toolbar -// mProfileToolBar->addSeparator(); -// mProfileToolBar->addAction(mNewProfileAction); -// mProfileToolBar->addAction(mDeleteProfileAction); + // Add the newly created actions to the toolbuttons + newProfileButton->setDefaultAction(mNewProfileAction); + deleteProfileButton->setDefaultAction(mDeleteProfileAction); // Context menu actions mCheckAction = new QAction(tr("Check Selection"), this); @@ -369,6 +369,26 @@ void DataFilesPage::updateViews() pluginsTable->setColumnHidden(8, true); } +void DataFilesPage::setProfilesComboBoxIndex(int index) +{ + profilesComboBox->setCurrentIndex(index); +} + +void DataFilesPage::slotCurrentIndexChanged(int index) +{ + emit profileChanged(index); +} + +QAbstractItemModel* DataFilesPage::profilesComboBoxModel() +{ + return profilesComboBox->model(); +} + +int DataFilesPage::profilesComboBoxIndex() +{ + return profilesComboBox->currentIndex(); +} + void DataFilesPage::deleteProfile() { QString profile = profilesComboBox->currentText(); diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index e98b09aef..301abf59b 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -7,11 +7,11 @@ #include "ui_datafilespage.h" class QSortFilterProxyModel; +class QAbstractItemModel; class QAction; class QMenu; class DataFilesModel; - class TextInputDialog; class GameSettings; class LauncherSettings; @@ -26,12 +26,19 @@ class DataFilesPage : public QWidget, private Ui::DataFilesPage public: DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0); + QAbstractItemModel* profilesComboBoxModel(); + int profilesComboBoxIndex(); + void writeConfig(QString profile = QString()); void saveSettings(); +signals: + void profileChanged(int index); public slots: void setCheckState(QModelIndex index); + void setProfilesComboBoxIndex(int index); + void filterChanged(const QString filter); void showContextMenu(const QPoint &point); void profileChanged(const QString &previous, const QString ¤t); @@ -47,6 +54,9 @@ public slots: void uncheck(); void refresh(); +private slots: + void slotCurrentIndexChanged(int index); + private: DataFilesModel *mDataFilesModel; diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index cab763b10..6a3965cc9 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -93,8 +93,8 @@ void MainDialog::createPages() mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage -// mPlayPage->setProfilesComboBoxModel(mDataFilesPage->mProfilesComboBox->model()); -// mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); + mPlayPage->setProfilesComboBoxModel(mDataFilesPage->profilesComboBoxModel()); + mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->profilesComboBoxIndex()); // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); @@ -106,8 +106,8 @@ void MainDialog::createPages() connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play())); -// connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); -// connect(mDataFilesPage->mProfilesComboBox, SIGNAL(currentIndexChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); + connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage, SLOT(setProfilesComboBoxIndex(int))); + connect(mDataFilesPage, SIGNAL(profileChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); } From 770d8af931ea7ad75c3a978761eb36fcd4e1e37c Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 5 Mar 2013 03:57:27 +0100 Subject: [PATCH 120/151] Forgot to add the DataFilesPage .ui --- apps/launcher/ui/datafilespage.ui | 125 ++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 apps/launcher/ui/datafilespage.ui diff --git a/apps/launcher/ui/datafilespage.ui b/apps/launcher/ui/datafilespage.ui new file mode 100644 index 000000000..91b5475e6 --- /dev/null +++ b/apps/launcher/ui/datafilespage.ui @@ -0,0 +1,125 @@ + + + DataFilesPage + + + + 0 + 0 + 520 + 256 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Filter: + + + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + false + + + + + + + + + + + Current Profile: + + + + + + + + 0 + 0 + + + + + + + + New Profile + + + &New Profile + + + true + + + + + + + Delete Profile + + + Delete Profile + + + Ctrl+D + + + true + + + + + + + + + + LineEdit + QLineEdit +
components/fileorderlist/utils/lineedit.hpp
+
+ + ProfilesComboBox + QComboBox +
components/fileorderlist/utils/profilescombobox.hpp
+
+
+ + +
From ce49ad54a1ef73a557ef0a6d32362d21718ed2e0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 5 Mar 2013 08:02:05 +0100 Subject: [PATCH 121/151] some cleanup and fixing --- components/esm/loadglob.cpp | 8 ++------ components/esm/variant.cpp | 37 ++++++++++++++++++++++--------------- components/esm/variant.hpp | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index 0cb6d0a41..ccb519acd 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -1,17 +1,13 @@ #include "loadglob.hpp" -#include "esmreader.hpp" -#include "esmwriter.hpp" - namespace ESM { - - void Global::load(ESMReader &esm) + void Global::load (ESMReader &esm) { mValue.read (esm, ESM::Variant::Format_Global); } - void Global::save(ESMWriter &esm) + void Global::save (ESMWriter &esm) { mValue.write (esm, ESM::Variant::Format_Global); } diff --git a/components/esm/variant.cpp b/components/esm/variant.cpp index bf8d2069b..98786c20e 100644 --- a/components/esm/variant.cpp +++ b/components/esm/variant.cpp @@ -37,7 +37,7 @@ ESM::VarType ESM::Variant::getType() const return mType; } -std::string ESM::Variant::toString() const +std::string ESM::Variant::getString() const { if (!mData) throw std::runtime_error ("can not convert empty variant to string"); @@ -81,23 +81,30 @@ void ESM::Variant::read (ESMReader& esm, Format format) } else // GMST { - esm.getSubName(); - NAME name = esm.retSubName(); - - if (name=="STRV") + if (!esm.hasMoreSubs()) { - type = VT_String; - } - else if (name=="INTV") - { - type = VT_Int; - } - else if (name=="FLTV") - { - type = VT_Float; + type = VT_None; } else - esm.fail ("invalid subrecord: " + name.toString()); + { + esm.getSubName(); + NAME name = esm.retSubName(); + + if (name=="STRV") + { + type = VT_String; + } + else if (name=="INTV") + { + type = VT_Int; + } + else if (name=="FLTV") + { + type = VT_Float; + } + else + esm.fail ("invalid subrecord: " + name.toString()); + } } setType (type); diff --git a/components/esm/variant.hpp b/components/esm/variant.hpp index b50bb1d2f..b78d647a8 100644 --- a/components/esm/variant.hpp +++ b/components/esm/variant.hpp @@ -45,7 +45,7 @@ namespace ESM VarType getType() const; - std::string toString() const; + std::string getString() const; ///< Will throw an exception, if value can not be represented as a string. int getInteger() const; From ba4907fbaf7ed8d1dee768569b912bf7ee7641cf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 5 Mar 2013 08:02:27 +0100 Subject: [PATCH 122/151] use new Variant type for GMSTs --- apps/esmtool/record.cpp | 18 +----- apps/opencs/model/doc/document.cpp | 10 ++- apps/opencs/model/world/columns.hpp | 31 ++++++--- apps/opencs/model/world/data.cpp | 1 + apps/openmw/mwgui/windowmanagerimp.cpp | 11 ++-- apps/openmw/mwworld/worldimp.cpp | 14 ++-- components/esm/loadgmst.cpp | 89 ++++---------------------- components/esm/loadgmst.hpp | 10 ++- 8 files changed, 55 insertions(+), 129 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 929201417..e4de63dd4 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -719,23 +719,7 @@ void Record::print() template<> void Record::print() { - std::cout << " Value: "; - switch (mData.mType) { - case ESM::VT_String: - std::cout << "'" << mData.mStr << "' (std::string)"; - break; - - case ESM::VT_Float: - std::cout << mData.mF << " (float)"; - break; - - case ESM::VT_Int: - std::cout << mData.mI << " (int)"; - break; - - default: - std::cout << "unknown type"; - } + std::cout << " " << mData.mValue << std::endl; } template<> diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index f6df1f499..6a76b0b6c 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -116,8 +116,7 @@ void CSMDoc::Document::addOptionalGmsts() { ESM::GameSetting gmst; gmst.mId = sFloats[i]; - gmst.mF = 0; - gmst.mType = ESM::VT_Float; + gmst.mValue.setType (ESM::VT_Float); addOptionalGmst (gmst); } @@ -125,8 +124,7 @@ void CSMDoc::Document::addOptionalGmsts() { ESM::GameSetting gmst; gmst.mId = sIntegers[i]; - gmst.mI = 0; - gmst.mType = ESM::VT_Long; + gmst.mValue.setType (ESM::VT_Int); addOptionalGmst (gmst); } @@ -134,8 +132,8 @@ void CSMDoc::Document::addOptionalGmsts() { ESM::GameSetting gmst; gmst.mId = sStrings[i]; - gmst.mStr = ""; - gmst.mType = ESM::VT_String; + gmst.mValue.setType (ESM::VT_String); + gmst.mValue.setString (""); addOptionalGmst (gmst); } } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 8855edc46..270987ec1 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -100,13 +100,13 @@ namespace CSMWorld virtual QVariant get (const Record& record) const { - return static_cast (record.get().mType); + return static_cast (record.get().mValue.getType()); } virtual void set (Record& record, const QVariant& data) { ESXRecordT record2 = record.get(); - record2.mType = static_cast (data.toInt()); + record2.mValue.setType (static_cast (data.toInt())); record.setModified (record2); } @@ -123,11 +123,11 @@ namespace CSMWorld virtual QVariant get (const Record& record) const { - switch (record.get().mType) + switch (record.get().mValue.getType()) { - case ESM::VT_String: return record.get().mStr.c_str(); break; - case ESM::VT_Int: return record.get().mI; break; - case ESM::VT_Float: return record.get().mF; break; + case ESM::VT_String: return record.get().mValue.getString().c_str(); break; + case ESM::VT_Int: return record.get().mValue.getInteger(); break; + case ESM::VT_Float: return record.get().mValue.getFloat(); break; default: return QVariant(); } @@ -137,11 +137,22 @@ namespace CSMWorld { ESXRecordT record2 = record.get(); - switch (record2.mType) + switch (record2.mValue.getType()) { - case ESM::VT_String: record2.mStr = data.toString().toUtf8().constData(); break; - case ESM::VT_Int: record2.mI = data.toInt(); break; - case ESM::VT_Float: record2.mF = data.toFloat(); break; + case ESM::VT_String: + + record2.mValue.setString (data.toString().toUtf8().constData()); + break; + + case ESM::VT_Int: + + record2.mValue.setInteger (data.toInt()); + break; + + case ESM::VT_Float: + + record2.mValue.setFloat (data.toFloat()); + break; default: break; } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index c59763f51..d4704b0c6 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "idtable.hpp" diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 1dc11f2c4..efdb86400 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -569,7 +569,7 @@ void WindowManager::messageBox (const std::string& message, const std::vectorcreateMessageBox(message); } - + else { mMessageBoxManager->createInteractiveMessageBox(message, buttons); @@ -592,8 +592,9 @@ std::string WindowManager::getGameSettingString(const std::string &id, const std const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().get().search(id); - if (setting && setting->mType == ESM::VT_String) - return setting->getString(); + if (setting && setting->mValue.getType()==ESM::VT_String) + return setting->mValue.getString(); + return default_; } @@ -774,8 +775,8 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().get().find(tag); - if (setting && setting->mType == ESM::VT_String) - _result = setting->getString(); + if (setting && setting->mValue.getType()==ESM::VT_String) + _result = setting->mValue.getString(); else _result = tag; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 90f26096e..1de0559d9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -198,7 +198,7 @@ namespace MWWorld for (std::vector::size_type i = 0; i < master.size(); i++, idx++) { boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i])); - + std::cout << "Loading ESM " << masterPath.string() << "\n"; // This parses the ESM file @@ -210,11 +210,11 @@ namespace MWWorld mEsm[idx] = lEsm; mStore.load (mEsm[idx]); } - + for (std::vector::size_type i = 0; i < plugins.size(); i++, idx++) { boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i])); - + std::cout << "Loading ESP " << pluginPath.string() << "\n"; // This parses the ESP file @@ -226,7 +226,7 @@ namespace MWWorld mEsm[idx] = lEsm; mStore.load (mEsm[idx]); } - + mStore.setUp(); mPlayer = new MWWorld::Player (mStore.get().find ("player"), *this); @@ -363,10 +363,8 @@ namespace MWWorld const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().get().search("sDefaultCellname"); - if (setting && setting->mType == ESM::VT_String) - name = setting->getString(); - else - name = "Wilderness"; + if (setting && setting->mValue.getType()==ESM::VT_String) + name = setting->mValue.getString(); } } diff --git a/components/esm/loadgmst.cpp b/components/esm/loadgmst.cpp index e9852ec07..fe1cc1b04 100644 --- a/components/esm/loadgmst.cpp +++ b/components/esm/loadgmst.cpp @@ -1,104 +1,39 @@ #include "loadgmst.hpp" -#include - -#include "esmreader.hpp" -#include "esmwriter.hpp" - namespace ESM { - -void GameSetting::load(ESMReader &esm) -{ - assert(mId != ""); - - // We are apparently allowed to be empty - if (!esm.hasMoreSubs()) + void GameSetting::load (ESMReader &esm) { - mType = VT_None; - return; + mValue.read (esm, ESM::Variant::Format_Gmst); } - // Load some data - esm.getSubName(); - NAME n = esm.retSubName(); - if (n == "STRV") + void GameSetting::save (ESMWriter &esm) { - mStr = esm.getHString(); - mType = VT_String; + mValue.write (esm, ESM::Variant::Format_Gmst); } - else if (n == "INTV") - { - esm.getHT(mI); - mType = VT_Int; - } - else if (n == "FLTV") - { - esm.getHT(mF); - mType = VT_Float; - } - else - esm.fail("Unwanted subrecord type"); -} -void GameSetting::save(ESMWriter &esm) -{ - switch(mType) + int GameSetting::getInt() const { - case VT_String: esm.writeHNString("STRV", mStr); break; - case VT_Int: esm.writeHNT("INTV", mI); break; - case VT_Float: esm.writeHNT("FLTV", mF); break; - default: break; + return mValue.getInteger(); } -} -int GameSetting::getInt() const -{ - switch (mType) + float GameSetting::getFloat() const { - case VT_Float: return static_cast (mF); - case VT_Int: return mI; - default: throw std::runtime_error ("GMST " + mId + " is not of a numeric type"); + return mValue.getFloat(); } -} -float GameSetting::getFloat() const -{ - switch (mType) + std::string GameSetting::getString() const { - case VT_Float: return mF; - case VT_Int: return mI; - default: throw std::runtime_error ("GMST " + mId + " is not of a numeric type"); + return mValue.getString(); } -} - -std::string GameSetting::getString() const -{ - if (mType==VT_String) - return mStr; - - throw std::runtime_error ("GMST " + mId + " is not a string"); -} void GameSetting::blank() { - mStr.clear(); - mI = 0; - mF = 0; - mType = VT_Float; + mValue.setType (ESM::VT_None); } bool operator== (const GameSetting& left, const GameSetting& right) { - if (left.mType!=right.mType) - return false; - - switch (left.mType) - { - case VT_Float: return left.mF==right.mF; - case VT_Int: return left.mI==right.mI; - case VT_String: return left.mStr==right.mStr; - default: return false; - } + return left.mValue==right.mValue; } } diff --git a/components/esm/loadgmst.hpp b/components/esm/loadgmst.hpp index 12f212081..a6e0c2ecb 100644 --- a/components/esm/loadgmst.hpp +++ b/components/esm/loadgmst.hpp @@ -3,7 +3,6 @@ #include -#include "defs.hpp" #include "variant.hpp" namespace ESM @@ -20,14 +19,13 @@ class ESMWriter; struct GameSetting { std::string mId; - // One of these is used depending on the variable type - std::string mStr; - int mI; - float mF; - VarType mType; + + Variant mValue; void load(ESMReader &esm); + /// \todo remove the get* functions (redundant, since mValue as equivalent functions now). + int getInt() const; ///< Throws an exception if GMST is not of type int or float. From 1b19ab6028929cc6384afaf8c634cd84abeb2817 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 5 Mar 2013 08:15:03 +0100 Subject: [PATCH 123/151] fixed gmst integers --- components/esm/variantimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esm/variantimp.cpp b/components/esm/variantimp.cpp index e99cc50b5..1b8cf4f87 100644 --- a/components/esm/variantimp.cpp +++ b/components/esm/variantimp.cpp @@ -156,8 +156,8 @@ void ESM::VariantIntegerData::read (ESMReader& esm, Variant::Format format, VarT } else // GMST { - if (type==VT_Int) - esm.fail ("unsupported global variable integer type"); + if (type!=VT_Int) + esm.fail ("unsupported gmst variable integer type"); esm.getHT (mValue); } From 1489570b097bc31103fa1e03ec49ba2081a61a6c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 5 Mar 2013 09:40:41 +0100 Subject: [PATCH 124/151] change variant in info record to new type --- apps/esmtool/record.cpp | 9 ++--- apps/openmw/mwdialogue/selectwrapper.cpp | 9 +++-- components/esm/loadinfo.cpp | 25 ++----------- components/esm/loadinfo.hpp | 46 ++---------------------- components/esm/variant.cpp | 21 ++++++++++- components/esm/variant.hpp | 3 +- components/esm/variantimp.cpp | 32 +++++++++++++---- 7 files changed, 59 insertions(+), 86 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index e4de63dd4..38fddd6b9 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -112,14 +112,11 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss) case '5': oper_str = ">="; break; } - std::string value_str = "??"; - if (ss.mType == ESM::VT_Int) - value_str = str(boost::format("%d") % ss.mI); - else if (ss.mType == ESM::VT_Float) - value_str = str(boost::format("%f") % ss.mF); + std::ostringstream stream; + stream << ss.mValue; std::string result = str(boost::format("%-12s %-32s %2s %s") - % type_str % func_str % oper_str % value_str); + % type_str % func_str % oper_str % stream.str()); return result; } diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index 9cc528a11..9d705f6be 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -31,14 +31,13 @@ namespace template bool selectCompareImp (const ESM::DialInfo::SelectStruct& select, T value1) { - if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || - select.mType==ESM::VT_Long) + if (select.mValue.getType()==ESM::VT_Int) { - return selectCompareImp (select.mSelectRule[4], value1, select.mI); + return selectCompareImp (select.mSelectRule[4], value1, select.mValue.getInteger()); } - else if (select.mType==ESM::VT_Float) + else if (select.mValue.getType()==ESM::VT_Float) { - return selectCompareImp (select.mSelectRule[4], value1, select.mF); + return selectCompareImp (select.mSelectRule[4], value1, select.mValue.getFloat()); } else throw std::runtime_error ( diff --git a/components/esm/loadinfo.cpp b/components/esm/loadinfo.cpp index f237cf780..90f8fcf35 100644 --- a/components/esm/loadinfo.cpp +++ b/components/esm/loadinfo.cpp @@ -84,22 +84,8 @@ void DialInfo::load(ESMReader &esm) SelectStruct ss; ss.mSelectRule = esm.getHString(); - esm.isEmptyOrGetName(); - if (subName.val == REC_INTV) - { - ss.mType = VT_Int; - esm.getHT(ss.mI); - } - else if (subName.val == REC_FLTV) - { - ss.mType = VT_Float; - esm.getHT(ss.mF); - } - else - esm.fail( - "INFO.SCVR must precede INTV or FLTV, not " - + subName.toString()); + ss.mValue.read (esm, Variant::Format_Info); mSelects.push_back(ss); @@ -152,16 +138,11 @@ void DialInfo::save(ESMWriter &esm) for (std::vector::iterator it = mSelects.begin(); it != mSelects.end(); ++it) { esm.writeHNString("SCVR", it->mSelectRule); - switch(it->mType) - { - case VT_Int: esm.writeHNT("INTV", it->mI); break; - case VT_Float: esm.writeHNT("FLTV", it->mF); break; - default: break; - } + it->mValue.write (esm, Variant::Format_Info); } esm.writeHNOString("BNAM", mResultScript); - + switch(mQuestStatus) { case QS_Name: esm.writeHNT("QSTN",'\1'); break; diff --git a/components/esm/loadinfo.hpp b/components/esm/loadinfo.hpp index ca08c3b55..2361ed9eb 100644 --- a/components/esm/loadinfo.hpp +++ b/components/esm/loadinfo.hpp @@ -13,8 +13,6 @@ namespace ESM class ESMReader; class ESMWriter; -// NOT DONE - /* * Dialogue information. A series of these follow after DIAL records, * and form a linked list of dialogue items. @@ -44,9 +42,7 @@ struct DialInfo struct SelectStruct { std::string mSelectRule; // This has a complicated format - float mF; // Only one of 'f' or 'i' is used - int mI; - VarType mType; + Variant mValue; }; // Journal quest indices (introduced with the quest system in Tribunal) @@ -94,8 +90,7 @@ struct DialInfo REC_SNAM = 0x4d414e53, REC_NAME = 0x454d414e, REC_SCVR = 0x52564353, - REC_INTV = 0x56544e49, - REC_FLTV = 0x56544c46, + REC_BNAM = 0x4d414e42, REC_QSTN = 0x4e545351, REC_QSTF = 0x46545351, @@ -107,42 +102,5 @@ struct DialInfo void save(ESMWriter &esm); }; -/* - Some old and unused D code and comments, that might be useful later: - -------- - - // We only need to put each item in ONE list. For if your NPC - // matches this response, then it must match ALL criteria, thus it - // will have to look up itself in all the lists. I think the order - // is well optimized in making the lists as small as possible. - if(this.actor.index != -1) actorDial[this.actor][parent]++; - else if(cell != "") cellDial[cell][parent]++; - else if(this.Class != -1) classDial[this.Class][parent]++; - else if(this.npcFaction != -1) - factionDial[this.npcFaction][parent]++; - else if(this.race != -1) raceDial[this.race][parent]++; - else allDial[parent]++; // Lists dialogues that might - // apply to all npcs. - */ - -// List of dialogue topics (and greetings, voices, etc.) that -// reference other objects. Eg. raceDial is indexed by the indices of -// all races referenced. The value of raceDial is a new AA, which is -// basically used as a map (the int value is just a count and isn't -// used for anything important.) The indices (or elements of the map) -// are the dialogues that reference the given race. I use an AA -// instead of a list or array, since each dialogue can be added lots -// of times. - -/* -int allDial[Dialogue*]; -int classDial[int][Dialogue*]; -int factionDial[int][Dialogue*]; -int actorDial[Item][Dialogue*]; -// If I look up cells on cell load, I don't have to resolve these -// names into anything! -int cellDial[char[]][Dialogue*]; -int raceDial[int][Dialogue*]; -*/ } #endif diff --git a/components/esm/variant.cpp b/components/esm/variant.cpp index 98786c20e..d25072e54 100644 --- a/components/esm/variant.cpp +++ b/components/esm/variant.cpp @@ -79,7 +79,7 @@ void ESM::Variant::read (ESMReader& esm, Format format) else esm.fail ("illegal global variable type " + typeId); } - else // GMST + else if (format==Format_Gmst) { if (!esm.hasMoreSubs()) { @@ -106,6 +106,22 @@ void ESM::Variant::read (ESMReader& esm, Format format) esm.fail ("invalid subrecord: " + name.toString()); } } + else // info + { + esm.getSubName(); + NAME name = esm.retSubName(); + + if (name=="INTV") + { + type = VT_Int; + } + else if (name=="FLTV") + { + type = VT_Float; + } + else + esm.fail ("invalid subrecord: " + name.toString()); + } setType (type); @@ -125,6 +141,9 @@ void ESM::Variant::write (ESMWriter& esm, Format format) const if (format==Format_Global) throw std::runtime_error ("can not serialise variant of type none to global format"); + if (format==Format_Info) + throw std::runtime_error ("can not serialise variant of type none to info format"); + // nothing to do here for GMST format } else diff --git a/components/esm/variant.hpp b/components/esm/variant.hpp index b78d647a8..8c5f3b3d4 100644 --- a/components/esm/variant.hpp +++ b/components/esm/variant.hpp @@ -32,7 +32,8 @@ namespace ESM enum Format { Format_Global, - Format_Gmst + Format_Gmst, + Format_Info }; Variant(); diff --git a/components/esm/variantimp.cpp b/components/esm/variantimp.cpp index 1b8cf4f87..160402aa4 100644 --- a/components/esm/variantimp.cpp +++ b/components/esm/variantimp.cpp @@ -78,6 +78,9 @@ void ESM::VariantStringData::read (ESMReader& esm, Variant::Format format, VarTy if (format==Variant::Format_Global) esm.fail ("global variables of type string not supported"); + if (format==Variant::Format_Info) + esm.fail ("info variables of type string not supported"); + // GMST mValue = esm.getHString(); } @@ -90,6 +93,9 @@ void ESM::VariantStringData::write (ESMWriter& esm, Variant::Format format, VarT if (format==Variant::Format_Global) throw std::runtime_error ("global variables of type string not supported"); + if (format==Variant::Format_Info) + throw std::runtime_error ("info variables of type string not supported"); + // GMST esm.writeHNString ("STRV", mValue); } @@ -154,10 +160,16 @@ void ESM::VariantIntegerData::read (ESMReader& esm, Variant::Format format, VarT else esm.fail ("unsupported global variable integer type"); } - else // GMST + else if (format==Variant::Format_Gmst || format==Variant::Format_Info) { if (type!=VT_Int) - esm.fail ("unsupported gmst variable integer type"); + { + std::ostringstream stream; + stream + << "unsupported " <<(format==Variant::Format_Gmst ? "gmst" : "info") + << " variable integer type"; + esm.fail (stream.str()); + } esm.getHT (mValue); } @@ -179,10 +191,16 @@ void ESM::VariantIntegerData::write (ESMWriter& esm, Variant::Format format, Var else throw std::runtime_error ("unsupported global variable integer type"); } - else // GMST + else if (format==Variant::Format_Gmst || format==Variant::Format_Info) { if (type==VT_Int) - throw std::runtime_error ("unsupported global variable integer type"); + { + std::ostringstream stream; + stream + << "unsupported " <<(format==Variant::Format_Gmst ? "gmst" : "info") + << " variable integer type"; + throw std::runtime_error (stream.str()); + } esm.writeHNT ("INTV", mValue); } @@ -234,7 +252,7 @@ void ESM::VariantFloatData::read (ESMReader& esm, Variant::Format format, VarTyp { esm.getHNT (mValue, "FLTV"); } - else // GMST + else if (format==Variant::Format_Gmst || format==Variant::Format_Info) { esm.getHT (mValue); } @@ -250,9 +268,9 @@ void ESM::VariantFloatData::write (ESMWriter& esm, Variant::Format format, VarTy esm.writeHNString ("FNAM", "f"); esm.writeHNT ("FLTV", mValue); } - else // GMST + else if (format==Variant::Format_Gmst || format==Variant::Format_Info) { - esm.writeHNT ("INTV", mValue); + esm.writeHNT ("FLTV", mValue); } } From 46de45b9a2a70ad4a67995a690a5ed2265f835c9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 5 Mar 2013 11:37:13 +0100 Subject: [PATCH 125/151] added var type column to globals --- apps/opencs/model/doc/document.cpp | 2 +- apps/opencs/model/world/columnbase.hpp | 3 ++- apps/opencs/model/world/columns.hpp | 20 ++++++++++++++++---- apps/opencs/model/world/data.cpp | 5 +++-- apps/opencs/view/doc/viewmanager.cpp | 6 +++++- apps/opencs/view/world/vartypedelegate.cpp | 2 +- 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 6a76b0b6c..e709cc5bf 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -152,7 +152,7 @@ void CSMDoc::Document::addOptionalGlobals() { ESM::Global global; global.mId = sGlobals[i]; - global.mValue.setType (ESM::VT_Int); + global.mValue.setType (ESM::VT_Long); addOptionalGlobal (global); } } diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 40581972e..c44abda2b 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -30,7 +30,8 @@ namespace CSMWorld Display_Integer, Display_Float, Display_Var, - Display_VarType + Display_GmstVarType, + Display_GlobalVarType }; std::string mTitle; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 270987ec1..018825831 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -96,7 +96,7 @@ namespace CSMWorld template struct VarTypeColumn : public Column { - VarTypeColumn() : Column ("Type", ColumnBase::Display_VarType) {} + VarTypeColumn (ColumnBase::Display display) : Column ("Type", display) {} virtual QVariant get (const Record& record) const { @@ -125,9 +125,19 @@ namespace CSMWorld { switch (record.get().mValue.getType()) { - case ESM::VT_String: return record.get().mValue.getString().c_str(); break; - case ESM::VT_Int: return record.get().mValue.getInteger(); break; - case ESM::VT_Float: return record.get().mValue.getFloat(); break; + case ESM::VT_String: + + return record.get().mValue.getString().c_str(); break; + + case ESM::VT_Int: + case ESM::VT_Short: + case ESM::VT_Long: + + return record.get().mValue.getInteger(); break; + + case ESM::VT_Float: + + return record.get().mValue.getFloat(); break; default: return QVariant(); } @@ -145,6 +155,8 @@ namespace CSMWorld break; case ESM::VT_Int: + case ESM::VT_Short: + case ESM::VT_Long: record2.mValue.setInteger (data.toInt()); break; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index d4704b0c6..bbd8667b3 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -27,12 +27,13 @@ CSMWorld::Data::Data() mGlobals.addColumn (new StringIdColumn); mGlobals.addColumn (new RecordStateColumn); mGlobals.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Global)); - mGlobals.addColumn (new FloatValueColumn); + mGlobals.addColumn (new VarTypeColumn (ColumnBase::Display_GlobalVarType)); + mGlobals.addColumn (new VarValueColumn); mGmsts.addColumn (new StringIdColumn); mGmsts.addColumn (new RecordStateColumn); mGmsts.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Gmst)); - mGmsts.addColumn (new VarTypeColumn); + mGmsts.addColumn (new VarTypeColumn (ColumnBase::Display_GmstVarType)); mGmsts.addColumn (new VarValueColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index a8faefb97..718b80728 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -35,8 +35,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) { mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; - mDelegateFactories->add (CSMWorld::ColumnBase::Display_VarType, + mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType, new CSVWorld::VarTypeDelegateFactory (ESM::VT_None, ESM::VT_String, ESM::VT_Int, ESM::VT_Float)); + + mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType, + new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float)); + } CSVDoc::ViewManager::~ViewManager() diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index 3ee759ef2..72cbaae42 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -85,7 +85,7 @@ void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) { { ESM::VT_None, "empty" }, { ESM::VT_Short, "short" }, - { ESM::VT_Int, "long" }, + { ESM::VT_Int, "integer" }, { ESM::VT_Long, "long" }, { ESM::VT_Float, "float" }, { ESM::VT_String, "string" }, From 2486ec6cb9edc637367bd95ff8081581a06d5f80 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Mar 2013 13:51:48 +0100 Subject: [PATCH 126/151] Material fixes (vertex colors, alpha) --- apps/openmw/mwrender/renderingmanager.cpp | 6 +- components/nifogre/ogrenifloader.cpp | 11 +- files/materials/objects.mat | 14 +-- files/materials/objects.shader | 135 ++++++---------------- files/materials/terrain.shader | 21 +--- 5 files changed, 53 insertions(+), 134 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3f559c9fd..44385e662 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -102,6 +102,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // Set default mipmap level (NB some APIs ignore this) // Mipmap generation is currently disabled because it causes issues on Intel/AMD //TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General")); + TextureManager::getSingleton().setDefaultNumMipmaps(0); // Set default texture filtering options TextureFilterOptions tfo; @@ -128,7 +129,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); sh::Factory::getInstance ().setGlobalSetting ("fog", "true"); - sh::Factory::getInstance ().setGlobalSetting ("lighting", "true"); sh::Factory::getInstance ().setGlobalSetting ("num_lights", Settings::Manager::getString ("num lights", "Objects")); sh::Factory::getInstance ().setGlobalSetting ("terrain_num_lights", Settings::Manager::getString ("num lights", "Terrain")); sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true"); @@ -329,8 +329,6 @@ void RenderingManager::update (float duration, bool paused) float *_playerPos = data.getPosition().pos; Ogre::Vector3 playerPos(_playerPos[0], _playerPos[1], _playerPos[2]); - Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); - Ogre::Vector3 orig, dest; mPlayer->setCameraDistance(); if (!mPlayer->getPosition(orig, dest)) { @@ -353,6 +351,8 @@ void RenderingManager::update (float duration, bool paused) Ogre::ControllerManager::getSingleton().setTimeFactor(paused ? 0.f : 1.f); + Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); + applyFog(world->isUnderwater (world->getPlayer().getPlayer().getCell(), cam)); if(paused) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 6f7afee43..7057c83e2 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -694,21 +694,24 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String sh::MaterialInstance* instance = sh::Factory::getInstance ().createMaterialInstance (matname, "openmw_objects_base"); if(vertMode == 0 || !vertexColour) { - instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, alpha))); + instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); - instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, alpha))); + instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); + instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("0"))); } else if(vertMode == 1) { - instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, alpha))); + instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); instance->setProperty("emissive", sh::makeProperty(new sh::StringValue("vertexcolour"))); + instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("1"))); } else if(vertMode == 2) { instance->setProperty("ambient", sh::makeProperty(new sh::StringValue("vertexcolour"))); instance->setProperty("diffuse", sh::makeProperty(new sh::StringValue("vertexcolour"))); - instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, alpha))); + instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); + instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("2"))); } else std::cerr<< "Unhandled vertex mode: "< Date: Tue, 5 Mar 2013 14:24:29 +0100 Subject: [PATCH 127/151] Avoid manually updating render targets from within frameRenderingQueued --- apps/openmw/engine.cpp | 7 +++++++ apps/openmw/engine.hpp | 1 + apps/openmw/mwbase/world.hpp | 1 + apps/openmw/mwrender/renderingmanager.cpp | 5 +++++ apps/openmw/mwrender/renderingmanager.hpp | 1 + apps/openmw/mwrender/water.cpp | 10 ++++++++-- apps/openmw/mwrender/water.hpp | 6 +++++- apps/openmw/mwworld/worldimp.cpp | 5 +++++ apps/openmw/mwworld/worldimp.hpp | 1 + 9 files changed, 34 insertions(+), 3 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index ea6e0a2f5..62e106f3f 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -62,6 +62,13 @@ void OMW::Engine::setAnimationVerbose(bool animverbose) { } +bool OMW::Engine::frameStarted (const Ogre::FrameEvent& evt) +{ + if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) + MWBase::Environment::get().getWorld()->frameStarted(evt.timeSinceLastFrame); + return true; +} + bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) { try diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 572d1013e..a4acee523 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -105,6 +105,7 @@ namespace OMW void executeLocalScripts(); virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); + virtual bool frameStarted (const Ogre::FrameEvent& evt); /// Load settings from various files, returns the path to the user settings file std::string loadSettings (Settings::Manager & settings); diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index eef844c76..654a59cea 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -314,6 +314,7 @@ namespace MWBase /// \todo this does not belong here virtual void playVideo(const std::string& name, bool allowSkipping) = 0; virtual void stopVideo() = 0; + virtual void frameStarted (float dt) = 0; }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 44385e662..94daa8a01 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -939,4 +939,9 @@ void RenderingManager::updateWaterRippleEmitterPtr (const MWWorld::Ptr& old, con mWater->updateEmitterPtr(old, ptr); } +void RenderingManager::frameStarted(float dt) +{ + mWater->frameStarted(dt); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index e40672ada..5cea24175 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -196,6 +196,7 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void playVideo(const std::string& name, bool allowSkipping); void stopVideo(); + void frameStarted(float dt); protected: virtual void windowResized(Ogre::RenderWindow* rw); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 2801e6494..c8b9db7f1 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -191,7 +191,8 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend) : mWaterTimer(0.f), mReflection(NULL), mRefraction(NULL), - mSimulation(NULL) + mSimulation(NULL), + mPlayer(0,0) { mSimulation = new RippleSimulation(mSceneMgr); @@ -371,7 +372,12 @@ void Water::update(float dt, Ogre::Vector3 player) mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); - mSimulation->update(dt, Ogre::Vector2(player.x, player.y)); + mPlayer = Ogre::Vector2(player.x, player.y); +} + +void Water::frameStarted(float dt) +{ + mSimulation->update(dt, mPlayer); if (mReflection) mReflection->update(); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 633a30664..6c0323637 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -98,7 +99,7 @@ namespace MWRender { }; /// Water rendering - class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener, public sh::MaterialInstanceListener + class Water : public sh::MaterialInstanceListener { static const int CELL_SIZE = 8192; Ogre::Camera *mCamera; @@ -139,6 +140,8 @@ namespace MWRender { Refraction* mRefraction; RippleSimulation* mSimulation; + Ogre::Vector2 mPlayer; + public: Water (Ogre::Camera *camera, RenderingManager* rend); ~Water(); @@ -147,6 +150,7 @@ namespace MWRender { void toggle(); void update(float dt, Ogre::Vector3 player); + void frameStarted(float dt); /// adds an emitter, position will be tracked automatically using its scene node void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index cddcda68b..970b339bd 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1469,4 +1469,9 @@ namespace MWWorld { mRendering->stopVideo(); } + + void World::frameStarted (float dt) + { + mRendering->frameStarted(dt); + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 0ae81b33a..79d036e99 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -356,6 +356,7 @@ namespace MWWorld /// \todo this does not belong here virtual void playVideo(const std::string& name, bool allowSkipping); virtual void stopVideo(); + virtual void frameStarted (float dt); }; } From ff30bef3b2cc4a7186e8d928613adf292c1aa20b Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Mar 2013 14:27:05 +0100 Subject: [PATCH 128/151] Mipmap fix --- files/materials/water.mat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/materials/water.mat b/files/materials/water.mat index 3ea6a2c2b..0ec71d2df 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -37,7 +37,7 @@ material Water texture_unit normalMap { - direct_texture water_nm.png + texture water_nm.png 5 } texture_unit rippleNormalMap From 7f8d659f3cad7361b4b10ea7a23f12418d64c8b5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 Mar 2013 17:09:20 +0100 Subject: [PATCH 129/151] Fix transparency sorting --- components/nifogre/ogrenifloader.cpp | 3 ++- extern/shiny/Platforms/Ogre/OgreMaterialSerializer.cpp | 9 +++++++++ extern/shiny/Platforms/Ogre/OgrePass.cpp | 7 ------- files/materials/objects.mat | 2 ++ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 7057c83e2..30c71023b 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -755,7 +755,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String instance->setProperty("alpha_rejection", sh::makeProperty(new sh::StringValue(reject))); } - instance->setProperty("transparent_sorting", sh::makeProperty(new sh::StringValue(!((alphaFlags>>13)&1) ? "on" : "off"))); + // 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("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/extern/shiny/Platforms/Ogre/OgreMaterialSerializer.cpp b/extern/shiny/Platforms/Ogre/OgreMaterialSerializer.cpp index 9f57c7b44..4ec43fcae 100644 --- a/extern/shiny/Platforms/Ogre/OgreMaterialSerializer.cpp +++ b/extern/shiny/Platforms/Ogre/OgreMaterialSerializer.cpp @@ -1,5 +1,7 @@ #include "OgreMaterialSerializer.hpp" +#include + namespace sh { void OgreMaterialSerializer::reset() @@ -19,6 +21,13 @@ namespace sh bool OgreMaterialSerializer::setPassProperty (const std::string& param, std::string value, Ogre::Pass* pass) { + // workaround https://ogre3d.atlassian.net/browse/OGRE-158 + if (param == "transparent_sorting" && value == "force") + { + pass->setTransparentSortingForced(true); + return true; + } + reset(); mScriptContext.section = Ogre::MSS_PASS; diff --git a/extern/shiny/Platforms/Ogre/OgrePass.cpp b/extern/shiny/Platforms/Ogre/OgrePass.cpp index 8cfaae078..3ed48b96f 100644 --- a/extern/shiny/Platforms/Ogre/OgrePass.cpp +++ b/extern/shiny/Platforms/Ogre/OgrePass.cpp @@ -50,13 +50,6 @@ namespace sh return true; // handled already else if (name == "fragment_program") return true; // handled already - else if (name == "ffp_vertex_colour_ambient") - { - bool enabled = retrieveValue(value, context).get(); - // fixed-function vertex colour tracking - mPass->setVertexColourTracking(enabled ? Ogre::TVC_AMBIENT : Ogre::TVC_NONE); - return true; - } else { OgreMaterialSerializer& s = OgrePlatform::getSerializer(); diff --git a/files/materials/objects.mat b/files/materials/objects.mat index 069a1036b..5e18a666a 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -11,6 +11,7 @@ material openmw_objects_base scene_blend default depth_write default alpha_rejection default + transparent_sorting default pass { @@ -30,6 +31,7 @@ material openmw_objects_base scene_blend $scene_blend alpha_rejection $alpha_rejection depth_write $depth_write + transparent_sorting $transparent_sorting texture_unit diffuseMap { From 9133182f2fb87b3a02a35a853b22b0f37337a249 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 5 Mar 2013 20:25:20 +0400 Subject: [PATCH 130/151] restore loading CELL records in esmtool --- components/esm/loadcell.cpp | 12 +++++++++++- components/esm/loadcell.hpp | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 92cb7d5ce..76a48e5ec 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -79,7 +79,7 @@ void CellRef::save(ESMWriter &esm) } } -void Cell::load(ESMReader &esm, MWWorld::ESMStore &store) +void Cell::load(ESMReader &esm, bool saveContext) { // Ignore this for now, it might mean we should delete the entire // cell? @@ -127,6 +127,16 @@ void Cell::load(ESMReader &esm, MWWorld::ESMStore &store) esm.getHT(mNAM0); } + if (saveContext) { + mContextList.push_back(esm.getContext()); + esm.skipRecord(); + } +} + +void Cell::load(ESMReader &esm, MWWorld::ESMStore &store) +{ + this->load(esm, false); + // preload moved references while (esm.isNextSub("MVRF")) { CellRef ref; diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index 6bde9972d..7db6dbe77 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -174,7 +174,7 @@ struct Cell // This method is left in for compatibility with esmtool. Parsing moved references currently requires // passing ESMStore, bit it does not know about this parameter, so we do it this way. - void load(ESMReader &esm) {}; + void load(ESMReader &esm, bool saveContext = true); void save(ESMWriter &esm); bool isExterior() const From 8b6f0e0770ef9672fc401618efa91eda52d19292 Mon Sep 17 00:00:00 2001 From: gus Date: Tue, 5 Mar 2013 18:28:57 +0000 Subject: [PATCH 131/151] Correct orientation sign --- apps/openmw/mwrender/renderingmanager.cpp | 36 ++++++++++------------- apps/openmw/mwworld/physicssystem.cpp | 14 ++++----- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b214fd800..abc1960b8 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -270,32 +270,28 @@ bool RenderingManager::rotateObject( const MWWorld::Ptr &ptr, Ogre::Vector3 &rot if (!isPlayer && isActive) { - Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X); - Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y); - Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z); + Ogre::Quaternion xr(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X); + Ogre::Quaternion yr(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y); + Ogre::Quaternion zr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z); - Ogre::Quaternion xref(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::UNIT_X); - Ogre::Quaternion yref(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::UNIT_Y); - Ogre::Quaternion zref(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); + Ogre::Quaternion xref(Ogre::Radian(-ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::UNIT_X); + Ogre::Quaternion yref(Ogre::Radian(-ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::UNIT_Y); + Ogre::Quaternion zref(Ogre::Radian(-ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); - Ogre::Quaternion newo = adjust ? (xr * yr * zr) * (xref*yref*zref) : xr * yr * zr; - rot.x = newo.getPitch().valueRadians();// newo.x;Ogre::Quaternion:: - rot.y = newo.getYaw().valueRadians();//newo.y; - rot.z = newo.getRoll().valueRadians(); //newo.z; + Ogre::Quaternion newo = adjust ? (zr * yr * xr) * (zref*yref*xref) : zr * yr * xr; + Ogre::Radian ax,ay,az; + Ogre::Matrix3 mat; + newo.ToRotationMatrix(mat); + mat.ToEulerAnglesXYZ(ax,ay,az); + rot.x = -ax.valueRadians(); + rot.y = -ay.valueRadians(); + rot.z = -az.valueRadians(); ptr.getRefData().getBaseNode()->setOrientation(newo); } else if(isPlayer) { - rot.x = mPlayer->getPitch(); - rot.z = -mPlayer->getYaw(); - } - else if (adjust) - { - // Stored and passed in radians - float *f = ptr.getRefData().getPosition().rot; - rot.x += f[0]; - rot.y += f[1]; - rot.z += f[2]; + rot.x = -mPlayer->getPitch(); + rot.z = mPlayer->getYaw(); } return force; } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 316e57b78..c1c33cb5d 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -99,9 +99,9 @@ namespace MWWorld if(!physicActor || !physicActor->getCollisionMode()) { // FIXME: This works, but it's inconcsistent with how the rotations are applied elsewhere. Why? - return position + (Ogre::Quaternion(Ogre::Radian( refpos.rot[2]), Ogre::Vector3::UNIT_Z)* - Ogre::Quaternion(Ogre::Radian( refpos.rot[1]), Ogre::Vector3::UNIT_Y)* - Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * + return position + (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)* + Ogre::Quaternion(Ogre::Radian( -refpos.rot[1]), Ogre::Vector3::UNIT_Y)* + Ogre::Quaternion(Ogre::Radian( -refpos.rot[0]), Ogre::Vector3::UNIT_X)) * movement; } @@ -115,9 +115,9 @@ namespace MWWorld Ogre::Vector3 velocity; if(!gravity) { - velocity = (Ogre::Quaternion(Ogre::Radian( refpos.rot[2]), Ogre::Vector3::UNIT_Z)* - Ogre::Quaternion(Ogre::Radian( refpos.rot[1]), Ogre::Vector3::UNIT_Y)* - Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * + velocity = (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)* + Ogre::Quaternion(Ogre::Radian( -refpos.rot[1]), Ogre::Vector3::UNIT_Y)* + Ogre::Quaternion(Ogre::Radian( -refpos.rot[0]), Ogre::Vector3::UNIT_X)) * movement / time; } else @@ -128,7 +128,7 @@ namespace MWWorld if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope) onground = true; } - velocity = Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::UNIT_Z)*movement / time; + velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)*movement / time; velocity.z += physicActor->getVerticalForce(); } From d3bf3812a44eb3f40eadf197d091cbc2d61b0cc0 Mon Sep 17 00:00:00 2001 From: gus Date: Tue, 5 Mar 2013 20:16:57 +0000 Subject: [PATCH 132/151] changing rotation order (fix some misoriented objects) --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index abc1960b8..8bad0d17e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -278,7 +278,7 @@ bool RenderingManager::rotateObject( const MWWorld::Ptr &ptr, Ogre::Vector3 &rot Ogre::Quaternion yref(Ogre::Radian(-ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::UNIT_Y); Ogre::Quaternion zref(Ogre::Radian(-ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); - Ogre::Quaternion newo = adjust ? (zr * yr * xr) * (zref*yref*xref) : zr * yr * xr; + Ogre::Quaternion newo = adjust ? (xr * yr * zr) * (xref*yref*zref) : xr * yr * zr; Ogre::Radian ax,ay,az; Ogre::Matrix3 mat; newo.ToRotationMatrix(mat); From c9859382bf70ef009a9a3f932e0a1ad6b2bf261d Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 6 Mar 2013 01:35:32 +0100 Subject: [PATCH 133/151] Made the launcher write the custom resolution to file, cleaned resolution parsing --- apps/launcher/graphicspage.cpp | 43 ++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 590504354..6d5b3ab09 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -190,11 +190,17 @@ void GraphicsPage::saveSettings() mGraphicsSettings.setValue(QString("Video/antialiasing"), antiAliasingComboBox->currentText()); mGraphicsSettings.setValue(QString("Video/render system"), rendererComboBox->currentText()); - QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); - if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) { - mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); - mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); + if (standardRadioButton->isChecked()) { + QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); + + if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) { + mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); + mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); + } + } else { + mGraphicsSettings.setValue(QString("Video/resolution x"), QString::number(customWidthSpinBox->value())); + mGraphicsSettings.setValue(QString("Video/resolution y"), QString::number(customHeightSpinBox->value())); } } @@ -250,25 +256,26 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) for (opt_it = i->second.possibleValues.begin (); opt_it != i->second.possibleValues.end (); opt_it++, idx++) { - QString qval = QString::fromStdString(*opt_it).simplified(); - // remove extra tokens after the resolution (for example bpp, can be there or not depending on rendersystem) - QStringList tokens = qval.split(" ", QString::SkipEmptyParts); - assert (tokens.size() >= 3); + QRegExp resolutionRe(QString("(\\d+) x (\\d+)")); + QString resolution = QString::fromStdString(*opt_it).simplified(); - QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2); + if (resolutionRe.exactMatch(resolution)) { - QString aspect = getAspect(tokens.at(0).toInt(),tokens.at(2).toInt()); + int width = resolutionRe.cap(1).toInt(); + int height = resolutionRe.cap(2).toInt(); - if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) { - resolutionStr.append(tr("\t(Widescreen ") + aspect + ")"); + QString aspect = getAspect(width, height); - } else if (aspect == QLatin1String("4:3")) { - resolutionStr.append(tr("\t(Standard 4:3)")); + if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) { + resolution.append(tr("\t(Wide ") + aspect + ")"); + + } else if (aspect == QLatin1String("4:3")) { + resolution.append(tr("\t(Standard 4:3)")); + } + // do not add duplicate resolutions + if (!result.contains(resolution)) + result.append(resolution); } - - // do not add duplicate resolutions - if (!result.contains(resolutionStr)) - result << resolutionStr; } } From 39411eda7b663622582615d11e59c767e53dafc2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 Mar 2013 15:11:40 +0100 Subject: [PATCH 134/151] Fix the spell buying window listing already owned spells --- apps/openmw/mwgui/spellbuyingwindow.cpp | 19 ++++++++++++++----- apps/openmw/mwgui/spellbuyingwindow.hpp | 2 ++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 11f090494..40fcf2988 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -94,9 +94,6 @@ namespace MWGui mPtr = actor; clearSpells(); - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - - MWMechanics::Spells& playerSpells = MWWorld::Class::get (player).getCreatureStats (player).getSpells(); MWMechanics::Spells& merchantSpells = MWWorld::Class::get (actor).getCreatureStats (actor).getSpells(); for (MWMechanics::Spells::TIterator iter = merchantSpells.begin(); iter!=merchantSpells.end(); ++iter) @@ -107,8 +104,8 @@ namespace MWGui if (spell->mData.mType!=ESM::Spell::ST_Spell) continue; // don't try to sell diseases, curses or powers - if (std::find (playerSpells.begin(), playerSpells.end(), *iter)!=playerSpells.end()) - continue; // we have that spell already + if (playerHasSpell(iter->first)) + continue; addSpell (iter->first); } @@ -118,6 +115,18 @@ namespace MWGui mSpellsView->setCanvasSize (MyGUI::IntSize(mSpellsView->getWidth(), std::max(mSpellsView->getHeight(), mCurrentY))); } + bool SpellBuyingWindow::playerHasSpell(const std::string &id) + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::Spells& playerSpells = MWWorld::Class::get (player).getCreatureStats (player).getSpells(); + for (MWMechanics::Spells::TIterator it = playerSpells.begin(); it != playerSpells.end(); ++it) + { + if (Misc::StringUtils::ciEqual(id, it->first)) + return true; + } + return false; + } + void SpellBuyingWindow::onSpellButtonClick(MyGUI::Widget* _sender) { int price = *_sender->getUserData(); diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index 1d0ac28e0..c4988fff3 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -47,6 +47,8 @@ namespace MWGui void updateLabels(); virtual void onReferenceUnavailable(); + + bool playerHasSpell (const std::string& id); }; } From 268bb235908be852c016e3339af60b260036a015 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 Mar 2013 16:58:56 +0100 Subject: [PATCH 135/151] Implemented sneaking animation --- apps/openmw/mwclass/npc.cpp | 3 +-- apps/openmw/mwinput/inputmanagerimp.cpp | 15 +++++------- apps/openmw/mwinput/inputmanagerimp.hpp | 4 ++-- apps/openmw/mwmechanics/character.cpp | 32 +++++++++++++++---------- apps/openmw/mwmechanics/character.hpp | 6 +++++ apps/openmw/mwworld/player.cpp | 7 ++++++ apps/openmw/mwworld/player.hpp | 1 + 7 files changed, 42 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index c8c61e118..b1263c2e5 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -365,11 +365,10 @@ namespace MWClass fSwimRunAthleticsMult->getFloat(); moveSpeed = swimSpeed; } - else if(Npc::getStance(ptr, Run, false)) + else if(Npc::getStance(ptr, Run, false) && !Npc::getStance(ptr, Sneak, false)) moveSpeed = runSpeed; else moveSpeed = walkSpeed; - if(getMovementSettings(ptr).mLeftRight != 0 && getMovementSettings(ptr).mForwardBackward == 0) moveSpeed *= 0.75f; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 69de2988c..4c10749b3 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -193,9 +193,6 @@ namespace MWInput case A_AutoMove: toggleAutoMove (); break; - case A_ToggleSneak: - /// \todo implement - break; case A_ToggleWalk: toggleWalking (); break; @@ -308,13 +305,13 @@ namespace MWInput else mPlayer.setForwardBackward (0); + mPlayer.setSneak(actionIsActive(A_Sneak)); + if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"]) { mPlayer.setUpDown (1); triedToMove = true; } - else if (actionIsActive(A_Crouch)) - mPlayer.setUpDown (-1); else mPlayer.setUpDown (0); @@ -364,7 +361,7 @@ namespace MWInput actionIsActive(A_MoveLeft) || actionIsActive(A_MoveRight) || actionIsActive(A_Jump) || - actionIsActive(A_Crouch) || + actionIsActive(A_Sneak) || actionIsActive(A_TogglePOV)) { resetIdleTime(); @@ -749,7 +746,7 @@ namespace MWInput defaultKeyBindings[A_QuickKeysMenu] = OIS::KC_F1; defaultKeyBindings[A_Console] = OIS::KC_F2; defaultKeyBindings[A_Run] = OIS::KC_LSHIFT; - defaultKeyBindings[A_Crouch] = OIS::KC_LCONTROL; + defaultKeyBindings[A_Sneak] = OIS::KC_LCONTROL; defaultKeyBindings[A_AutoMove] = OIS::KC_Q; defaultKeyBindings[A_Jump] = OIS::KC_E; defaultKeyBindings[A_Journal] = OIS::KC_J; @@ -816,7 +813,7 @@ namespace MWInput descriptions[A_ToggleSpell] = "sReady_Magic"; descriptions[A_Console] = "sConsoleTitle"; descriptions[A_Run] = "sRun"; - descriptions[A_Crouch] = "sCrouch_Sneak"; + descriptions[A_Sneak] = "sCrouch_Sneak"; descriptions[A_AutoMove] = "sAuto_Run"; descriptions[A_Jump] = "sJump"; descriptions[A_Journal] = "sJournal"; @@ -865,7 +862,7 @@ namespace MWInput ret.push_back(A_MoveRight); ret.push_back(A_TogglePOV); ret.push_back(A_Run); - ret.push_back(A_Crouch); + ret.push_back(A_Sneak); ret.push_back(A_Activate); ret.push_back(A_ToggleWeapon); ret.push_back(A_ToggleSpell); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index d4f47723d..8bb20b7be 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -216,9 +216,9 @@ namespace MWInput A_CycleSpellRight, A_CycleWeaponLeft,//Cycling through weapons A_CycleWeaponRight, - A_ToggleSneak, //Toggles Sneak, add Push-Sneak later + A_ToggleSneak, //Toggles Sneak A_ToggleWalk, //Toggle Walking/Running - A_Crouch, + A_Sneak, A_QuickSave, A_QuickLoad, diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index ae0114a35..62958db8d 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -46,6 +46,7 @@ static const struct { { CharState_Idle8, "idle8" }, { CharState_Idle9, "idle9" }, { CharState_IdleSwim, "idleswim" }, + { CharState_IdleSneak, "idlesneak" }, { CharState_WalkForward, "walkforward" }, { CharState_WalkBack, "walkback" }, @@ -67,6 +68,11 @@ static const struct { { CharState_SwimRunLeft, "swimrunleft" }, { CharState_SwimRunRight, "swimrunright" }, + { CharState_SneakForward, "sneakforward" }, + { CharState_SneakBack, "sneakback" }, + { CharState_SneakLeft, "sneakleft" }, + { CharState_SneakRight, "sneakright" }, + { CharState_Jump, "jump" }, { CharState_Death1, "death1" }, @@ -176,6 +182,7 @@ Ogre::Vector3 CharacterController::update(float duration) bool onground = world->isOnGround(mPtr); bool inwater = world->isSwimming(mPtr); bool isrunning = cls.getStance(mPtr, MWWorld::Class::Run); + bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak); speed = cls.getSpeed(mPtr); /* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except @@ -201,31 +208,30 @@ Ogre::Vector3 CharacterController::update(float duration) if(std::abs(vec.x/2.0f) > std::abs(vec.y) && speed > 0.0f) { if(vec.x > 0.0f) - setState(isrunning ? - (inwater ? CharState_SwimRunRight : CharState_RunRight) : - (inwater ? CharState_SwimWalkRight : CharState_WalkRight), true); + setState(inwater ? (isrunning ? CharState_SwimRunRight : CharState_SwimWalkRight) + : (sneak ? CharState_SneakRight : (isrunning ? CharState_RunRight : CharState_WalkRight)), true); + else if(vec.x < 0.0f) - setState(isrunning ? - (inwater ? CharState_SwimRunLeft: CharState_RunLeft) : - (inwater ? CharState_SwimWalkLeft : CharState_WalkLeft), true); + setState(inwater ? (isrunning ? CharState_SwimRunLeft : CharState_SwimWalkLeft) + : (sneak ? CharState_SneakLeft : (isrunning ? CharState_RunLeft : CharState_WalkLeft)), true); + // Apply any forward/backward movement manually movement.y += vec.y * (speed*duration); } else if(vec.y != 0.0f && speed > 0.0f) { if(vec.y > 0.0f) - setState(isrunning ? - (inwater ? CharState_SwimRunForward : CharState_RunForward) : - (inwater ? CharState_SwimWalkForward : CharState_WalkForward), true); + setState(inwater ? (isrunning ? CharState_SwimRunForward : CharState_SwimWalkForward) + : (sneak ? CharState_SneakForward : (isrunning ? CharState_RunForward : CharState_WalkForward)), true); + else if(vec.y < 0.0f) - setState(isrunning ? - (inwater ? CharState_SwimRunBack : CharState_RunBack) : - (inwater ? CharState_SwimWalkBack : CharState_WalkBack), true); + setState(inwater ? (isrunning ? CharState_SwimRunBack : CharState_SwimWalkBack) + : (sneak ? CharState_SneakBack : (isrunning ? CharState_RunBack : CharState_WalkBack)), true); // Apply any sideways movement manually movement.x += vec.x * (speed*duration); } else if(mAnimQueue.size() == 0) - setState((inwater ? CharState_IdleSwim : CharState_Idle), true); + setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true); } if(mAnimation && !mSkipAnim) diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 2b3c50864..46f0690e7 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -25,6 +25,7 @@ enum CharacterState { CharState_Idle8, CharState_Idle9, CharState_IdleSwim, + CharState_IdleSneak, CharState_WalkForward, CharState_WalkBack, @@ -46,6 +47,11 @@ enum CharacterState { CharState_SwimRunLeft, CharState_SwimRunRight, + CharState_SneakForward, + CharState_SneakBack, + CharState_SneakLeft, + CharState_SneakRight, + CharState_Jump, /* Death states must be last! */ diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 76d44a5d7..03dd1abc7 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -86,6 +86,13 @@ namespace MWWorld MWWorld::Class::get (ptr).setStance (ptr, MWWorld::Class::Run, !running); } + void Player::setSneak(bool sneak) + { + MWWorld::Ptr ptr = getPlayer(); + + MWWorld::Class::get (ptr).setStance (ptr, MWWorld::Class::Sneak, sneak); + } + MWMechanics::DrawState_ Player::getDrawState() { MWWorld::Ptr ptr = getPlayer(); diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 4ef4d6771..5f2fc3a08 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -67,6 +67,7 @@ namespace MWWorld void setRunState(bool run); void toggleRunning(); + void setSneak(bool sneak); }; } #endif From 66d2d3522f3fa94f73a0a23d942eb20b1405f0d5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 Mar 2013 18:03:47 +0100 Subject: [PATCH 136/151] Race selection preview: render only the head, and focus the camera on its node --- apps/openmw/mwrender/characterpreview.cpp | 20 +++++++++++++++++--- apps/openmw/mwrender/characterpreview.hpp | 8 ++++++++ apps/openmw/mwrender/npcanimation.cpp | 15 ++++++++++++--- apps/openmw/mwrender/npcanimation.hpp | 5 ++++- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 4a3344e22..c99e42662 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -60,7 +60,7 @@ namespace MWRender mNode = renderRoot->createChildSceneNode(); mAnimation = new NpcAnimation(mCharacter, mNode, - MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0); + MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0, renderHeadOnly()); mNode->setVisible (false); @@ -102,7 +102,7 @@ namespace MWRender delete mAnimation; mAnimation = new NpcAnimation(mCharacter, mNode, - MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0); + MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0, renderHeadOnly()); mNode->setVisible (false); @@ -161,7 +161,7 @@ namespace MWRender RaceSelectionPreview::RaceSelectionPreview() : CharacterPreview(MWBase::Environment::get().getWorld()->getPlayer().getPlayer(), - 512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 120, -35), Ogre::Vector3(0,125,0)) + 512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 6, -35), Ogre::Vector3(0,125,0)) , mRef(&mBase) { mBase = *mCharacter.get()->mBase; @@ -173,6 +173,8 @@ namespace MWRender mAnimation->runAnimation(0.0f); mNode->roll(Ogre::Radian(angle), Ogre::SceneNode::TS_LOCAL); + updateCamera(); + mNode->setVisible (true); mRenderTarget->update(); mNode->setVisible (false); @@ -189,5 +191,17 @@ namespace MWRender void RaceSelectionPreview::onSetup () { mAnimation->play("idle", "start", "stop", false); + + updateCamera(); + } + + void RaceSelectionPreview::updateCamera() + { + Ogre::Vector3 scale = mNode->getScale(); + Ogre::Vector3 headOffset = mAnimation->getHeadNode()->_getDerivedPosition(); + headOffset = mNode->convertLocalToWorldPosition(headOffset); + + mCamera->setPosition(headOffset + mPosition * scale); + mCamera->lookAt(headOffset + mPosition*Ogre::Vector3(0,1,0) * scale); } } diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index cf1e25069..08cbd5108 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -36,6 +36,8 @@ namespace MWRender virtual void rebuild(); protected: + virtual bool renderHeadOnly() { return false; } + Ogre::TexturePtr mTexture; Ogre::RenderTarget* mRenderTarget; Ogre::Viewport* mViewport; @@ -82,6 +84,12 @@ namespace MWRender ESM::NPC mBase; MWWorld::LiveCellRef mRef; + protected: + + virtual bool renderHeadOnly() { return true; } + + void updateCamera(); + public: RaceSelectionPreview(); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index a7d5c22af..9da70beb4 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -54,7 +54,7 @@ NpcAnimation::~NpcAnimation() } -NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& inv, int visibilityFlags) +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& inv, int visibilityFlags, bool headOnly) : Animation(ptr), mStateID(-1), mTimeToChange(0), @@ -70,7 +70,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor mPants(inv.end()), mGloveL(inv.end()), mGloveR(inv.end()), - mSkirtIter(inv.end()) + mSkirtIter(inv.end()), + mHeadOnly(headOnly) { mNpc = mPtr.get()->mBase; @@ -215,7 +216,7 @@ void NpcAnimation::updateParts(bool forceupdate) if(!forceupdate) return; - for(size_t i = 0;i < slotlistsize;i++) + for(size_t i = 0;i < slotlistsize && !mHeadOnly;i++) { MWWorld::ContainerStoreIterator iter = inv.getSlot(slotlist[i].slot); @@ -252,6 +253,9 @@ void NpcAnimation::updateParts(bool forceupdate) if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1) addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel); + if (mHeadOnly) + return; + static const struct { ESM::PartReferenceType type; const char name[2][12]; @@ -449,4 +453,9 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vectorgetSkeleton()->getBone("Bip01 Head"); +} + } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index aed4868bd..5da4afef8 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -39,6 +39,7 @@ private: std::string mHeadModel; std::string mHairModel; std::string mBodyPrefix; + bool mHeadOnly; float mTimeToChange; MWWorld::ContainerStoreIterator mRobe; @@ -73,11 +74,13 @@ private: public: NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, - MWWorld::InventoryStore& inv, int visibilityFlags); + MWWorld::InventoryStore& inv, int visibilityFlags, bool headOnly=false); virtual ~NpcAnimation(); virtual Ogre::Vector3 runAnimation(float timepassed); + Ogre::Node* getHeadNode(); + void forceUpdate() { updateParts(true); } }; From 5938e19362a2acc7d6897be32724fda00c4b9398 Mon Sep 17 00:00:00 2001 From: gus Date: Wed, 6 Mar 2013 17:31:57 +0000 Subject: [PATCH 137/151] Clean up --- apps/openmw/mwrender/renderingmanager.cpp | 4 +++- libs/openengine/bullet/physic.cpp | 23 +++++++---------------- libs/openengine/bullet/physic.hpp | 8 ++++++++ libs/openengine/bullet/trace.cpp | 20 +------------------- 4 files changed, 19 insertions(+), 36 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 8bad0d17e..1cd7c7a3e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -279,13 +279,15 @@ bool RenderingManager::rotateObject( const MWWorld::Ptr &ptr, Ogre::Vector3 &rot Ogre::Quaternion zref(Ogre::Radian(-ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); Ogre::Quaternion newo = adjust ? (xr * yr * zr) * (xref*yref*zref) : xr * yr * zr; - Ogre::Radian ax,ay,az; + Ogre::Matrix3 mat; newo.ToRotationMatrix(mat); + Ogre::Radian ax,ay,az; mat.ToEulerAnglesXYZ(ax,ay,az); rot.x = -ax.valueRadians(); rot.y = -ay.valueRadians(); rot.z = -az.valueRadians(); + ptr.getRefData().getBaseNode()->setOrientation(newo); } else if(isPlayer) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 677d75f33..435ceef23 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -13,18 +13,9 @@ #include #include -#define BIT(x) (1<<(x)) - namespace OEngine { namespace Physic { - enum collisiontypes { - COL_NOTHING = 0, //addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); + dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal); } void PhysicEngine::removeHeightField(int x, int y) @@ -401,11 +392,11 @@ namespace Physic return; if(body->mCollide) { - dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); + dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal); } else { - dynamicsWorld->addRigidBody(body,COL_RAYCASTING,COL_RAYCASTING|COL_WORLD); + dynamicsWorld->addRigidBody(body,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_World); } body->setActivationState(DISABLE_DEACTIVATION); if(addToMap){ @@ -539,7 +530,7 @@ namespace Physic float d1 = 10000.; btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); - resultCallback1.m_collisionFilterMask = COL_WORLD|COL_RAYCASTING; + resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_Raycasting; dynamicsWorld->rayTest(from, to, resultCallback1); if (resultCallback1.hasHit()) { @@ -549,7 +540,7 @@ namespace Physic } btCollisionWorld::ClosestRayResultCallback resultCallback2(from, to); - resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; + resultCallback2.m_collisionFilterMask = CollisionType_ActorInternal|CollisionType_ActorExternal; dynamicsWorld->rayTest(from, to, resultCallback2); float d2 = 10000.; if (resultCallback2.hasHit()) @@ -568,12 +559,12 @@ namespace Physic std::vector< std::pair > PhysicEngine::rayTest2(btVector3& from, btVector3& to) { MyRayResultCallback resultCallback1; - resultCallback1.m_collisionFilterMask = COL_WORLD|COL_RAYCASTING; + resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_Raycasting; dynamicsWorld->rayTest(from, to, resultCallback1); std::vector< std::pair > results = resultCallback1.results; MyRayResultCallback resultCallback2; - resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; + resultCallback2.m_collisionFilterMask = CollisionType_ActorInternal|CollisionType_ActorExternal; dynamicsWorld->rayTest(from, to, resultCallback2); std::vector< std::pair > actorResults = resultCallback2.results; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index e579e3546..97fbbcea4 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -43,6 +43,14 @@ namespace Physic class PhysicEngine; class RigidBody; + enum CollisionType { + CollisionType_Nothing = 0, //dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback); From 642653d10e12eeeb6cef02a63f62480687499bb6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 6 Mar 2013 19:57:00 +0100 Subject: [PATCH 138/151] World constructor fixes --- apps/openmw/mwworld/worldimp.cpp | 7 +++---- apps/openmw/mwworld/worldimp.hpp | 10 +++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f9e4a743f..7d3efe3e8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -178,10 +178,11 @@ namespace MWWorld const Files::Collections& fileCollections, const std::vector& master, const std::vector& plugins, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, - ToUTF8::Utf8Encoder* encoder, std::map fallbackMap, int mActivationDistanceOverride) + ToUTF8::Utf8Encoder* encoder, const std::map& fallbackMap, int mActivationDistanceOverride) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (true), mCells (mStore, mEsm), - mNumFacing(0), mActivationDistanceOverride (mActivationDistanceOverride) + mNumFacing(0), mActivationDistanceOverride (mActivationDistanceOverride), + mFallback (fallbackMap) { mPhysics = new PhysicsSystem(renderer); mPhysEngine = mPhysics->getEngine(); @@ -247,8 +248,6 @@ namespace MWWorld mWorldScene = new Scene(*mRendering, mPhysics); - setFallbackValues(fallbackMap); - lastTick = mTimer.getMilliseconds(); } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 79d036e99..47088aa62 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -92,7 +92,7 @@ namespace MWWorld bool moveObjectImp (const Ptr& ptr, float x, float y, float z); ///< @return true if the active cell (cell player is in) changed - + Ptr copyObjectToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos); void updateWindowManager (); @@ -116,7 +116,7 @@ namespace MWWorld const Files::Collections& fileCollections, const std::vector& master, const std::vector& plugins, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, - ToUTF8::Utf8Encoder* encoder, std::map fallbackMap, int mActivationDistanceOverride); + ToUTF8::Utf8Encoder* encoder, const std::map& fallbackMap, int mActivationDistanceOverride); virtual ~World(); @@ -174,11 +174,11 @@ namespace MWWorld virtual char getGlobalVariableType (const std::string& name) const; ///< Return ' ', if there is no global variable with this name. - + virtual std::vector getGlobals () const; - + virtual std::string getCurrentCellName () const; - + virtual void removeRefScript (MWWorld::RefData *ref); //< Remove the script attached to ref from mLocalScripts From f7d8f6456f13907502db90bf0540b20826886c1c Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 Mar 2013 20:45:11 +0100 Subject: [PATCH 139/151] Stats should never go below 0 --- apps/openmw/mwmechanics/stat.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index d576020c5..e1bb1994c 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -28,7 +28,7 @@ namespace MWMechanics const T& getModified() const { - return mModified; + return std::max(static_cast(0), mModified); } T getModifier() const From 8be9627c8d62fa81cabd814e8382f9a55338301c Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 Mar 2013 21:26:41 +0100 Subject: [PATCH 140/151] Fix method signatures --- apps/openmw/mwmechanics/stat.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index e1bb1994c..e9b7f4385 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -26,7 +26,7 @@ namespace MWMechanics return mBase; } - const T& getModified() const + T getModified() const { return std::max(static_cast(0), mModified); } @@ -108,7 +108,7 @@ namespace MWMechanics return mStatic.getBase(); } - const T& getModified() const + T getModified() const { return mStatic.getModified(); } From 7504ae675b44c4ebea2509d8ef3e8381200111d3 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Thu, 7 Mar 2013 03:00:59 +0100 Subject: [PATCH 141/151] Implemented a file dialog for the editor using launcher .ui --- apps/launcher/CMakeLists.txt | 16 +- apps/launcher/datafilespage.cpp | 60 +--- apps/launcher/resources.qrc | 21 -- apps/opencs/CMakeLists.txt | 6 +- apps/opencs/editor.cpp | 101 ++++-- apps/opencs/editor.hpp | 15 +- apps/opencs/view/doc/filedialog.cpp | 272 ++++++++++++++++ apps/opencs/view/doc/filedialog.hpp | 66 ++++ components/CMakeLists.txt | 2 +- components/fileorderlist/datafileslist.cpp | 293 ------------------ components/fileorderlist/datafileslist.hpp | 75 ----- .../fileorderlist/model/datafilesmodel.cpp | 1 + .../fileorderlist/model/datafilesmodel.hpp | 3 + .../model/pluginsproxymodel.cpp | 0 .../model/pluginsproxymodel.hpp | 0 .../launcher}/icons/tango/document-new.png | Bin .../launcher}/icons/tango/edit-copy.png | Bin .../launcher}/icons/tango/edit-delete.png | Bin .../launcher}/icons/tango/go-bottom.png | Bin .../launcher}/icons/tango/go-down.png | Bin .../launcher}/icons/tango/go-top.png | Bin .../launcher}/icons/tango/go-up.png | Bin .../launcher}/icons/tango/index.theme | 0 .../launcher}/icons/tango/video-display.png | Bin .../launcher}/images/clear.png | Bin .../launcher}/images/down.png | Bin .../launcher}/images/openmw-header.png | Bin .../launcher}/images/openmw-plugin.png | Bin .../launcher}/images/openmw.ico | Bin .../launcher}/images/openmw.png | Bin .../launcher}/images/playpage-background.png | Bin files/launcher/launcher.qrc | 21 ++ {apps/launcher => files}/ui/datafilespage.ui | 2 +- {apps/launcher => files}/ui/graphicspage.ui | 0 {apps/launcher => files}/ui/mainwindow.ui | 0 {apps/launcher => files}/ui/playpage.ui | 0 36 files changed, 464 insertions(+), 490 deletions(-) delete mode 100644 apps/launcher/resources.qrc create mode 100644 apps/opencs/view/doc/filedialog.cpp create mode 100644 apps/opencs/view/doc/filedialog.hpp delete mode 100644 components/fileorderlist/datafileslist.cpp delete mode 100644 components/fileorderlist/datafileslist.hpp rename {apps/launcher => components/fileorderlist}/model/pluginsproxymodel.cpp (100%) rename {apps/launcher => components/fileorderlist}/model/pluginsproxymodel.hpp (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/document-new.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/edit-copy.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/edit-delete.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/go-bottom.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/go-down.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/go-top.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/go-up.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/index.theme (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/video-display.png (100%) rename {apps/launcher/resources => files/launcher}/images/clear.png (100%) rename {apps/launcher/resources => files/launcher}/images/down.png (100%) rename {apps/launcher/resources => files/launcher}/images/openmw-header.png (100%) rename {apps/launcher/resources => files/launcher}/images/openmw-plugin.png (100%) rename {apps/launcher/resources => files/launcher}/images/openmw.ico (100%) rename {apps/launcher/resources => files/launcher}/images/openmw.png (100%) rename {apps/launcher/resources => files/launcher}/images/playpage-background.png (100%) create mode 100644 files/launcher/launcher.qrc rename {apps/launcher => files}/ui/datafilespage.ui (98%) rename {apps/launcher => files}/ui/graphicspage.ui (100%) rename {apps/launcher => files}/ui/mainwindow.ui (100%) rename {apps/launcher => files}/ui/playpage.ui (100%) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index a1c228945..a63898c0e 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -5,8 +5,6 @@ set(LAUNCHER maindialog.cpp playpage.cpp - model/pluginsproxymodel.cpp - settings/gamesettings.cpp settings/graphicssettings.cpp settings/launchersettings.cpp @@ -23,8 +21,6 @@ set(LAUNCHER_HEADER maindialog.hpp playpage.hpp - model/pluginsproxymodel.hpp - settings/gamesettings.hpp settings/graphicssettings.hpp settings/launchersettings.hpp @@ -42,17 +38,15 @@ set(LAUNCHER_HEADER_MOC maindialog.hpp playpage.hpp - model/pluginsproxymodel.hpp - utils/checkablemessagebox.hpp utils/textinputdialog.hpp ) set(LAUNCHER_UI - ui/datafilespage.ui - ui/graphicspage.ui - ui/mainwindow.ui - ui/playpage.ui + ../../files/ui/datafilespage.ui + ../../files/ui/graphicspage.ui + ../../files/ui/mainwindow.ui + ../../files/ui/playpage.ui ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) @@ -66,7 +60,7 @@ if(WIN32) set(QT_USE_QTMAIN TRUE) endif(WIN32) -QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) +QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 069cdd9ac..90cdd2942 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -2,25 +2,21 @@ #include -#include #include #include +#include #include #include #include #include -#include "model/pluginsproxymodel.hpp" - #include "settings/gamesettings.hpp" #include "settings/launchersettings.hpp" #include "utils/textinputdialog.hpp" -using namespace ESM; -using namespace std; //sort QModelIndexList ascending bool rowGreaterThan(const QModelIndex &index1, const QModelIndex &index2) @@ -100,60 +96,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam splitter->setSizes(sizeList); -// // Filter toolbar -// QLabel *filterLabel = new QLabel(tr("&Filter:"), this); -// LineEdit *filterLineEdit = new LineEdit(this); -// filterLabel->setBuddy(filterLineEdit); - -// QToolBar *filterToolBar = new QToolBar(this); -// filterToolBar->setMovable(false); - -// // Create a container widget and a layout to get the spacer to work -// QWidget *filterWidget = new QWidget(this); -// QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget); -// QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - -// filterLayout->addItem(hSpacer1); -// filterLayout->addWidget(filterLabel); -// filterLayout->addWidget(filterLineEdit); - -// filterToolBar->addWidget(filterWidget); - - - -// // Add both tables to a splitter -// mSplitter = new QSplitter(this); -// mSplitter->setOrientation(Qt::Horizontal); -// mSplitter->setChildrenCollapsible(false); // Don't allow the widgets to be hidden -// mSplitter->addWidget(mastersTable); -// mSplitter->addWidget(pluginsTable); - - - -// - -// // Bottom part with profile options -// QLabel *profileLabel = new QLabel(tr("Current Profile: "), this); - -// profilesComboBox = new ProfilesComboBox(this); -// profilesComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); -// profilesComboBox->setInsertPolicy(QComboBox::NoInsert); -// profilesComboBox->setDuplicatesEnabled(false); -// profilesComboBox->setEditEnabled(false); - -// mProfileToolBar = new QToolBar(this); -// mProfileToolBar->setMovable(false); -// mProfileToolBar->setIconSize(QSize(16, 16)); - -// mProfileToolBar->addWidget(profileLabel); -// mProfileToolBar->addWidget(profilesComboBox); - -// QVBoxLayout *pageLayout = new QVBoxLayout(this); - -// pageLayout->addWidget(filterToolBar); -// pageLayout->addWidget(mSplitter); -// pageLayout->addWidget(mProfileToolBar); - // Create a dialog for the new profile name input mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); diff --git a/apps/launcher/resources.qrc b/apps/launcher/resources.qrc deleted file mode 100644 index 2b56f80fd..000000000 --- a/apps/launcher/resources.qrc +++ /dev/null @@ -1,21 +0,0 @@ - - - resources/images/clear.png - resources/images/down.png - resources/images/openmw.png - resources/images/openmw-plugin.png - resources/images/openmw-header.png - resources/images/playpage-background.png - - - resources/icons/tango/index.theme - resources/icons/tango/video-display.png - resources/icons/tango/document-new.png - resources/icons/tango/edit-copy.png - resources/icons/tango/edit-delete.png - resources/icons/tango/go-bottom.png - resources/icons/tango/go-down.png - resources/icons/tango/go-top.png - resources/icons/tango/go-up.png - - diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d5d389a14..0071dd1fc 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -41,7 +41,7 @@ opencs_units_noqt (model/tools opencs_units (view/doc - viewmanager view operations operation subview startup opendialog + viewmanager view operations operation subview startup filedialog ) @@ -76,6 +76,10 @@ set (OPENCS_US ) set (OPENCS_RES ../../files/opencs/resources.qrc + ../../files/launcher/launcher.qrc + ) + +set (OPENCS_UI ../../files/ui/datafilespage.ui ) source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR}) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index e2df365a2..5966d089e 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -1,14 +1,12 @@ #include "editor.hpp" -#include - #include #include "model/doc/document.hpp" #include "model/world/data.hpp" -CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0) +CS::Editor::Editor() : mViewManager (mDocumentManager) { connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ())); connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ())); @@ -16,42 +14,99 @@ CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0) connect (&mStartup, SIGNAL (createDocument()), this, SLOT (createDocument ())); connect (&mStartup, SIGNAL (loadDocument()), this, SLOT (loadDocument ())); - connect (&mOpenDialog, SIGNAL(accepted()), this, SLOT(openFiles())); + connect (&mFileDialog, SIGNAL(openFiles()), this, SLOT(openFiles())); + connect (&mFileDialog, SIGNAL(createNewFile()), this, SLOT(createNewFile())); + + setupDataFiles(); +} + +void CS::Editor::setupDataFiles() +{ + boost::program_options::variables_map variables; + boost::program_options::options_description desc; + + desc.add_options() + ("data", boost::program_options::value()->default_value(Files::PathContainer(), "data")->multitoken()) + ("data-local", boost::program_options::value()->default_value("")) + ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) + ("encoding", boost::program_options::value()->default_value("win1252")); + + boost::program_options::notify(variables); + + mCfgMgr.readConfiguration(variables, desc); + + Files::PathContainer mDataDirs, mDataLocal; + if (!variables["data"].empty()) { + mDataDirs = Files::PathContainer(variables["data"].as()); + } + + std::string local = variables["data-local"].as(); + if (!local.empty()) { + mDataLocal.push_back(Files::PathContainer::value_type(local)); + } + + mCfgMgr.processPaths(mDataDirs); + mCfgMgr.processPaths(mDataLocal); + + // Set the charset for reading the esm/esp files + QString encoding = QString::fromStdString(variables["encoding"].as()); + mFileDialog.setEncoding(encoding); + + Files::PathContainer dataDirs; + dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end()); + dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end()); + + for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) + { + QString path = QString::fromStdString(iter->string()); + mFileDialog.addFiles(path); + } } void CS::Editor::createDocument() { mStartup.hide(); - /// \todo open the ESX picker instead - - std::ostringstream stream; - - stream << "NewDocument" << (++mNewDocumentIndex); - - std::vector files; - files.push_back (stream.str()); - - CSMDoc::Document *document = mDocumentManager.addDocument (files, true); - - mViewManager.addView (document); + mFileDialog.newFile(); } void CS::Editor::loadDocument() { mStartup.hide(); - mOpenDialog.show(); - mOpenDialog.raise(); - mOpenDialog.activateWindow(); + + mFileDialog.openFile(); } void CS::Editor::openFiles() { - std::vector paths; - mOpenDialog.getFileList(paths); - CSMDoc::Document *document = mDocumentManager.addDocument(paths, false); + std::vector files; + QStringList paths = mFileDialog.checkedItemsPaths(); + + foreach (const QString &path, paths) { + files.push_back(path.toStdString()); + } + + CSMDoc::Document *document = mDocumentManager.addDocument(files, false); mViewManager.addView (document); + mFileDialog.hide(); +} + +void CS::Editor::createNewFile() +{ + std::vector files; + QStringList paths = mFileDialog.checkedItemsPaths(); + + foreach (const QString &path, paths) { + files.push_back(path.toStdString()); + } + + files.push_back(mFileDialog.fileName().toStdString()); + + CSMDoc::Document *document = mDocumentManager.addDocument (files, true); + + mViewManager.addView (document); + mFileDialog.hide(); } int CS::Editor::run() @@ -59,4 +114,4 @@ int CS::Editor::run() mStartup.show(); return QApplication::exec(); -} \ No newline at end of file +} diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 024475bf0..c242a17ea 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -3,11 +3,13 @@ #include +#include + #include "model/doc/documentmanager.hpp" #include "view/doc/viewmanager.hpp" #include "view/doc/startup.hpp" -#include "view/doc/opendialog.hpp" +#include "view/doc/filedialog.hpp" namespace CS { @@ -15,12 +17,14 @@ namespace CS { Q_OBJECT - int mNewDocumentIndex; ///< \todo remove when the proper new document dialogue is implemented. - CSMDoc::DocumentManager mDocumentManager; CSVDoc::ViewManager mViewManager; CSVDoc::StartupDialogue mStartup; - OpenDialog mOpenDialog; + FileDialog mFileDialog; + + Files::ConfigurationManager mCfgMgr; + + void setupDataFiles(); // not implemented Editor (const Editor&); @@ -39,7 +43,8 @@ namespace CS void loadDocument(); void openFiles(); + void createNewFile(); }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/doc/filedialog.cpp b/apps/opencs/view/doc/filedialog.cpp new file mode 100644 index 000000000..f956317a7 --- /dev/null +++ b/apps/opencs/view/doc/filedialog.cpp @@ -0,0 +1,272 @@ +#include "filedialog.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +FileDialog::FileDialog(QWidget *parent) : + QDialog(parent) +{ + setupUi(this); + + // Models + mDataFilesModel = new DataFilesModel(this); + + mMastersProxyModel = new QSortFilterProxyModel(); + mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm")); + mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + mMastersProxyModel->setSourceModel(mDataFilesModel); + + mPluginsProxyModel = new PluginsProxyModel(); + mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp")); + mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + mPluginsProxyModel->setSourceModel(mDataFilesModel); + + mFilterProxyModel = new QSortFilterProxyModel(); + mFilterProxyModel->setDynamicSortFilter(true); + mFilterProxyModel->setSourceModel(mPluginsProxyModel); + + QCheckBox checkBox; + unsigned int height = checkBox.sizeHint().height() + 4; + + mastersTable->setModel(mMastersProxyModel); + mastersTable->setObjectName("MastersTable"); + mastersTable->setContextMenuPolicy(Qt::CustomContextMenu); + mastersTable->setSortingEnabled(false); + mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); + mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + mastersTable->setAlternatingRowColors(true); + mastersTable->horizontalHeader()->setStretchLastSection(true); + + // Set the row height to the size of the checkboxes + mastersTable->verticalHeader()->setDefaultSectionSize(height); + mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + mastersTable->verticalHeader()->hide(); + + pluginsTable->setModel(mFilterProxyModel); + pluginsTable->setObjectName("PluginsTable"); + pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); + pluginsTable->setSortingEnabled(false); + pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + pluginsTable->setAlternatingRowColors(true); + pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + pluginsTable->horizontalHeader()->setStretchLastSection(true); + + pluginsTable->verticalHeader()->setDefaultSectionSize(height); + pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + + // Hide the profile elements + profileLabel->hide(); + profilesComboBox->hide(); + newProfileButton->hide(); + deleteProfileButton->hide(); + + // Add some extra widgets + QHBoxLayout *nameLayout = new QHBoxLayout(); + QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + mNameLabel = new QLabel(tr("File Name:"), this); + + QRegExpValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9\\s]*$")); + mNameLineEdit = new LineEdit(this); + mNameLineEdit->setValidator(validator); + + nameLayout->addSpacerItem(spacer); + nameLayout->addWidget(mNameLabel); + nameLayout->addWidget(mNameLineEdit); + + mButtonBox = new QDialogButtonBox(this); + + mCreateButton = new QPushButton(tr("Create"), this); + mCreateButton->setEnabled(false); + + verticalLayout->addLayout(nameLayout); + verticalLayout->addWidget(mButtonBox); + + // Set sizes + QList sizeList; + sizeList << 175; + sizeList << 200; + + splitter->setSizes(sizeList); + + resize(600, 400); + + connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); + connect(mDataFilesModel, SIGNAL(checkedItemsChanged(QStringList)), this, SLOT(updateOpenButton(QStringList))); + connect(mNameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateCreateButton(QString))); + + connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); + + connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + + connect(mCreateButton, SIGNAL(clicked()), this, SLOT(createButtonClicked())); + + connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject())); +} + +void FileDialog::updateViews() +{ + // Ensure the columns are hidden because sort() re-enables them + mastersTable->setColumnHidden(1, true); + mastersTable->setColumnHidden(3, true); + mastersTable->setColumnHidden(4, true); + mastersTable->setColumnHidden(5, true); + mastersTable->setColumnHidden(6, true); + mastersTable->setColumnHidden(7, true); + mastersTable->setColumnHidden(8, true); + mastersTable->resizeColumnsToContents(); + + pluginsTable->setColumnHidden(1, true); + pluginsTable->setColumnHidden(3, true); + pluginsTable->setColumnHidden(4, true); + pluginsTable->setColumnHidden(5, true); + pluginsTable->setColumnHidden(6, true); + pluginsTable->setColumnHidden(7, true); + pluginsTable->setColumnHidden(8, true); + pluginsTable->resizeColumnsToContents(); + +} + +void FileDialog::updateOpenButton(const QStringList &items) +{ + QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open); + + if (!openButton) + return; + + openButton->setEnabled(!items.isEmpty()); +} + +void FileDialog::updateCreateButton(const QString &name) +{ + if (!mCreateButton->isVisible()) + return; + + mCreateButton->setEnabled(!name.isEmpty()); +} + +void FileDialog::filterChanged(const QString &filter) +{ + QRegExp filterRe(filter, Qt::CaseInsensitive, QRegExp::FixedString); + mFilterProxyModel->setFilterRegExp(filterRe); +} + +void FileDialog::addFiles(const QString &path) +{ + mDataFilesModel->addFiles(path); + mDataFilesModel->sort(3); // Sort by date accessed +} + +void FileDialog::setEncoding(const QString &encoding) +{ + mDataFilesModel->setEncoding(encoding); +} + +void FileDialog::setCheckState(QModelIndex index) +{ + if (!index.isValid()) + return; + + QObject *object = QObject::sender(); + + // Not a signal-slot call + if (!object) + return; + + + if (object->objectName() == QLatin1String("PluginsTable")) { + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (sourceIndex.isValid()) { + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); + } + } + + if (object->objectName() == QLatin1String("MastersTable")) { + QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index); + + if (sourceIndex.isValid()) { + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); + } + } + + return; +} + +QStringList FileDialog::checkedItemsPaths() +{ + return mDataFilesModel->checkedItemsPaths(); +} + +QString FileDialog::fileName() +{ + return mNameLineEdit->text(); +} + +void FileDialog::openFile() +{ + setWindowTitle(tr("Open")); + + mNameLabel->hide(); + mNameLineEdit->hide(); + mCreateButton->hide(); + + mButtonBox->removeButton(mCreateButton); + mButtonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Open); + QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open); + openButton->setEnabled(false); + + show(); + raise(); + activateWindow(); +} + +void FileDialog::newFile() +{ + setWindowTitle(tr("New")); + + mNameLabel->show(); + mNameLineEdit->clear(); + mNameLineEdit->show(); + mCreateButton->show(); + + mButtonBox->setStandardButtons(QDialogButtonBox::Cancel); + mButtonBox->addButton(mCreateButton, QDialogButtonBox::ActionRole); + + show(); + raise(); + activateWindow(); +} + +void FileDialog::accept() +{ + emit openFiles(); +} + +void FileDialog::createButtonClicked() +{ + emit createNewFile(); +} diff --git a/apps/opencs/view/doc/filedialog.hpp b/apps/opencs/view/doc/filedialog.hpp new file mode 100644 index 000000000..b21618d5d --- /dev/null +++ b/apps/opencs/view/doc/filedialog.hpp @@ -0,0 +1,66 @@ +#ifndef FILEDIALOG_HPP +#define FILEDIALOG_HPP + +#include +#include + +#include "ui_datafilespage.h" + +class QDialogButtonBox; +class QSortFilterProxyModel; +class QAbstractItemModel; +class QPushButton; +class QStringList; +class QString; +class QMenu; + +class DataFilesModel; +class PluginsProxyModel; + +class FileDialog : public QDialog, private Ui::DataFilesPage +{ + Q_OBJECT +public: + explicit FileDialog(QWidget *parent = 0); + void addFiles(const QString &path); + void setEncoding(const QString &encoding); + + void openFile(); + void newFile(); + void accepted(); + + QStringList checkedItemsPaths(); + QString fileName(); + +signals: + void openFiles(); + void createNewFile(); + +public slots: + void accept(); + +private slots: + void updateViews(); + void updateOpenButton(const QStringList &items); + void updateCreateButton(const QString &name); + void setCheckState(QModelIndex index); + + void filterChanged(const QString &filter); + + void createButtonClicked(); + +private: + QLabel *mNameLabel; + LineEdit *mNameLineEdit; + + QPushButton *mCreateButton; + QDialogButtonBox *mButtonBox; + + DataFilesModel *mDataFilesModel; + + PluginsProxyModel *mPluginsProxyModel; + QSortFilterProxyModel *mMastersProxyModel; + QSortFilterProxyModel *mFilterProxyModel; +}; + +#endif // FILEDIALOG_HPP diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 7c52ab12c..a4b194fab 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -70,7 +70,7 @@ find_package(Qt4 COMPONENTS QtCore QtGui) if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) add_component_qt_dir (fileorderlist - datafileslist model/modelitem model/datafilesmodel model/esm/esmfile + model/modelitem model/datafilesmodel model/pluginsproxymodel model/esm/esmfile utils/profilescombobox utils/comboboxlineedit utils/lineedit utils/naturalsort ) diff --git a/components/fileorderlist/datafileslist.cpp b/components/fileorderlist/datafileslist.cpp deleted file mode 100644 index 9fe8d0fea..000000000 --- a/components/fileorderlist/datafileslist.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#include - -#include -#include - -#include "model/datafilesmodel.hpp" -#include "model/esm/esmfile.hpp" - -#include "utils/lineedit.hpp" - -#include "datafileslist.hpp" - -#include -/** - * Workaround for problems with whitespaces in paths in older versions of Boost library - */ -#if (BOOST_VERSION <= 104600) -namespace boost -{ - - template<> - inline boost::filesystem::path lexical_cast(const std::string& arg) - { - return boost::filesystem::path(arg); - } - -} /* namespace boost */ -#endif /* (BOOST_VERSION <= 104600) */ - -using namespace ESM; -using namespace std; - -//sort QModelIndexList ascending -bool rowGreaterThan(const QModelIndex &index1, const QModelIndex &index2) -{ - return index1.row() >= index2.row(); -} - -//sort QModelIndexList descending -bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2) -{ - return index1.row() <= index2.row(); -} - -DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) - : QWidget(parent) - , mCfgMgr(cfg) -{ - // Model - mFilesModel = new DataFilesModel(this); - - mFilesProxyModel = new QSortFilterProxyModel(); - mFilesProxyModel->setDynamicSortFilter(true); - mFilesProxyModel->setSourceModel(mFilesModel); - - // Filter toolbar - QLabel *filterLabel = new QLabel(tr("&Filter:"), this); - LineEdit *filterLineEdit = new LineEdit(this); - filterLabel->setBuddy(filterLineEdit); - - QToolBar *filterToolBar = new QToolBar(this); - filterToolBar->setMovable(false); - - // Create a container widget and a layout to get the spacer to work - QWidget *filterWidget = new QWidget(this); - QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget); - QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - filterLayout->addItem(hSpacer1); - filterLayout->addWidget(filterLabel); - filterLayout->addWidget(filterLineEdit); - - filterToolBar->addWidget(filterWidget); - - QCheckBox checkBox; - unsigned int height = checkBox.sizeHint().height() + 4; - - mFilesTable = new QTableView(this); - mFilesTable->setModel(mFilesProxyModel); - mFilesTable->setObjectName("PluginsTable"); - mFilesTable->setContextMenuPolicy(Qt::CustomContextMenu); - mFilesTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mFilesTable->setSelectionMode(QAbstractItemView::SingleSelection); - mFilesTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mFilesTable->setAlternatingRowColors(true); - mFilesTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); - mFilesTable->horizontalHeader()->setStretchLastSection(true); - mFilesTable->horizontalHeader()->hide(); - - mFilesTable->verticalHeader()->setDefaultSectionSize(height); - mFilesTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - mFilesTable->setColumnHidden(1, true); - mFilesTable->setColumnHidden(2, true); - mFilesTable->setColumnHidden(3, true); - mFilesTable->setColumnHidden(4, true); - mFilesTable->setColumnHidden(5, true); - mFilesTable->setColumnHidden(6, true); - mFilesTable->setColumnHidden(7, true); - mFilesTable->setColumnHidden(8, true); - - QVBoxLayout *pageLayout = new QVBoxLayout(this); - - pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(mFilesTable); - - connect(mFilesTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - - connect(mFilesModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mFilesModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); - - connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - - connect(mFilesTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); - - createActions(); -} - -void DataFilesList::createActions() -{ - // Refresh the plugins - QAction *refreshAction = new QAction(tr("Refresh"), this); - refreshAction->setShortcut(QKeySequence(tr("F5"))); - connect(refreshAction, SIGNAL(triggered()), this, SLOT(refresh())); - - // Context menu actions - mCheckAction = new QAction(tr("Check selected"), this); - connect(mCheckAction, SIGNAL(triggered()), this, SLOT(check())); - - mUncheckAction = new QAction(tr("Uncheck selected"), this); - connect(mUncheckAction, SIGNAL(triggered()), this, SLOT(uncheck())); - - // Context menu for the plugins table - mContextMenu = new QMenu(this); - - mContextMenu->addAction(mCheckAction); - mContextMenu->addAction(mUncheckAction); - -} - -bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString encoding) -{ - // Set the charset for reading the esm/esp files - if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) { - mFilesModel->setEncoding(encoding); - } - - // Add the paths to the respective models - for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { - QString path = QString::fromStdString(it->string()); - path.remove(QChar('\"')); - mFilesModel->addFiles(path); - } - - mFilesModel->sort(0); -// mMastersTable->sortByColumn(3, Qt::AscendingOrder); -// mPluginsTable->sortByColumn(3, Qt::AscendingOrder); - - return true; -} - -void DataFilesList::selectedFiles(std::vector& paths) -{ - QStringList pluginPaths = mFilesModel->checkedItemsPaths(); - foreach (const QString &path, pluginPaths) - { - paths.push_back(path.toStdString()); - } -} - -void DataFilesList::check() -{ - // Check the current selection - if (!mFilesTable->selectionModel()->hasSelection()) { - return; - } - - QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); - - //sort selection ascending because selectedIndexes returns an unsorted list - //qSort(indexes.begin(), indexes.end(), rowSmallerThan); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - mFilesModel->setCheckState(index, Qt::Checked); - } -} - -void DataFilesList::uncheck() -{ - // uncheck the current selection - if (!mFilesTable->selectionModel()->hasSelection()) { - return; - } - - QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); - - //sort selection ascending because selectedIndexes returns an unsorted list - //qSort(indexes.begin(), indexes.end(), rowSmallerThan); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - mFilesModel->setCheckState(index, Qt::Unchecked); - } -} - -void DataFilesList::refresh() -{ - mFilesModel->sort(0); - - - // Refresh the plugins table - mFilesTable->scrollToTop(); -} - - -void DataFilesList::setCheckState(QModelIndex index) -{ - if (!index.isValid()) - return; - - QObject *object = QObject::sender(); - - // Not a signal-slot call - if (!object) - return; - - if (object->objectName() == QLatin1String("PluginsTable")) { - QModelIndex sourceIndex = mFilesProxyModel->mapToSource(index); - - (mFilesModel->checkState(sourceIndex) == Qt::Checked) - ? mFilesModel->setCheckState(sourceIndex, Qt::Unchecked) - : mFilesModel->setCheckState(sourceIndex, Qt::Checked); - } - - return; - -} - -void DataFilesList::uncheckAll() -{ - mFilesModel->uncheckAll(); -} - -void DataFilesList::filterChanged(const QString filter) -{ - QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString); - mFilesProxyModel->setFilterRegExp(regExp); -} - -void DataFilesList::showContextMenu(const QPoint &point) -{ - // Make sure there are plugins in the view - if (!mFilesTable->selectionModel()->hasSelection()) { - return; - } - - QPoint globalPos = mFilesTable->mapToGlobal(point); - - QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); - - // Show the check/uncheck actions depending on the state of the selected items - mUncheckAction->setEnabled(false); - mCheckAction->setEnabled(false); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - (mFilesModel->checkState(index) == Qt::Checked) - ? mUncheckAction->setEnabled(true) - : mCheckAction->setEnabled(true); - } - - // Show menu - mContextMenu->exec(globalPos); -} - -void DataFilesList::setCheckState(const QString& element, Qt::CheckState state) -{ - EsmFile *file = mFilesModel->findItem(element); - if (file) - { - mFilesModel->setCheckState(mFilesModel->indexFromItem(file), Qt::Checked); - } -} - -QStringList DataFilesList::checkedFiles() -{ - return mFilesModel->checkedItems(); -} diff --git a/components/fileorderlist/datafileslist.hpp b/components/fileorderlist/datafileslist.hpp deleted file mode 100644 index 69a20393c..000000000 --- a/components/fileorderlist/datafileslist.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef DATAFILESLIST_H -#define DATAFILESLIST_H - -#include -#include -#include - - -class QTableView; -class QSortFilterProxyModel; -class QSettings; -class QAction; -class QToolBar; -class QMenu; -class ProfilesComboBox; -class DataFilesModel; - -class TextInputDialog; - -namespace Files { struct ConfigurationManager; } - -class DataFilesList : public QWidget -{ - Q_OBJECT - -public: - DataFilesList(Files::ConfigurationManager& cfg, QWidget *parent = 0); - - bool setupDataFiles(Files::PathContainer dataDirs, const QString encoding); - void selectedFiles(std::vector& paths); - void uncheckAll(); - QStringList checkedFiles(); - void setCheckState(const QString& element, Qt::CheckState); - - -public slots: - void setCheckState(QModelIndex index); - - void filterChanged(const QString filter); - void showContextMenu(const QPoint &point); - - // Action slots -// void moveUp(); -// void moveDown(); -// void moveTop(); -// void moveBottom(); - void check(); - void uncheck(); - void refresh(); - -private: - DataFilesModel *mFilesModel; - - QSortFilterProxyModel *mFilesProxyModel; - - QTableView *mFilesTable; - - QMenu *mContextMenu; - -// QAction *mMoveUpAction; -// QAction *mMoveDownAction; -// QAction *mMoveTopAction; -// QAction *mMoveBottomAction; - QAction *mCheckAction; - QAction *mUncheckAction; - - Files::ConfigurationManager &mCfgMgr; - -// const QStringList checkedPlugins(); -// const QStringList selectedMasters(); - - void createActions(); -}; - -#endif diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 4e9b69dc2..b33e2e12a 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -212,6 +212,7 @@ bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, in QModelIndex lastIndex = indexFromItem(mFiles.last()); emit dataChanged(firstIndex, lastIndex); + emit checkedItemsChanged(checkedItems()); return true; } diff --git a/components/fileorderlist/model/datafilesmodel.hpp b/components/fileorderlist/model/datafilesmodel.hpp index 0e5008abe..0a07a536f 100644 --- a/components/fileorderlist/model/datafilesmodel.hpp +++ b/components/fileorderlist/model/datafilesmodel.hpp @@ -48,6 +48,9 @@ public: QModelIndex indexFromItem(EsmFile *item) const; EsmFile* findItem(const QString &name); EsmFile* item(int row) const; + +signals: + void checkedItemsChanged(const QStringList &items); private: bool canBeChecked(EsmFile *file) const; diff --git a/apps/launcher/model/pluginsproxymodel.cpp b/components/fileorderlist/model/pluginsproxymodel.cpp similarity index 100% rename from apps/launcher/model/pluginsproxymodel.cpp rename to components/fileorderlist/model/pluginsproxymodel.cpp diff --git a/apps/launcher/model/pluginsproxymodel.hpp b/components/fileorderlist/model/pluginsproxymodel.hpp similarity index 100% rename from apps/launcher/model/pluginsproxymodel.hpp rename to components/fileorderlist/model/pluginsproxymodel.hpp diff --git a/apps/launcher/resources/icons/tango/document-new.png b/files/launcher/icons/tango/document-new.png similarity index 100% rename from apps/launcher/resources/icons/tango/document-new.png rename to files/launcher/icons/tango/document-new.png diff --git a/apps/launcher/resources/icons/tango/edit-copy.png b/files/launcher/icons/tango/edit-copy.png similarity index 100% rename from apps/launcher/resources/icons/tango/edit-copy.png rename to files/launcher/icons/tango/edit-copy.png diff --git a/apps/launcher/resources/icons/tango/edit-delete.png b/files/launcher/icons/tango/edit-delete.png similarity index 100% rename from apps/launcher/resources/icons/tango/edit-delete.png rename to files/launcher/icons/tango/edit-delete.png diff --git a/apps/launcher/resources/icons/tango/go-bottom.png b/files/launcher/icons/tango/go-bottom.png similarity index 100% rename from apps/launcher/resources/icons/tango/go-bottom.png rename to files/launcher/icons/tango/go-bottom.png diff --git a/apps/launcher/resources/icons/tango/go-down.png b/files/launcher/icons/tango/go-down.png similarity index 100% rename from apps/launcher/resources/icons/tango/go-down.png rename to files/launcher/icons/tango/go-down.png diff --git a/apps/launcher/resources/icons/tango/go-top.png b/files/launcher/icons/tango/go-top.png similarity index 100% rename from apps/launcher/resources/icons/tango/go-top.png rename to files/launcher/icons/tango/go-top.png diff --git a/apps/launcher/resources/icons/tango/go-up.png b/files/launcher/icons/tango/go-up.png similarity index 100% rename from apps/launcher/resources/icons/tango/go-up.png rename to files/launcher/icons/tango/go-up.png diff --git a/apps/launcher/resources/icons/tango/index.theme b/files/launcher/icons/tango/index.theme similarity index 100% rename from apps/launcher/resources/icons/tango/index.theme rename to files/launcher/icons/tango/index.theme diff --git a/apps/launcher/resources/icons/tango/video-display.png b/files/launcher/icons/tango/video-display.png similarity index 100% rename from apps/launcher/resources/icons/tango/video-display.png rename to files/launcher/icons/tango/video-display.png diff --git a/apps/launcher/resources/images/clear.png b/files/launcher/images/clear.png similarity index 100% rename from apps/launcher/resources/images/clear.png rename to files/launcher/images/clear.png diff --git a/apps/launcher/resources/images/down.png b/files/launcher/images/down.png similarity index 100% rename from apps/launcher/resources/images/down.png rename to files/launcher/images/down.png diff --git a/apps/launcher/resources/images/openmw-header.png b/files/launcher/images/openmw-header.png similarity index 100% rename from apps/launcher/resources/images/openmw-header.png rename to files/launcher/images/openmw-header.png diff --git a/apps/launcher/resources/images/openmw-plugin.png b/files/launcher/images/openmw-plugin.png similarity index 100% rename from apps/launcher/resources/images/openmw-plugin.png rename to files/launcher/images/openmw-plugin.png diff --git a/apps/launcher/resources/images/openmw.ico b/files/launcher/images/openmw.ico similarity index 100% rename from apps/launcher/resources/images/openmw.ico rename to files/launcher/images/openmw.ico diff --git a/apps/launcher/resources/images/openmw.png b/files/launcher/images/openmw.png similarity index 100% rename from apps/launcher/resources/images/openmw.png rename to files/launcher/images/openmw.png diff --git a/apps/launcher/resources/images/playpage-background.png b/files/launcher/images/playpage-background.png similarity index 100% rename from apps/launcher/resources/images/playpage-background.png rename to files/launcher/images/playpage-background.png diff --git a/files/launcher/launcher.qrc b/files/launcher/launcher.qrc new file mode 100644 index 000000000..19b1c5a6f --- /dev/null +++ b/files/launcher/launcher.qrc @@ -0,0 +1,21 @@ + + + images/clear.png + images/down.png + images/openmw.png + images/openmw-plugin.png + images/openmw-header.png + images/playpage-background.png + + + icons/tango/index.theme + icons/tango/video-display.png + icons/tango/document-new.png + icons/tango/edit-copy.png + icons/tango/edit-delete.png + icons/tango/go-bottom.png + icons/tango/go-down.png + icons/tango/go-top.png + icons/tango/go-up.png + + diff --git a/apps/launcher/ui/datafilespage.ui b/files/ui/datafilespage.ui similarity index 98% rename from apps/launcher/ui/datafilespage.ui rename to files/ui/datafilespage.ui index 91b5475e6..044817fb4 100644 --- a/apps/launcher/ui/datafilespage.ui +++ b/files/ui/datafilespage.ui @@ -59,7 +59,7 @@ - + Current Profile: diff --git a/apps/launcher/ui/graphicspage.ui b/files/ui/graphicspage.ui similarity index 100% rename from apps/launcher/ui/graphicspage.ui rename to files/ui/graphicspage.ui diff --git a/apps/launcher/ui/mainwindow.ui b/files/ui/mainwindow.ui similarity index 100% rename from apps/launcher/ui/mainwindow.ui rename to files/ui/mainwindow.ui diff --git a/apps/launcher/ui/playpage.ui b/files/ui/playpage.ui similarity index 100% rename from apps/launcher/ui/playpage.ui rename to files/ui/playpage.ui From a994a23f4ec1a1fe956216651caea2ff7bd0a127 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 7 Mar 2013 07:56:29 +0100 Subject: [PATCH 142/151] file loading fixes --- apps/opencs/model/doc/document.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index e709cc5bf..11d877d0b 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -18,9 +18,6 @@ void CSMDoc::Document::load (const std::vector::const_i if (lastAsModified) getData().loadFile (*end2, false); - - addOptionalGmsts(); - addOptionalGlobals(); } void CSMDoc::Document::addOptionalGmsts() @@ -199,6 +196,8 @@ void CSMDoc::Document::createBase() getData().getGlobals().add (record); } + + /// \todo add GMSTs } CSMDoc::Document::Document (const std::vector& files, bool new_) @@ -213,7 +212,9 @@ CSMDoc::Document::Document (const std::vector& files, b mName = files.back().filename().string(); - if (files.size()>1 || !new_) + if (new_ && files.size()==1) + createBase(); + else if (files.size()>1) { std::vector::const_iterator end = files.end(); @@ -223,8 +224,8 @@ CSMDoc::Document::Document (const std::vector& files, b load (files.begin(), end, !new_); } - if (new_ && files.size()==1) - createBase(); + addOptionalGmsts(); + addOptionalGlobals(); connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); From e34685b8a314d49d6353876c3634022a5ad444af Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 7 Mar 2013 12:46:26 +0100 Subject: [PATCH 143/151] Fix manually changed mouse cursor --- apps/openmw/mwbase/windowmanager.hpp | 2 ++ apps/openmw/mwgui/cursor.cpp | 5 +++-- apps/openmw/mwgui/hud.cpp | 11 +++++------ apps/openmw/mwgui/windowmanagerimp.cpp | 5 +++++ apps/openmw/mwgui/windowmanagerimp.hpp | 2 ++ 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 81d7cb9fe..93cc8e44a 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -237,6 +237,8 @@ namespace MWBase virtual void startEnchanting(MWWorld::Ptr actor) = 0; virtual void startTraining(MWWorld::Ptr actor) = 0; + virtual void changePointer (const std::string& name) = 0; + virtual const Translation::Storage& getTranslationDataStorage() const = 0; }; } diff --git a/apps/openmw/mwgui/cursor.cpp b/apps/openmw/mwgui/cursor.cpp index 399695ae3..b0d164bed 100644 --- a/apps/openmw/mwgui/cursor.cpp +++ b/apps/openmw/mwgui/cursor.cpp @@ -13,8 +13,9 @@ namespace MWGui { - ResourceImageSetPointerFix::ResourceImageSetPointerFix() : - mImageSet(NULL) + ResourceImageSetPointerFix::ResourceImageSetPointerFix() + : mImageSet(NULL) + , mRotation(0) { } diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index cebc457db..0a31a428b 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -4,7 +4,6 @@ #include #include -#include #include @@ -222,7 +221,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) else world->dropObjectOnGround(world->getPlayer().getPlayer(), object); - MyGUI::PointerManager::getInstance().setPointer("arrow"); + MWBase::Environment::get().getWindowManager()->changePointer("arrow"); std::string sound = MWWorld::Class::get(object).getDownSoundId(object); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); @@ -273,21 +272,21 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) bool canDrop = world->canPlaceObject(mouseX, mouseY); if (!canDrop) - MyGUI::PointerManager::getInstance().setPointer("drop_ground"); + MWBase::Environment::get().getWindowManager()->changePointer("drop_ground"); else - MyGUI::PointerManager::getInstance().setPointer("arrow"); + MWBase::Environment::get().getWindowManager()->changePointer("arrow"); } else { - MyGUI::PointerManager::getInstance().setPointer("arrow"); + MWBase::Environment::get().getWindowManager()->changePointer("arrow"); mWorldMouseOver = true; } } void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) { - MyGUI::PointerManager::getInstance().setPointer("arrow"); + MWBase::Environment::get().getWindowManager()->changePointer("arrow"); mWorldMouseOver = false; } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index eb8d4c191..d866ec755 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1127,3 +1127,8 @@ const Translation::Storage& WindowManager::getTranslationDataStorage() const { return mTranslationDataStorage; } + +void WindowManager::changePointer(const std::string &name) +{ + mCursor->onCursorChange(name); +} diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 7786af31a..122b10cc3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -228,6 +228,8 @@ namespace MWGui virtual void startEnchanting(MWWorld::Ptr actor); virtual void startTraining(MWWorld::Ptr actor); + virtual void changePointer (const std::string& name); + virtual const Translation::Storage& getTranslationDataStorage() const; private: From 0ee0dbdb971bb5ae09ef256173f69d46ba1cd303 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 7 Mar 2013 14:00:13 +0100 Subject: [PATCH 144/151] Added "dispose corpse" button, added stealing (all items visible and no penalty yet) --- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/npc.cpp | 4 +- apps/openmw/mwgui/container.cpp | 66 +++++++++++++++++++--- apps/openmw/mwgui/container.hpp | 10 +++- apps/openmw/mwgui/inventorywindow.cpp | 18 ------ apps/openmw/mwgui/inventorywindow.hpp | 1 - apps/openmw/mwgui/tradewindow.cpp | 27 +-------- apps/openmw/mwgui/tradewindow.hpp | 4 -- apps/openmw/mwworld/actionopen.cpp | 6 +- apps/openmw/mwworld/actionopen.hpp | 8 ++- files/mygui/openmw_container_window.layout | 4 ++ 11 files changed, 87 insertions(+), 63 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 90dc70715..19f327dcb 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -132,7 +132,7 @@ namespace MWClass const MWWorld::Ptr& actor) const { if (MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead()) - return boost::shared_ptr (new MWWorld::ActionOpen(ptr)); + return boost::shared_ptr (new MWWorld::ActionOpen(ptr, true)); else return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index b1263c2e5..f074d0368 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -220,7 +220,9 @@ namespace MWClass const MWWorld::Ptr& actor) const { if (MWWorld::Class::get (ptr).getCreatureStats (ptr).isDead()) - return boost::shared_ptr (new MWWorld::ActionOpen(ptr)); + return boost::shared_ptr (new MWWorld::ActionOpen(ptr, true)); + else if (MWWorld::Class::get(actor).getStance(actor, MWWorld::Class::Sneak)) + return boost::shared_ptr (new MWWorld::ActionOpen(ptr)); // stealing else return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 479a82efa..2b8000312 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -15,6 +15,7 @@ #include "../mwworld/manualref.hpp" #include "../mwworld/containerstore.hpp" +#include "../mwworld/inventorystore.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" @@ -70,9 +71,11 @@ namespace } -ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) : - mDragAndDrop(dragAndDrop), - mFilter(ContainerBase::Filter_All) +ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) + : mDragAndDrop(dragAndDrop) + , mFilter(ContainerBase::Filter_All) + , mDisplayEquippedItems(true) + , mHighlightEquippedItems(true) { } @@ -313,7 +316,6 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); } - std::cout << "container weight " << curWeight << "/" << capacity << std::endl; } else { @@ -430,7 +432,7 @@ void ContainerBase::drawItems() equippedItems.erase(found); } // and add the items that are left (= have the correct category) - if (!ignoreEquippedItems()) + if (mDisplayEquippedItems && mHighlightEquippedItems) { for (std::vector::const_iterator it=equippedItems.begin(); it != equippedItems.end(); ++it) @@ -445,7 +447,8 @@ void ContainerBase::drawItems() std::vector regularItems; for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) { - if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end() + if ( (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end() + || (!mHighlightEquippedItems && mDisplayEquippedItems)) && std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end() && std::find(mBoughtItems.begin(), mBoughtItems.end(), *iter) == mBoughtItems.end()) regularItems.push_back(*iter); @@ -587,6 +590,27 @@ void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store) } } +std::vector ContainerBase::getEquippedItems() +{ + if (mPtr.getTypeName() != typeid(ESM::NPC).name()) + return std::vector(); + + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + + std::vector items; + + for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) + { + MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); + if (it != invStore.end()) + { + items.push_back(*it); + } + } + + return items; +} + MWWorld::ContainerStore& ContainerBase::getContainerStore() { MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); @@ -599,6 +623,7 @@ ContainerWindow::ContainerWindow(MWBase::WindowManager& parWindowManager,DragAnd : ContainerBase(dragAndDrop) , WindowBase("openmw_container_window.layout", parWindowManager) { + getWidget(mDisposeCorpseButton, "DisposeCorpseButton"); getWidget(mTakeButton, "TakeButton"); getWidget(mCloseButton, "CloseButton"); @@ -608,6 +633,7 @@ ContainerWindow::ContainerWindow(MWBase::WindowManager& parWindowManager,DragAnd getWidget(itemView, "ItemView"); setWidgets(containerWidget, itemView); + mDisposeCorpseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onDisposeCorpseButtonClicked); mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked); mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked); @@ -625,8 +651,18 @@ void ContainerWindow::onWindowResize(MyGUI::Window* window) drawItems(); } -void ContainerWindow::open(MWWorld::Ptr container) +void ContainerWindow::open(MWWorld::Ptr container, bool loot) { + mDisplayEquippedItems = true; + mHighlightEquippedItems = false; + if (container.getTypeName() == typeid(ESM::NPC).name() && !loot) + { + // we are stealing stuff + mDisplayEquippedItems = false; + } + + mDisposeCorpseButton->setVisible(loot); + openContainer(container); setTitle(MWWorld::Class::get(container).getName(container)); drawItems(); @@ -671,6 +707,22 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) } } +void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender) +{ + if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) + { + onTakeAllButtonClicked(mTakeButton); + + /// \todo I don't think this is the correct flag to check + if (MWWorld::Class::get(mPtr).isEssential(mPtr)) + mWindowManager.messageBox("#{sDisposeCorpseFail}"); + else + MWBase::Environment::get().getWorld()->deleteObject(mPtr); + + mPtr = MWWorld::Ptr(); + } +} + void ContainerWindow::onReferenceUnavailable() { MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 08d425032..3c8127b26 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -82,6 +82,9 @@ namespace MWGui void drawItems(); protected: + bool mDisplayEquippedItems; + bool mHighlightEquippedItems; + MyGUI::ScrollView* mItemView; MyGUI::Widget* mContainerWidget; @@ -111,14 +114,13 @@ namespace MWGui virtual bool isTradeWindow() { return false; } virtual bool isInventory() { return false; } - virtual std::vector getEquippedItems() { return std::vector(); } + virtual std::vector getEquippedItems(); virtual void _unequipItem(MWWorld::Ptr item) { ; } virtual bool isTrading() { return false; } virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; } - virtual bool ignoreEquippedItems() { return false; } virtual std::vector itemsToIgnore() { return std::vector(); } virtual void notifyContentChanged() { ; } @@ -131,15 +133,17 @@ namespace MWGui virtual ~ContainerWindow(); - void open(MWWorld::Ptr container); + void open(MWWorld::Ptr container, bool loot=false); protected: + MyGUI::Button* mDisposeCorpseButton; MyGUI::Button* mTakeButton; MyGUI::Button* mCloseButton; void onWindowResize(MyGUI::Window* window); void onCloseButtonClicked(MyGUI::Widget* _sender); void onTakeAllButtonClicked(MyGUI::Widget* _sender); + void onDisposeCorpseButtonClicked(MyGUI::Widget* sender); virtual void onReferenceUnavailable(); }; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 4a0234644..ab7615c0e 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -211,24 +211,6 @@ namespace MWGui return MWWorld::Ptr(); } - std::vector InventoryWindow::getEquippedItems() - { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); - - std::vector items; - - for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) - { - MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); - if (it != invStore.end()) - { - items.push_back(*it); - } - } - - return items; - } - void InventoryWindow::_unequipItem(MWWorld::Ptr item) { MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 6b45a9980..7c59bab50 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -64,7 +64,6 @@ namespace MWGui virtual bool isTrading() { return mTrading; } virtual bool isInventory() { return true; } - virtual std::vector getEquippedItems(); virtual void _unequipItem(MWWorld::Ptr item); virtual void onReferenceUnavailable() { ; } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index e3cf8ea3a..1b82d741c 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -31,6 +31,9 @@ namespace MWGui , mBalanceButtonsState(BBS_None) , mBalanceChangePause(0.0) { + // items the NPC is wearing should not be for trade + mDisplayEquippedItems = true; + MyGUI::ScrollView* itemView; MyGUI::Widget* containerWidget; getWidget(containerWidget, "Items"); @@ -337,30 +340,6 @@ namespace MWGui mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + boost::lexical_cast(getMerchantGold())); } - std::vector TradeWindow::getEquippedItems() - { - std::vector items; - - if (mPtr.getTypeName() == typeid(ESM::Creature).name()) - { - // creatures don't have equipment slots. - return items; - } - - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); - - for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) - { - MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); - if (it != invStore.end()) - { - items.push_back(*it); - } - } - - return items; - } - bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item) { int services = 0; diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index ea749f5a2..2e05d03d5 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -82,10 +82,6 @@ namespace MWGui void onIncreaseButtonTriggered(); void onDecreaseButtonTriggered(); - // don't show items that the NPC has equipped in his trade-window. - virtual bool ignoreEquippedItems() { return true; } - virtual std::vector getEquippedItems(); - virtual bool isTrading() { return true; } virtual bool isTradeWindow() { return true; } diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index 040a3856e..728b6e32b 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -10,7 +10,9 @@ namespace MWWorld { - ActionOpen::ActionOpen (const MWWorld::Ptr& container) : Action (false, container) + ActionOpen::ActionOpen (const MWWorld::Ptr& container, bool loot) + : Action (false, container) + , mLoot(loot) { } @@ -20,6 +22,6 @@ namespace MWWorld return; MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container); - MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(getTarget()); + MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(getTarget(), mLoot); } } diff --git a/apps/openmw/mwworld/actionopen.hpp b/apps/openmw/mwworld/actionopen.hpp index c49ebefa5..8578995ae 100644 --- a/apps/openmw/mwworld/actionopen.hpp +++ b/apps/openmw/mwworld/actionopen.hpp @@ -13,8 +13,12 @@ namespace MWWorld virtual void executeImp (const MWWorld::Ptr& actor); public: - ActionOpen (const Ptr& container); - ///< \param The Container the Player has activated. + ActionOpen (const Ptr& container, bool loot=false); + ///< \param container The Container the Player has activated. + /// \param loot If true, display the "dispose of corpse" button + + private: + bool mLoot; }; } diff --git a/files/mygui/openmw_container_window.layout b/files/mygui/openmw_container_window.layout index 94e9458a5..452196aae 100644 --- a/files/mygui/openmw_container_window.layout +++ b/files/mygui/openmw_container_window.layout @@ -15,6 +15,10 @@ + + + + From 66a754e9aa515b5b5c9e993e8608ef501b59110c Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 7 Mar 2013 15:25:22 +0100 Subject: [PATCH 145/151] Fix tooltip position when hovering the crosshair over NPCs --- apps/openmw/mwworld/worldimp.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 7d3efe3e8..33a9b52bf 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -996,13 +996,7 @@ namespace MWWorld if (!object.isEmpty ()) { Ogre::SceneNode* node = object.getRefData().getBaseNode(); - Ogre::AxisAlignedBox bounds; - int i; - for (i=0; inumAttachedObjects(); ++i) - { - Ogre::MovableObject* ob = node->getAttachedObject(i); - bounds.merge(ob->getWorldBoundingBox()); - } + Ogre::AxisAlignedBox bounds = node->_getWorldAABB(); if (bounds.isFinite()) { Vector4 screenCoords = mRendering->boundingBoxToScreen(bounds); From f2f4b6e2d5f5e91f752f7f42860118a739a3e865 Mon Sep 17 00:00:00 2001 From: Michal Sciubidlo Date: Thu, 7 Mar 2013 20:15:01 +0100 Subject: [PATCH 146/151] Make MWWorld::getInterior case insensitive. Interior cells names can use different mix of uppercase/lowercase in different places. getInterior() should return same cell in all cases. Fixes bug #586. --- apps/openmw/mwworld/cells.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index b912f5ccc..f95d30df1 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -129,13 +129,14 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name) { - std::map::iterator result = mInteriors.find (name); + std::string lowerName = Misc::StringUtils::lowerCase(name); + std::map::iterator result = mInteriors.find (lowerName); if (result==mInteriors.end()) { - const ESM::Cell *cell = mStore.get().find(name); + const ESM::Cell *cell = mStore.get().find(lowerName); - result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; + result = mInteriors.insert (std::make_pair (lowerName, Ptr::CellStore (cell))).first; } if (result->second.mState!=Ptr::CellStore::State_Loaded) From 3adf3f51212c4330010bf04c63687b7593c29b6f Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Tue, 5 Mar 2013 00:45:25 +0100 Subject: [PATCH 147/151] Revive bsatool --- CMakeLists.txt | 13 ++- apps/bsatool/CMakeLists.txt | 26 ++++++ apps/bsatool/bsatool.cpp | 86 +++++++++++++++++ .../bsa/tests => apps/bsatool}/bsatool.ggo | 0 .../bsa/tests => apps/bsatool}/bsatool_cmd.c | 62 ++++++------- .../bsa/tests => apps/bsatool}/bsatool_cmd.h | 6 +- components/bsa/tests/Makefile | 9 +- components/bsa/tests/bsatool.cpp | 92 ------------------- 8 files changed, 159 insertions(+), 135 deletions(-) create mode 100644 apps/bsatool/CMakeLists.txt create mode 100644 apps/bsatool/bsatool.cpp rename {components/bsa/tests => apps/bsatool}/bsatool.ggo (100%) rename {components/bsa/tests => apps/bsatool}/bsatool_cmd.c (99%) rename {components/bsa/tests => apps/bsatool}/bsatool_cmd.h (98%) delete mode 100644 components/bsa/tests/bsatool.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6498e723c..395027479 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binarie option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE) # Apps and tools +option(BUILD_BSATOOL "build BSA extractor" OFF) option(BUILD_ESMTOOL "build ESM inspector" ON) option(BUILD_LAUNCHER "build Launcher" ON) option(BUILD_MWINIIMPORTER "build MWiniImporter" ON) @@ -352,7 +353,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 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") @@ -446,6 +447,10 @@ add_subdirectory (components) # Apps and tools add_subdirectory( apps/openmw ) +if (BUILD_BSATOOL) + add_subdirectory( apps/bsatool ) +endif() + if (BUILD_ESMTOOL) add_subdirectory( apps/esmtool ) endif() @@ -532,6 +537,9 @@ if (WIN32) set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif (BUILD_LAUNCHER) set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) + if (BUILD_BSATOOL) + set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS}) + endif (BUILD_BSATOOL) if (BUILD_ESMTOOL) set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif (BUILD_ESMTOOL) @@ -656,6 +664,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) + INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_BSATOOL) IF(BUILD_ESMTOOL) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" ) ENDIF(BUILD_ESMTOOL) diff --git a/apps/bsatool/CMakeLists.txt b/apps/bsatool/CMakeLists.txt new file mode 100644 index 000000000..8e33f0675 --- /dev/null +++ b/apps/bsatool/CMakeLists.txt @@ -0,0 +1,26 @@ +set(BSATOOL + bsatool.cpp + bsatool_cmd.c + bsatool_cmd.h +) +source_group(apps\\bsatool FILES ${BSATOOL}) + +# Main executable +add_executable(bsatool + ${BSATOOL} +) + +target_link_libraries(bsatool + ${Boost_LIBRARIES} + components +) + +#if (APPLE) +# find_library(CARBON_FRAMEWORK Carbon) +# target_link_libraries(openmw ${CARBON_FRAMEWORK}) +#endif (APPLE) + +if (BUILD_WITH_CODE_COVERAGE) + add_definitions (--coverage) + target_link_libraries(bsatool gcov) +endif() diff --git a/apps/bsatool/bsatool.cpp b/apps/bsatool/bsatool.cpp new file mode 100644 index 000000000..2d15f8cf7 --- /dev/null +++ b/apps/bsatool/bsatool.cpp @@ -0,0 +1,86 @@ +#include + +#include "bsatool_cmd.h" + +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + gengetopt_args_info info; + + if(cmdline_parser(argc, argv, &info) != 0) + return 1; + + if(info.inputs_num != 1) + { + if(info.inputs_num == 0) + std::cout << "ERROR: missing BSA file\n\n"; + else + std::cout << "ERROR: more than one BSA file specified\n\n"; + cmdline_parser_print_help(); + return 1; + } + + // Open file + Bsa::BSAFile bsa; + char *arcname = info.inputs[0]; + try { bsa.open(arcname); } + catch(std::exception &e) + { + std::cout << "ERROR reading BSA archive '" << arcname + << "'\nDetails:\n" << e.what() << std::endl; + return 2; + } + + if(info.extract_given) + { + char *file = info.extract_arg; + + if(!bsa.exists(file)) + { + std::cout << "ERROR: file '" << file << "' not found\n"; + std::cout << "In archive: " << arcname << std::endl; + return 3; + } + + // Find the base name of the file + int pos = strlen(file); + while(pos > 0 && file[pos] != '\\') pos--; + char *base = file+pos+1; + + // TODO: We might add full directory name extraction later. We + // could also allow automatic conversion from / to \ in + // parameter file names. + + // Load the file into a memory buffer + Ogre::DataStreamPtr data = bsa.getFile(file); + + // Write the file to disk + std::ofstream out(base, std::ios::binary); + out.write(data->getAsString().c_str(), data->size()); + out.close(); + + return 0; + } + + // List all files + const Bsa::BSAFile::FileList &files = bsa.getList(); + for(int i=0; i -#include +#include +#include #include #ifndef FIX_UNUSED @@ -71,7 +71,7 @@ void clear_args (struct gengetopt_args_info *args_info) FIX_UNUSED (args_info); args_info->extract_arg = NULL; args_info->extract_orig = NULL; - + } static @@ -83,7 +83,7 @@ void init_args_info(struct gengetopt_args_info *args_info) args_info->version_help = gengetopt_args_info_help[1] ; args_info->extract_help = gengetopt_args_info_help[2] ; args_info->long_help = gengetopt_args_info_help[3] ; - + } void @@ -133,7 +133,7 @@ void cmdline_parser_params_init(struct cmdline_parser_params *params) { if (params) - { + { params->override = 0; params->initialize = 1; params->check_required = 1; @@ -145,9 +145,9 @@ cmdline_parser_params_init(struct cmdline_parser_params *params) struct cmdline_parser_params * cmdline_parser_params_create(void) { - struct cmdline_parser_params *params = + struct cmdline_parser_params *params = (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); - cmdline_parser_params_init(params); + cmdline_parser_params_init(params); return params; } @@ -168,8 +168,8 @@ cmdline_parser_release (struct gengetopt_args_info *args_info) unsigned int i; free_string_field (&(args_info->extract_arg)); free_string_field (&(args_info->extract_orig)); - - + + for (i = 0; i < args_info->inputs_num; ++i) free (args_info->inputs [i]); @@ -211,7 +211,7 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) write_into_file(outfile, "extract", args_info->extract_orig, 0); if (args_info->long_given) write_into_file(outfile, "long", 0, 0 ); - + i = EXIT_SUCCESS; return i; @@ -276,7 +276,7 @@ cmdline_parser_ext (int argc, char * const *argv, struct gengetopt_args_info *ar cmdline_parser_free (args_info); exit (EXIT_FAILURE); } - + return result; } @@ -285,7 +285,7 @@ cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_ { int result; struct cmdline_parser_params params; - + params.override = override; params.initialize = initialize; params.check_required = check_required; @@ -299,7 +299,7 @@ cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_ cmdline_parser_free (args_info); exit (EXIT_FAILURE); } - + return result; } @@ -324,7 +324,7 @@ cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog * */ -/* +/* * we must include anything we need since this file is not thought to be * inserted in a file already using getopt.h * @@ -859,7 +859,7 @@ static int getopt_internal_r(int argc, char *const *argv, const char *optstring, return -1; d->custom_optarg = NULL; - /* + /* * This is a big difference with GNU getopt, since optind == 0 * means initialization while here 1 means first call. */ @@ -926,7 +926,7 @@ static char *package_name = 0; */ static int update_arg(void *field, char **orig_field, - unsigned int *field_given, unsigned int *prev_given, + unsigned int *field_given, unsigned int *prev_given, char *value, const char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, @@ -947,18 +947,18 @@ int update_arg(void *field, char **orig_field, if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { if (short_opt != '-') - fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", + fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", package_name, long_opt, short_opt, (additional_error ? additional_error : "")); else - fprintf (stderr, "%s: `--%s' option given more than once%s\n", + fprintf (stderr, "%s: `--%s' option given more than once%s\n", package_name, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } FIX_UNUSED (default_value); - + if (field_given && *field_given && ! override) return 0; if (prev_given) @@ -1011,7 +1011,7 @@ cmdline_parser_internal ( int error = 0; struct gengetopt_args_info local_args_info; - + int override; int initialize; int check_required; @@ -1021,9 +1021,9 @@ cmdline_parser_internal ( int optind; int opterr; int optopt; - + package_name = argv[0]; - + override = params->override; initialize = params->initialize; check_required = params->check_required; @@ -1078,28 +1078,28 @@ cmdline_parser_internal ( exit (EXIT_SUCCESS); case 'x': /* Extract file from archive. */ - - - if (update_arg( (void *)&(args_info->extract_arg), + + + if (update_arg( (void *)&(args_info->extract_arg), &(args_info->extract_orig), &(args_info->extract_given), &(local_args_info.extract_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "extract", 'x', additional_error)) goto failure; - + break; case 'l': /* Include extra information in archive listing. */ - - - if (update_arg( 0 , + + + if (update_arg( 0 , 0 , &(args_info->long_given), &(local_args_info.long_given), optarg, 0, 0, ARG_NO, check_ambiguity, override, 0, 0, "long", 'l', additional_error)) goto failure; - + break; case 0: /* Long option with no short option */ @@ -1140,7 +1140,7 @@ cmdline_parser_internal ( return 0; failure: - + cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } diff --git a/components/bsa/tests/bsatool_cmd.h b/apps/bsatool/bsatool_cmd.h similarity index 98% rename from components/bsa/tests/bsatool_cmd.h rename to apps/bsatool/bsatool_cmd.h index 98fe2633f..4d5f80ea2 100644 --- a/components/bsa/tests/bsatool_cmd.h +++ b/apps/bsatool/bsatool_cmd.h @@ -13,7 +13,7 @@ #include "config.h" #endif -#include /* for FILE */ +#include /* for FILE */ #ifdef __cplusplus extern "C" { @@ -43,7 +43,7 @@ struct gengetopt_args_info char * extract_orig; /**< @brief Extract file from archive original value given at command line. */ const char *extract_help; /**< @brief Extract file from archive help description. */ const char *long_help; /**< @brief Include extra information in archive listing help description. */ - + unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int extract_given ; /**< @brief Whether extract was given. */ @@ -136,7 +136,7 @@ void cmdline_parser_print_help(void); void cmdline_parser_print_version(void); /** - * Initializes all the fields a cmdline_parser_params structure + * Initializes all the fields a cmdline_parser_params structure * to their default values * @param params the structure to initialize */ diff --git a/components/bsa/tests/Makefile b/components/bsa/tests/Makefile index bc2bf4e50..73e20d7b3 100644 --- a/components/bsa/tests/Makefile +++ b/components/bsa/tests/Makefile @@ -1,6 +1,6 @@ GCC=g++ -all: bsa_file_test bsatool ogre_archive_test +all: bsa_file_test ogre_archive_test I_OGRE=$(shell pkg-config --cflags OGRE) L_OGRE=$(shell pkg-config --libs OGRE) @@ -11,12 +11,5 @@ bsa_file_test: bsa_file_test.cpp ../bsa_file.cpp ogre_archive_test: ogre_archive_test.cpp ../bsa_file.cpp ../bsa_archive.cpp $(GCC) $^ -o $@ $(I_OGRE) $(L_OGRE) -bsatool: bsatool.cpp ../bsa_file.cpp bsatool_cmd.c - $(GCC) $^ -o $@ - -bsatool_cmd.c: bsatool.ggo - gengetopt < bsatool.ggo - clean: rm *_test - rm bsatool diff --git a/components/bsa/tests/bsatool.cpp b/components/bsa/tests/bsatool.cpp deleted file mode 100644 index df37e3827..000000000 --- a/components/bsa/tests/bsatool.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "../bsa_file.hpp" - -#include "bsatool_cmd.h" - -#include -#include -#include -#include - -#include "../../mangle/stream/filters/buffer_stream.hpp" - -using namespace std; -using namespace Mangle::Stream; -using namespace Bsa; - -int main(int argc, char** argv) -{ - gengetopt_args_info info; - - if(cmdline_parser(argc, argv, &info) != 0) - return 1; - - if(info.inputs_num != 1) - { - if(info.inputs_num == 0) - cout << "ERROR: missing BSA file\n\n"; - else - cout << "ERROR: more than one BSA file specified\n\n"; - cmdline_parser_print_help(); - return 1; - } - - // Open file - BSAFile bsa; - char *arcname = info.inputs[0]; - try { bsa.open(arcname); } - catch(exception &e) - { - cout << "ERROR reading BSA archive '" << arcname - << "'\nDetails:\n" << e.what() << endl; - return 2; - } - - if(info.extract_given) - { - char *file = info.extract_arg; - - if(!bsa.exists(file)) - { - cout << "ERROR: file '" << file << "' not found\n"; - cout << "In archive: " << arcname << endl; - return 3; - } - - // Find the base name of the file - int pos = strlen(file); - while(pos > 0 && file[pos] != '\\') pos--; - char *base = file+pos+1; - - // TODO: We might add full directory name extraction later. We - // could also allow automatic conversion from / to \ in - // parameter file names. - - // Load the file into a memory buffer - BufferStream data(bsa.getFile(file)); - - // Write the file to disk - ofstream out(base, ios::binary); - out.write((char*)data.getPtr(), data.size()); - out.close(); - - return 0; - } - - // List all files - const BSAFile::FileList &files = bsa.getList(); - for(int i=0; i Date: Thu, 7 Mar 2013 21:05:56 +0100 Subject: [PATCH 148/151] Bsatool: extract and extractall modes --- apps/bsatool/CMakeLists.txt | 7 - apps/bsatool/bsatool.cpp | 304 ++++++++-- apps/bsatool/bsatool.ggo | 11 - apps/bsatool/bsatool_cmd.c | 1146 ----------------------------------- apps/bsatool/bsatool_cmd.h | 179 ------ 5 files changed, 253 insertions(+), 1394 deletions(-) delete mode 100644 apps/bsatool/bsatool.ggo delete mode 100644 apps/bsatool/bsatool_cmd.c delete mode 100644 apps/bsatool/bsatool_cmd.h diff --git a/apps/bsatool/CMakeLists.txt b/apps/bsatool/CMakeLists.txt index 8e33f0675..3f1988a70 100644 --- a/apps/bsatool/CMakeLists.txt +++ b/apps/bsatool/CMakeLists.txt @@ -1,7 +1,5 @@ set(BSATOOL bsatool.cpp - bsatool_cmd.c - bsatool_cmd.h ) source_group(apps\\bsatool FILES ${BSATOOL}) @@ -15,11 +13,6 @@ target_link_libraries(bsatool components ) -#if (APPLE) -# find_library(CARBON_FRAMEWORK Carbon) -# target_link_libraries(openmw ${CARBON_FRAMEWORK}) -#endif (APPLE) - if (BUILD_WITH_CODE_COVERAGE) add_definitions (--coverage) target_link_libraries(bsatool gcov) diff --git a/apps/bsatool/bsatool.cpp b/apps/bsatool/bsatool.cpp index 2d15f8cf7..e6fcc2567 100644 --- a/apps/bsatool/bsatool.cpp +++ b/apps/bsatool/bsatool.cpp @@ -1,76 +1,192 @@ +#include +#include +#include + +#include +#include +#include + #include -#include "bsatool_cmd.h" +#define BSATOOL_VERSION 1.1 -#include -#include -#include -#include +// Create local aliases for brevity +namespace bpo = boost::program_options; +namespace bfs = boost::filesystem; + +struct Arguments +{ + std::string mode; + std::string filename; + std::string extractfile; + std::string outdir; + + bool longformat; + bool fullpath; +}; + +void replaceAll(std::string& str, const std::string& needle, const std::string& substitute) +{ + int pos = str.find(needle); + while(pos != -1) + { + str.replace(pos, needle.size(), substitute); + pos = str.find(needle); + } +} + +bool parseOptions (int argc, char** argv, Arguments &info) +{ + bpo::options_description desc("Inspect and extract files from Bethesda BSA archives\n\n" + "Usages:\n" + " bsatool list [-l] archivefile\n" + " List the files presents in the input archive.\n\n" + " bsatool extract [-f] archivefile [file_to_extract] [output_directory]\n" + " Extract a file from the input archive.\n\n" + " bsatool extractall archivefile [output_directory]\n" + " Extract all files from the input archive.\n\n" + "Allowed options"); + + desc.add_options() + ("help,h", "print help message.") + ("version,v", "print version information and quit.") + ("long,l", "Include extra information in archive listing.") + ("full-path,f", "Create diretory hierarchy on file extraction " + "(always true for extractall).") + ; + + // input-file is hidden and used as a positional argument + bpo::options_description hidden("Hidden Options"); + + hidden.add_options() + ( "mode,m", bpo::value(), "bsatool mode") + ( "input-file,i", bpo::value< std::vector >(), "input file") + ; + + bpo::positional_options_description p; + p.add("mode", 1).add("input-file", 3); + + // there might be a better way to do this + bpo::options_description all; + all.add(desc).add(hidden); + + bpo::variables_map variables; + try + { + bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv) + .options(all).positional(p).run(); + bpo::store(valid_opts, variables); + } + catch(std::exception &e) + { + std::cout << "ERROR parsing arguments: " << e.what() << "\n\n" + << desc << std::endl; + return false; + } + + bpo::notify(variables); + + if (variables.count ("help")) + { + std::cout << desc << std::endl; + return false; + } + if (variables.count ("version")) + { + std::cout << "BSATool version " << BSATOOL_VERSION << std::endl; + return false; + } + if (!variables.count("mode")) + { + std::cout << "ERROR: no mode specified!\n\n" + << desc << std::endl; + return false; + } + + info.mode = variables["mode"].as(); + if (!(info.mode == "list" || info.mode == "extract" || info.mode == "extractall")) + { + std::cout << std::endl << "ERROR: invalid mode \"" << info.mode << "\"\n\n" + << desc << std::endl; + return false; + } + + if (!variables.count("input-file")) + { + std::cout << "\nERROR: missing BSA archive\n\n" + << desc << std::endl; + return false; + } + info.filename = variables["input-file"].as< std::vector >()[0]; + + // Default output to the working directory + info.outdir = "."; + + if (info.mode == "extract") + { + if (variables["input-file"].as< std::vector >().size() < 2) + { + std::cout << "\nERROR: file to extract unspecified\n\n" + << desc << std::endl; + return false; + } + if (variables["input-file"].as< std::vector >().size() > 1) + info.extractfile = variables["input-file"].as< std::vector >()[1]; + if (variables["input-file"].as< std::vector >().size() > 2) + info.outdir = variables["input-file"].as< std::vector >()[2]; + } + else if (variables["input-file"].as< std::vector >().size() > 1) + info.outdir = variables["input-file"].as< std::vector >()[1]; + + info.longformat = variables.count("long"); + info.fullpath = variables.count("full-path"); + + return true; +} + +int list(Bsa::BSAFile& bsa, Arguments& info); +int extract(Bsa::BSAFile& bsa, Arguments& info); +int extractAll(Bsa::BSAFile& bsa, Arguments& info); int main(int argc, char** argv) { - gengetopt_args_info info; - - if(cmdline_parser(argc, argv, &info) != 0) + Arguments info; + if(!parseOptions (argc, argv, info)) return 1; - if(info.inputs_num != 1) - { - if(info.inputs_num == 0) - std::cout << "ERROR: missing BSA file\n\n"; - else - std::cout << "ERROR: more than one BSA file specified\n\n"; - cmdline_parser_print_help(); - return 1; - } - // Open file Bsa::BSAFile bsa; - char *arcname = info.inputs[0]; - try { bsa.open(arcname); } + try + { + bsa.open(info.filename); + } catch(std::exception &e) { - std::cout << "ERROR reading BSA archive '" << arcname + std::cout << "ERROR reading BSA archive '" << info.filename << "'\nDetails:\n" << e.what() << std::endl; return 2; } - if(info.extract_given) + if (info.mode == "list") + return list(bsa, info); + else if (info.mode == "extract") + return extract(bsa, info); + else if (info.mode == "extractall") + return extractAll(bsa, info); + else { - char *file = info.extract_arg; - - if(!bsa.exists(file)) - { - std::cout << "ERROR: file '" << file << "' not found\n"; - std::cout << "In archive: " << arcname << std::endl; - return 3; - } - - // Find the base name of the file - int pos = strlen(file); - while(pos > 0 && file[pos] != '\\') pos--; - char *base = file+pos+1; - - // TODO: We might add full directory name extraction later. We - // could also allow automatic conversion from / to \ in - // parameter file names. - - // Load the file into a memory buffer - Ogre::DataStreamPtr data = bsa.getFile(file); - - // Write the file to disk - std::ofstream out(base, std::ios::binary); - out.write(data->getAsString().c_str(), data->size()); - out.close(); - - return 0; + std::cout << "Unsupported mode. That is not supposed to happen." << std::endl; + return 1; } +} +int list(Bsa::BSAFile& bsa, Arguments& info) +{ // List all files const Bsa::BSAFile::FileList &files = bsa.getList(); for(int i=0; igetAsString().c_str(), data->size()); + out.close(); + + return 0; +} + +int extractAll(Bsa::BSAFile& bsa, Arguments& info) +{ + // Get the list of files present in the archive + Bsa::BSAFile::FileList list = bsa.getList(); + + // Iter on the list + for(Bsa::BSAFile::FileList::iterator it = list.begin(); it != list.end(); ++it) { + const char* archivePath = it->name; + + std::string extractPath (archivePath); + replaceAll(extractPath, "\\", "/"); + + // Get the target path (the path the file will be extracted to) + bfs::path target (info.outdir); + target /= extractPath; + + // Create the directory hierarchy + bfs::create_directories(target.parent_path()); + + bfs::file_status s = bfs::status(target.parent_path()); + if (!bfs::is_directory(s)) + { + std::cout << "ERROR: " << target.parent_path() << " is not a directory." << std::endl; + return 3; + } + + // Get a stream for the file to extract + // (inefficient because getFile iter on the list again) + Ogre::DataStreamPtr data = bsa.getFile(archivePath); + bfs::ofstream out(target, std::ios::binary); + + // Write the file to disk + std::cout << "Extracting " << target << std::endl; + out.write(data->getAsString().c_str(), data->size()); + out.close(); + } + return 0; } diff --git a/apps/bsatool/bsatool.ggo b/apps/bsatool/bsatool.ggo deleted file mode 100644 index 2e4227a1b..000000000 --- a/apps/bsatool/bsatool.ggo +++ /dev/null @@ -1,11 +0,0 @@ -package "bsatool" -version "1.0" -purpose "Inspect and extract files from Bethesda BSA archives" -#usage "" -#description "" -args "--unamed-opts=BSA-FILE -F bsatool_cmd -G" - -option "extract" x "Extract file from archive" string optional -option "long" l "Include extra information in archive listing" optional - -text "\nIf no option is given, the default action is to list all files in the archive." diff --git a/apps/bsatool/bsatool_cmd.c b/apps/bsatool/bsatool_cmd.c deleted file mode 100644 index 0b0ed66c2..000000000 --- a/apps/bsatool/bsatool_cmd.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - File autogenerated by gengetopt version 2.22.2 - generated with the following command: - gengetopt --unamed-opts=BSA-FILE -F bsatool_cmd -G - - The developers of gengetopt consider the fixed text that goes in all - gengetopt output files to be in the public domain: - we make no copyright claims on it. -*/ - -/* If we use autoconf. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#ifndef FIX_UNUSED -#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ -#endif - - -#include "bsatool_cmd.h" - -const char *gengetopt_args_info_purpose = "Inspect and extract files from Bethesda BSA archives"; - -const char *gengetopt_args_info_usage = "Usage: bsatool [OPTIONS]... [BSA-FILE]..."; - -const char *gengetopt_args_info_description = ""; - -const char *gengetopt_args_info_help[] = { - " -h, --help Print help and exit", - " -V, --version Print version and exit", - " -x, --extract=STRING Extract file from archive", - " -l, --long Include extra information in archive listing", - "\nIf no option is given, the default action is to list all files in the archive.", - 0 -}; - -typedef enum {ARG_NO - , ARG_STRING -} cmdline_parser_arg_type; - -static -void clear_given (struct gengetopt_args_info *args_info); -static -void clear_args (struct gengetopt_args_info *args_info); - -static int -cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, - struct cmdline_parser_params *params, const char *additional_error); - - -static char * -gengetopt_strdup (const char *s); - -static -void clear_given (struct gengetopt_args_info *args_info) -{ - args_info->help_given = 0 ; - args_info->version_given = 0 ; - args_info->extract_given = 0 ; - args_info->long_given = 0 ; -} - -static -void clear_args (struct gengetopt_args_info *args_info) -{ - FIX_UNUSED (args_info); - args_info->extract_arg = NULL; - args_info->extract_orig = NULL; - -} - -static -void init_args_info(struct gengetopt_args_info *args_info) -{ - - - args_info->help_help = gengetopt_args_info_help[0] ; - args_info->version_help = gengetopt_args_info_help[1] ; - args_info->extract_help = gengetopt_args_info_help[2] ; - args_info->long_help = gengetopt_args_info_help[3] ; - -} - -void -cmdline_parser_print_version (void) -{ - printf ("%s %s\n", - (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), - CMDLINE_PARSER_VERSION); -} - -static void print_help_common(void) { - cmdline_parser_print_version (); - - if (strlen(gengetopt_args_info_purpose) > 0) - printf("\n%s\n", gengetopt_args_info_purpose); - - if (strlen(gengetopt_args_info_usage) > 0) - printf("\n%s\n", gengetopt_args_info_usage); - - printf("\n"); - - if (strlen(gengetopt_args_info_description) > 0) - printf("%s\n\n", gengetopt_args_info_description); -} - -void -cmdline_parser_print_help (void) -{ - int i = 0; - print_help_common(); - while (gengetopt_args_info_help[i]) - printf("%s\n", gengetopt_args_info_help[i++]); -} - -void -cmdline_parser_init (struct gengetopt_args_info *args_info) -{ - clear_given (args_info); - clear_args (args_info); - init_args_info (args_info); - - args_info->inputs = 0; - args_info->inputs_num = 0; -} - -void -cmdline_parser_params_init(struct cmdline_parser_params *params) -{ - if (params) - { - params->override = 0; - params->initialize = 1; - params->check_required = 1; - params->check_ambiguity = 0; - params->print_errors = 1; - } -} - -struct cmdline_parser_params * -cmdline_parser_params_create(void) -{ - struct cmdline_parser_params *params = - (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); - cmdline_parser_params_init(params); - return params; -} - -static void -free_string_field (char **s) -{ - if (*s) - { - free (*s); - *s = 0; - } -} - - -static void -cmdline_parser_release (struct gengetopt_args_info *args_info) -{ - unsigned int i; - free_string_field (&(args_info->extract_arg)); - free_string_field (&(args_info->extract_orig)); - - - for (i = 0; i < args_info->inputs_num; ++i) - free (args_info->inputs [i]); - - if (args_info->inputs_num) - free (args_info->inputs); - - clear_given (args_info); -} - - -static void -write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) -{ - FIX_UNUSED (values); - if (arg) { - fprintf(outfile, "%s=\"%s\"\n", opt, arg); - } else { - fprintf(outfile, "%s\n", opt); - } -} - - -int -cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) -{ - int i = 0; - - if (!outfile) - { - fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); - return EXIT_FAILURE; - } - - if (args_info->help_given) - write_into_file(outfile, "help", 0, 0 ); - if (args_info->version_given) - write_into_file(outfile, "version", 0, 0 ); - if (args_info->extract_given) - write_into_file(outfile, "extract", args_info->extract_orig, 0); - if (args_info->long_given) - write_into_file(outfile, "long", 0, 0 ); - - - i = EXIT_SUCCESS; - return i; -} - -int -cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) -{ - FILE *outfile; - int i = 0; - - outfile = fopen(filename, "w"); - - if (!outfile) - { - fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); - return EXIT_FAILURE; - } - - i = cmdline_parser_dump(outfile, args_info); - fclose (outfile); - - return i; -} - -void -cmdline_parser_free (struct gengetopt_args_info *args_info) -{ - cmdline_parser_release (args_info); -} - -/** @brief replacement of strdup, which is not standard */ -char * -gengetopt_strdup (const char *s) -{ - char *result = 0; - if (!s) - return result; - - result = (char*)malloc(strlen(s) + 1); - if (result == (char*)0) - return (char*)0; - strcpy(result, s); - return result; -} - -int -cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info) -{ - return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); -} - -int -cmdline_parser_ext (int argc, char * const *argv, struct gengetopt_args_info *args_info, - struct cmdline_parser_params *params) -{ - int result; - result = cmdline_parser_internal (argc, argv, args_info, params, 0); - - if (result == EXIT_FAILURE) - { - cmdline_parser_free (args_info); - exit (EXIT_FAILURE); - } - - return result; -} - -int -cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) -{ - int result; - struct cmdline_parser_params params; - - params.override = override; - params.initialize = initialize; - params.check_required = check_required; - params.check_ambiguity = 0; - params.print_errors = 1; - - result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); - - if (result == EXIT_FAILURE) - { - cmdline_parser_free (args_info); - exit (EXIT_FAILURE); - } - - return result; -} - -int -cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) -{ - FIX_UNUSED (args_info); - FIX_UNUSED (prog_name); - return EXIT_SUCCESS; -} - -/* - * Extracted from the glibc source tree, version 2.3.6 - * - * Licensed under the GPL as per the whole glibc source tree. - * - * This file was modified so that getopt_long can be called - * many times without risking previous memory to be spoiled. - * - * Modified by Andre Noll and Lorenzo Bettini for use in - * GNU gengetopt generated files. - * - */ - -/* - * we must include anything we need since this file is not thought to be - * inserted in a file already using getopt.h - * - * Lorenzo - */ - -struct option -{ - const char *name; - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. -*/ -/* - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `custom_optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -/* Names for the values of the `has_arg' field of `struct option'. */ -#ifndef no_argument -#define no_argument 0 -#endif - -#ifndef required_argument -#define required_argument 1 -#endif - -#ifndef optional_argument -#define optional_argument 2 -#endif - -struct custom_getopt_data { - /* - * These have exactly the same meaning as the corresponding global variables, - * except that they are used for the reentrant versions of getopt. - */ - int custom_optind; - int custom_opterr; - int custom_optopt; - char *custom_optarg; - - /* True if the internal members have been initialized. */ - int initialized; - - /* - * The next char to be scanned in the option-element in which the last option - * character we returned was found. This allows us to pick up the scan where - * we left off. If this is zero, or a null string, it means resume the scan by - * advancing to the next ARGV-element. - */ - char *nextchar; - - /* - * Describe the part of ARGV that contains non-options that have been skipped. - * `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is - * the index after the last of them. - */ - int first_nonopt; - int last_nonopt; -}; - -/* - * the variables optarg, optind, opterr and optopt are renamed with - * the custom_ prefix so that they don't interfere with getopt ones. - * - * Moreover they're static so they are visible only from within the - * file where this very file will be included. - */ - -/* - * For communication from `custom_getopt' to the caller. When `custom_getopt' finds an - * option that takes an argument, the argument value is returned here. - */ -static char *custom_optarg; - -/* - * Index in ARGV of the next element to be scanned. This is used for - * communication to and from the caller and for communication between - * successive calls to `custom_getopt'. - * - * On entry to `custom_getopt', 1 means this is the first call; initialize. - * - * When `custom_getopt' returns -1, this is the index of the first of the non-option - * elements that the caller should itself scan. - * - * Otherwise, `custom_optind' communicates from one call to the next how much of ARGV - * has been scanned so far. - * - * 1003.2 says this must be 1 before any call. - */ -static int custom_optind = 1; - -/* - * Callers store zero here to inhibit the error message for unrecognized - * options. - */ -static int custom_opterr = 1; - -/* - * Set to an option character which was unrecognized. This must be initialized - * on some systems to avoid linking in the system's own getopt implementation. - */ -static int custom_optopt = '?'; - -/* - * Exchange two adjacent subsequences of ARGV. One subsequence is elements - * [first_nonopt,last_nonopt) which contains all the non-options that have been - * skipped so far. The other is elements [last_nonopt,custom_optind), which contains - * all the options processed since those non-options were skipped. - * `first_nonopt' and `last_nonopt' are relocated so that they describe the new - * indices of the non-options in ARGV after they are moved. - */ -static void exchange(char **argv, struct custom_getopt_data *d) -{ - int bottom = d->first_nonopt; - int middle = d->last_nonopt; - int top = d->custom_optind; - char *tem; - - /* - * Exchange the shorter segment with the far end of the longer segment. - * That puts the shorter segment into the right place. It leaves the - * longer segment in the right place overall, but it consists of two - * parts that need to be swapped next. - */ - while (top > middle && middle > bottom) { - if (top - middle > middle - bottom) { - /* Bottom segment is the short one. */ - int len = middle - bottom; - int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) { - tem = argv[bottom + i]; - argv[bottom + i] = - argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } else { - /* Top segment is the short one. */ - int len = top - middle; - int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - /* Update records for the slots the non-options now occupy. */ - d->first_nonopt += (d->custom_optind - d->last_nonopt); - d->last_nonopt = d->custom_optind; -} - -/* Initialize the internal data when the first call is made. */ -static void custom_getopt_initialize(struct custom_getopt_data *d) -{ - /* - * Start processing options with ARGV-element 1 (since ARGV-element 0 - * is the program name); the sequence of previously skipped non-option - * ARGV-elements is empty. - */ - d->first_nonopt = d->last_nonopt = d->custom_optind; - d->nextchar = NULL; - d->initialized = 1; -} - -#define NONOPTION_P (argv[d->custom_optind][0] != '-' || argv[d->custom_optind][1] == '\0') - -/* return: zero: continue, nonzero: return given value to user */ -static int shuffle_argv(int argc, char *const *argv,const struct option *longopts, - struct custom_getopt_data *d) -{ - /* - * Give FIRST_NONOPT & LAST_NONOPT rational values if CUSTOM_OPTIND has been - * moved back by the user (who may also have changed the arguments). - */ - if (d->last_nonopt > d->custom_optind) - d->last_nonopt = d->custom_optind; - if (d->first_nonopt > d->custom_optind) - d->first_nonopt = d->custom_optind; - /* - * If we have just processed some options following some - * non-options, exchange them so that the options come first. - */ - if (d->first_nonopt != d->last_nonopt && - d->last_nonopt != d->custom_optind) - exchange((char **) argv, d); - else if (d->last_nonopt != d->custom_optind) - d->first_nonopt = d->custom_optind; - /* - * Skip any additional non-options and extend the range of - * non-options previously skipped. - */ - while (d->custom_optind < argc && NONOPTION_P) - d->custom_optind++; - d->last_nonopt = d->custom_optind; - /* - * The special ARGV-element `--' means premature end of options. Skip - * it like a null option, then exchange with previous non-options as if - * it were an option, then skip everything else like a non-option. - */ - if (d->custom_optind != argc && !strcmp(argv[d->custom_optind], "--")) { - d->custom_optind++; - if (d->first_nonopt != d->last_nonopt - && d->last_nonopt != d->custom_optind) - exchange((char **) argv, d); - else if (d->first_nonopt == d->last_nonopt) - d->first_nonopt = d->custom_optind; - d->last_nonopt = argc; - d->custom_optind = argc; - } - /* - * If we have done all the ARGV-elements, stop the scan and back over - * any non-options that we skipped and permuted. - */ - if (d->custom_optind == argc) { - /* - * Set the next-arg-index to point at the non-options that we - * previously skipped, so the caller will digest them. - */ - if (d->first_nonopt != d->last_nonopt) - d->custom_optind = d->first_nonopt; - return -1; - } - /* - * If we have come to a non-option and did not permute it, either stop - * the scan or describe it to the caller and pass it by. - */ - if (NONOPTION_P) { - d->custom_optarg = argv[d->custom_optind++]; - return 1; - } - /* - * We have found another option-ARGV-element. Skip the initial - * punctuation. - */ - d->nextchar = (argv[d->custom_optind] + 1 + (longopts != NULL && argv[d->custom_optind][1] == '-')); - return 0; -} - -/* - * Check whether the ARGV-element is a long option. - * - * If there's a long option "fubar" and the ARGV-element is "-fu", consider - * that an abbreviation of the long option, just like "--fu", and not "-f" with - * arg "u". - * - * This distinction seems to be the most useful approach. - * - */ -static int check_long_opt(int argc, char *const *argv, const char *optstring, - const struct option *longopts, int *longind, - int print_errors, struct custom_getopt_data *d) -{ - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = d->nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match or abbreviated matches */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp(p->name, d->nextchar, nameend - d->nextchar)) { - if ((unsigned int) (nameend - d->nextchar) - == (unsigned int) strlen(p->name)) { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } else if (pfound == NULL) { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } else if (pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) { - if (print_errors) { - fprintf(stderr, - "%s: option `%s' is ambiguous\n", - argv[0], argv[d->custom_optind]); - } - d->nextchar += strlen(d->nextchar); - d->custom_optind++; - d->custom_optopt = 0; - return '?'; - } - if (pfound) { - option_index = indfound; - d->custom_optind++; - if (*nameend) { - if (pfound->has_arg != no_argument) - d->custom_optarg = nameend + 1; - else { - if (print_errors) { - if (argv[d->custom_optind - 1][1] == '-') { - /* --option */ - fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", - argv[0], pfound->name); - } else { - /* +option or -option */ - fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", - argv[0], argv[d->custom_optind - 1][0], pfound->name); - } - - } - d->nextchar += strlen(d->nextchar); - d->custom_optopt = pfound->val; - return '?'; - } - } else if (pfound->has_arg == required_argument) { - if (d->custom_optind < argc) - d->custom_optarg = argv[d->custom_optind++]; - else { - if (print_errors) { - fprintf(stderr, - "%s: option `%s' requires an argument\n", - argv[0], - argv[d->custom_optind - 1]); - } - d->nextchar += strlen(d->nextchar); - d->custom_optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - d->nextchar += strlen(d->nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - /* - * Can't find it as a long option. If this is not getopt_long_only, or - * the option starts with '--' or is not a valid short option, then - * it's an error. Otherwise interpret it as a short option. - */ - if (print_errors) { - if (argv[d->custom_optind][1] == '-') { - /* --option */ - fprintf(stderr, - "%s: unrecognized option `--%s'\n", - argv[0], d->nextchar); - } else { - /* +option or -option */ - fprintf(stderr, - "%s: unrecognized option `%c%s'\n", - argv[0], argv[d->custom_optind][0], - d->nextchar); - } - } - d->nextchar = (char *) ""; - d->custom_optind++; - d->custom_optopt = 0; - return '?'; -} - -static int check_short_opt(int argc, char *const *argv, const char *optstring, - int print_errors, struct custom_getopt_data *d) -{ - char c = *d->nextchar++; - const char *temp = strchr(optstring, c); - - /* Increment `custom_optind' when we start to process its last character. */ - if (*d->nextchar == '\0') - ++d->custom_optind; - if (!temp || c == ':') { - if (print_errors) - fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); - - d->custom_optopt = c; - return '?'; - } - if (temp[1] == ':') { - if (temp[2] == ':') { - /* This is an option that accepts an argument optionally. */ - if (*d->nextchar != '\0') { - d->custom_optarg = d->nextchar; - d->custom_optind++; - } else - d->custom_optarg = NULL; - d->nextchar = NULL; - } else { - /* This is an option that requires an argument. */ - if (*d->nextchar != '\0') { - d->custom_optarg = d->nextchar; - /* - * If we end this ARGV-element by taking the - * rest as an arg, we must advance to the next - * element now. - */ - d->custom_optind++; - } else if (d->custom_optind == argc) { - if (print_errors) { - fprintf(stderr, - "%s: option requires an argument -- %c\n", - argv[0], c); - } - d->custom_optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } else - /* - * We already incremented `custom_optind' once; - * increment it again when taking next ARGV-elt - * as argument. - */ - d->custom_optarg = argv[d->custom_optind++]; - d->nextchar = NULL; - } - } - return c; -} - -/* - * Scan elements of ARGV for option characters given in OPTSTRING. - * - * If an element of ARGV starts with '-', and is not exactly "-" or "--", - * then it is an option element. The characters of this element - * (aside from the initial '-') are option characters. If `getopt' - * is called repeatedly, it returns successively each of the option characters - * from each of the option elements. - * - * If `getopt' finds another option character, it returns that character, - * updating `custom_optind' and `nextchar' so that the next call to `getopt' can - * resume the scan with the following option character or ARGV-element. - * - * If there are no more option characters, `getopt' returns -1. - * Then `custom_optind' is the index in ARGV of the first ARGV-element - * that is not an option. (The ARGV-elements have been permuted - * so that those that are not options now come last.) - * - * OPTSTRING is a string containing the legitimate option characters. - * If an option character is seen that is not listed in OPTSTRING, - * return '?' after printing an error message. If you set `custom_opterr' to - * zero, the error message is suppressed but we still return '?'. - * - * If a char in OPTSTRING is followed by a colon, that means it wants an arg, - * so the following text in the same ARGV-element, or the text of the following - * ARGV-element, is returned in `custom_optarg'. Two colons mean an option that - * wants an optional arg; if there is text in the current ARGV-element, - * it is returned in `custom_optarg', otherwise `custom_optarg' is set to zero. - * - * If OPTSTRING starts with `-' or `+', it requests different methods of - * handling the non-option ARGV-elements. - * See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - * - * Long-named options begin with `--' instead of `-'. - * Their names may be abbreviated as long as the abbreviation is unique - * or is an exact match for some defined option. If they have an - * argument, it follows the option name in the same ARGV-element, separated - * from the option name by a `=', or else the in next ARGV-element. - * When `getopt' finds a long-named option, it returns 0 if that option's - * `flag' field is nonzero, the value of the option's `val' field - * if the `flag' field is zero. - * - * The elements of ARGV aren't really const, because we permute them. - * But we pretend they're const in the prototype to be compatible - * with other systems. - * - * LONGOPTS is a vector of `struct option' terminated by an - * element containing a name which is zero. - * - * LONGIND returns the index in LONGOPT of the long-named option found. - * It is only valid when a long-named option has been found by the most - * recent call. - * - * Return the option character from OPTS just read. Return -1 when there are - * no more options. For unrecognized options, or options missing arguments, - * `custom_optopt' is set to the option letter, and '?' is returned. - * - * The OPTS string is a list of characters which are recognized option letters, - * optionally followed by colons, specifying that that letter takes an - * argument, to be placed in `custom_optarg'. - * - * If a letter in OPTS is followed by two colons, its argument is optional. - * This behavior is specific to the GNU `getopt'. - * - * The argument `--' causes premature termination of argument scanning, - * explicitly telling `getopt' that there are no more options. If OPTS begins - * with `--', then non-option arguments are treated as arguments to the option - * '\0'. This behavior is specific to the GNU `getopt'. - */ - -static int getopt_internal_r(int argc, char *const *argv, const char *optstring, - const struct option *longopts, int *longind, - struct custom_getopt_data *d) -{ - int ret, print_errors = d->custom_opterr; - - if (optstring[0] == ':') - print_errors = 0; - if (argc < 1) - return -1; - d->custom_optarg = NULL; - - /* - * This is a big difference with GNU getopt, since optind == 0 - * means initialization while here 1 means first call. - */ - if (d->custom_optind == 0 || !d->initialized) { - if (d->custom_optind == 0) - d->custom_optind = 1; /* Don't scan ARGV[0], the program name. */ - custom_getopt_initialize(d); - } - if (d->nextchar == NULL || *d->nextchar == '\0') { - ret = shuffle_argv(argc, argv, longopts, d); - if (ret) - return ret; - } - if (longopts && (argv[d->custom_optind][1] == '-' )) - return check_long_opt(argc, argv, optstring, longopts, - longind, print_errors, d); - return check_short_opt(argc, argv, optstring, print_errors, d); -} - -static int custom_getopt_internal(int argc, char *const *argv, const char *optstring, - const struct option *longopts, int *longind) -{ - int result; - /* Keep a global copy of all internal members of d */ - static struct custom_getopt_data d; - - d.custom_optind = custom_optind; - d.custom_opterr = custom_opterr; - result = getopt_internal_r(argc, argv, optstring, longopts, - longind, &d); - custom_optind = d.custom_optind; - custom_optarg = d.custom_optarg; - custom_optopt = d.custom_optopt; - return result; -} - -static int custom_getopt_long (int argc, char *const *argv, const char *options, - const struct option *long_options, int *opt_index) -{ - return custom_getopt_internal(argc, argv, options, long_options, - opt_index); -} - - -static char *package_name = 0; - -/** - * @brief updates an option - * @param field the generic pointer to the field to update - * @param orig_field the pointer to the orig field - * @param field_given the pointer to the number of occurrence of this option - * @param prev_given the pointer to the number of occurrence already seen - * @param value the argument for this option (if null no arg was specified) - * @param possible_values the possible values for this option (if specified) - * @param default_value the default value (in case the option only accepts fixed values) - * @param arg_type the type of this option - * @param check_ambiguity @see cmdline_parser_params.check_ambiguity - * @param override @see cmdline_parser_params.override - * @param no_free whether to free a possible previous value - * @param multiple_option whether this is a multiple option - * @param long_opt the corresponding long option - * @param short_opt the corresponding short option (or '-' if none) - * @param additional_error possible further error specification - */ -static -int update_arg(void *field, char **orig_field, - unsigned int *field_given, unsigned int *prev_given, - char *value, const char *possible_values[], - const char *default_value, - cmdline_parser_arg_type arg_type, - int check_ambiguity, int override, - int no_free, int multiple_option, - const char *long_opt, char short_opt, - const char *additional_error) -{ - FIX_UNUSED (field); - char *stop_char = 0; - const char *val = value; - int found; - char **string_field; - - stop_char = 0; - found = 0; - - if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) - { - if (short_opt != '-') - fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", - package_name, long_opt, short_opt, - (additional_error ? additional_error : "")); - else - fprintf (stderr, "%s: `--%s' option given more than once%s\n", - package_name, long_opt, - (additional_error ? additional_error : "")); - return 1; /* failure */ - } - - FIX_UNUSED (default_value); - - if (field_given && *field_given && ! override) - return 0; - if (prev_given) - (*prev_given)++; - if (field_given) - (*field_given)++; - if (possible_values) - val = possible_values[found]; - - switch(arg_type) { - case ARG_STRING: - if (val) { - string_field = (char **)field; - if (!no_free && *string_field) - free (*string_field); /* free previous string */ - *string_field = gengetopt_strdup (val); - } - break; - default: - break; - }; - - - /* store the original value */ - switch(arg_type) { - case ARG_NO: - break; - default: - if (value && orig_field) { - if (no_free) { - *orig_field = value; - } else { - if (*orig_field) - free (*orig_field); /* free previous string */ - *orig_field = gengetopt_strdup (value); - } - } - }; - - return 0; /* OK */ -} - - -int -cmdline_parser_internal ( - int argc, char * const *argv, struct gengetopt_args_info *args_info, - struct cmdline_parser_params *params, const char *additional_error) -{ - int c; /* Character of the parsed option. */ - - int error = 0; - struct gengetopt_args_info local_args_info; - - int override; - int initialize; - int check_required; - int check_ambiguity; - - char *optarg; - int optind; - int opterr; - int optopt; - - package_name = argv[0]; - - override = params->override; - initialize = params->initialize; - check_required = params->check_required; - check_ambiguity = params->check_ambiguity; - - if (initialize) - cmdline_parser_init (args_info); - - cmdline_parser_init (&local_args_info); - - optarg = 0; - optind = 0; - opterr = params->print_errors; - optopt = '?'; - - while (1) - { - int option_index = 0; - - static struct option long_options[] = { - { "help", 0, NULL, 'h' }, - { "version", 0, NULL, 'V' }, - { "extract", 1, NULL, 'x' }, - { "long", 0, NULL, 'l' }, - { 0, 0, 0, 0 } - }; - - custom_optarg = optarg; - custom_optind = optind; - custom_opterr = opterr; - custom_optopt = optopt; - - c = custom_getopt_long (argc, argv, "hVx:l", long_options, &option_index); - - optarg = custom_optarg; - optind = custom_optind; - opterr = custom_opterr; - optopt = custom_optopt; - - if (c == -1) break; /* Exit from `while (1)' loop. */ - - switch (c) - { - case 'h': /* Print help and exit. */ - cmdline_parser_print_help (); - cmdline_parser_free (&local_args_info); - exit (EXIT_SUCCESS); - - case 'V': /* Print version and exit. */ - cmdline_parser_print_version (); - cmdline_parser_free (&local_args_info); - exit (EXIT_SUCCESS); - - case 'x': /* Extract file from archive. */ - - - if (update_arg( (void *)&(args_info->extract_arg), - &(args_info->extract_orig), &(args_info->extract_given), - &(local_args_info.extract_given), optarg, 0, 0, ARG_STRING, - check_ambiguity, override, 0, 0, - "extract", 'x', - additional_error)) - goto failure; - - break; - case 'l': /* Include extra information in archive listing. */ - - - if (update_arg( 0 , - 0 , &(args_info->long_given), - &(local_args_info.long_given), optarg, 0, 0, ARG_NO, - check_ambiguity, override, 0, 0, - "long", 'l', - additional_error)) - goto failure; - - break; - - case 0: /* Long option with no short option */ - case '?': /* Invalid option. */ - /* `getopt_long' already printed an error message. */ - goto failure; - - default: /* bug: option not considered. */ - fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); - abort (); - } /* switch */ - } /* while */ - - - - - cmdline_parser_release (&local_args_info); - - if ( error ) - return (EXIT_FAILURE); - - if (optind < argc) - { - int i = 0 ; - int found_prog_name = 0; - /* whether program name, i.e., argv[0], is in the remaining args - (this may happen with some implementations of getopt, - but surely not with the one included by gengetopt) */ - - - args_info->inputs_num = argc - optind - found_prog_name; - args_info->inputs = - (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ; - while (optind < argc) - args_info->inputs[ i++ ] = gengetopt_strdup (argv[optind++]) ; - } - - return 0; - -failure: - - cmdline_parser_release (&local_args_info); - return (EXIT_FAILURE); -} diff --git a/apps/bsatool/bsatool_cmd.h b/apps/bsatool/bsatool_cmd.h deleted file mode 100644 index 4d5f80ea2..000000000 --- a/apps/bsatool/bsatool_cmd.h +++ /dev/null @@ -1,179 +0,0 @@ -/** @file bsatool_cmd.h - * @brief The header file for the command line option parser - * generated by GNU Gengetopt version 2.22.2 - * http://www.gnu.org/software/gengetopt. - * DO NOT modify this file, since it can be overwritten - * @author GNU Gengetopt by Lorenzo Bettini */ - -#ifndef BSATOOL_CMD_H -#define BSATOOL_CMD_H - -/* If we use autoconf. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include /* for FILE */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifndef CMDLINE_PARSER_PACKAGE -/** @brief the program name (used for printing errors) */ -#define CMDLINE_PARSER_PACKAGE "bsatool" -#endif - -#ifndef CMDLINE_PARSER_PACKAGE_NAME -/** @brief the complete program name (used for help and version) */ -#define CMDLINE_PARSER_PACKAGE_NAME "bsatool" -#endif - -#ifndef CMDLINE_PARSER_VERSION -/** @brief the program version */ -#define CMDLINE_PARSER_VERSION "1.0" -#endif - -/** @brief Where the command line options are stored */ -struct gengetopt_args_info -{ - const char *help_help; /**< @brief Print help and exit help description. */ - const char *version_help; /**< @brief Print version and exit help description. */ - char * extract_arg; /**< @brief Extract file from archive. */ - char * extract_orig; /**< @brief Extract file from archive original value given at command line. */ - const char *extract_help; /**< @brief Extract file from archive help description. */ - const char *long_help; /**< @brief Include extra information in archive listing help description. */ - - unsigned int help_given ; /**< @brief Whether help was given. */ - unsigned int version_given ; /**< @brief Whether version was given. */ - unsigned int extract_given ; /**< @brief Whether extract was given. */ - unsigned int long_given ; /**< @brief Whether long was given. */ - - char **inputs ; /**< @brief unamed options (options without names) */ - unsigned inputs_num ; /**< @brief unamed options number */ -} ; - -/** @brief The additional parameters to pass to parser functions */ -struct cmdline_parser_params -{ - int override; /**< @brief whether to override possibly already present options (default 0) */ - int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ - int check_required; /**< @brief whether to check that all required options were provided (default 1) */ - int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ - int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ -} ; - -/** @brief the purpose string of the program */ -extern const char *gengetopt_args_info_purpose; -/** @brief the usage string of the program */ -extern const char *gengetopt_args_info_usage; -/** @brief all the lines making the help output */ -extern const char *gengetopt_args_info_help[]; - -/** - * The command line parser - * @param argc the number of command line options - * @param argv the command line options - * @param args_info the structure where option information will be stored - * @return 0 if everything went fine, NON 0 if an error took place - */ -int cmdline_parser (int argc, char * const *argv, - struct gengetopt_args_info *args_info); - -/** - * The command line parser (version with additional parameters - deprecated) - * @param argc the number of command line options - * @param argv the command line options - * @param args_info the structure where option information will be stored - * @param override whether to override possibly already present options - * @param initialize whether to initialize the option structure my_args_info - * @param check_required whether to check that all required options were provided - * @return 0 if everything went fine, NON 0 if an error took place - * @deprecated use cmdline_parser_ext() instead - */ -int cmdline_parser2 (int argc, char * const *argv, - struct gengetopt_args_info *args_info, - int override, int initialize, int check_required); - -/** - * The command line parser (version with additional parameters) - * @param argc the number of command line options - * @param argv the command line options - * @param args_info the structure where option information will be stored - * @param params additional parameters for the parser - * @return 0 if everything went fine, NON 0 if an error took place - */ -int cmdline_parser_ext (int argc, char * const *argv, - struct gengetopt_args_info *args_info, - struct cmdline_parser_params *params); - -/** - * Save the contents of the option struct into an already open FILE stream. - * @param outfile the stream where to dump options - * @param args_info the option struct to dump - * @return 0 if everything went fine, NON 0 if an error took place - */ -int cmdline_parser_dump(FILE *outfile, - struct gengetopt_args_info *args_info); - -/** - * Save the contents of the option struct into a (text) file. - * This file can be read by the config file parser (if generated by gengetopt) - * @param filename the file where to save - * @param args_info the option struct to save - * @return 0 if everything went fine, NON 0 if an error took place - */ -int cmdline_parser_file_save(const char *filename, - struct gengetopt_args_info *args_info); - -/** - * Print the help - */ -void cmdline_parser_print_help(void); -/** - * Print the version - */ -void cmdline_parser_print_version(void); - -/** - * Initializes all the fields a cmdline_parser_params structure - * to their default values - * @param params the structure to initialize - */ -void cmdline_parser_params_init(struct cmdline_parser_params *params); - -/** - * Allocates dynamically a cmdline_parser_params structure and initializes - * all its fields to their default values - * @return the created and initialized cmdline_parser_params structure - */ -struct cmdline_parser_params *cmdline_parser_params_create(void); - -/** - * Initializes the passed gengetopt_args_info structure's fields - * (also set default values for options that have a default) - * @param args_info the structure to initialize - */ -void cmdline_parser_init (struct gengetopt_args_info *args_info); -/** - * Deallocates the string fields of the gengetopt_args_info structure - * (but does not deallocate the structure itself) - * @param args_info the structure to deallocate - */ -void cmdline_parser_free (struct gengetopt_args_info *args_info); - -/** - * Checks that all the required options were specified - * @param args_info the structure to check - * @param prog_name the name of the program that will be used to print - * possible errors - * @return - */ -int cmdline_parser_required (struct gengetopt_args_info *args_info, - const char *prog_name); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* BSATOOL_CMD_H */ From d696da767762739af746c255a45c1a8040950225 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 7 Mar 2013 21:38:27 +0100 Subject: [PATCH 149/151] Fix selection buffer --- libs/openengine/ogre/selectionbuffer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/openengine/ogre/selectionbuffer.cpp b/libs/openengine/ogre/selectionbuffer.cpp index c6b43a45d..30e7b9e1e 100644 --- a/libs/openengine/ogre/selectionbuffer.cpp +++ b/libs/openengine/ogre/selectionbuffer.cpp @@ -24,7 +24,8 @@ namespace Render vp->setBackgroundColour(Ogre::ColourValue(0, 0, 0, 0)); vp->setShadowsEnabled(false); vp->setMaterialScheme("selectionbuffer"); - vp->setVisibilityMask (visibilityFlags); + if (visibilityFlags != 0) + vp->setVisibilityMask (visibilityFlags); mRenderTarget->setActive(true); mRenderTarget->setAutoUpdated (false); From 285b4bf726448722a2390260280925600b23c56f Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 8 Mar 2013 00:12:56 +0100 Subject: [PATCH 150/151] Allow zooming camera in vanity or preview mode with the mousewheel --- apps/openmw/mwbase/world.hpp | 1 + apps/openmw/mwinput/inputmanagerimp.cpp | 3 +++ apps/openmw/mwrender/player.cpp | 7 +++++++ apps/openmw/mwrender/player.hpp | 2 ++ apps/openmw/mwrender/renderingmanager.hpp | 5 +++++ apps/openmw/mwworld/worldimp.hpp | 4 ++++ 6 files changed, 22 insertions(+) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 654a59cea..6cd5b90b4 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -296,6 +296,7 @@ namespace MWBase virtual bool toggleVanityMode(bool enable, bool force) = 0; virtual void allowVanityMode(bool allow) = 0; virtual void togglePlayerLooking(bool enable) = 0; + virtual void changeVanityModeScale(float factor) = 0; virtual void renderPlayer() = 0; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 4c10749b3..f18c02a0e 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -548,6 +548,9 @@ namespace MWInput MWBase::World *world = MWBase::Environment::get().getWorld(); world->rotateObject(world->getPlayer().getPlayer(), -y, 0.f, x, true); + + if (arg.state.Z.rel) + MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.state.Z.rel); } return true; diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 1ac3b072f..63396378d 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -271,6 +271,8 @@ namespace MWRender v.z = 800.f; } else if (v.z < 10.f) { v.z = 10.f; + } else if (override && v.z < 50.f) { + v.z = 50.f; } mCamera->setPosition(v); @@ -362,4 +364,9 @@ namespace MWRender mCameraNode->setPosition(0.f, 0.f, mHeight); } } + + bool Player::isVanityOrPreviewModeEnabled() + { + return mPreviewMode || mVanity.enabled; + } } diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index e24f44d68..9de41823d 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -110,6 +110,8 @@ namespace MWRender void getSightAngles(float &pitch, float &yaw); void togglePlayerLooking(bool enable); + + bool isVanityOrPreviewModeEnabled(); }; } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 5cea24175..1777a72c3 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -83,6 +83,11 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList mPlayer->togglePlayerLooking(enable); } + void changeVanityModeScale(float factor) { + if (mPlayer->isVanityOrPreviewModeEnabled()) + mPlayer->setCameraDistance(-factor/120.f*10, true, true); + } + void getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw); void attachCameraTo(const MWWorld::Ptr &ptr); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 47088aa62..fe4ceff69 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -339,6 +339,10 @@ namespace MWWorld mRendering->togglePlayerLooking(enable); } + virtual void changeVanityModeScale(float factor) { + mRendering->changeVanityModeScale(factor); + } + virtual void renderPlayer(); virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); From 40b6b4afc5f7fb69d8db5849905b6eed841b184d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 8 Mar 2013 11:31:52 +0100 Subject: [PATCH 151/151] fix cmake typo that effects windows devs --- cmake/FindFFmpeg.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindFFmpeg.cmake b/cmake/FindFFmpeg.cmake index 4147590d6..a3509597b 100644 --- a/cmake/FindFFmpeg.cmake +++ b/cmake/FindFFmpeg.cmake @@ -99,7 +99,7 @@ endmacro() # Check for cached results. If there are skip the costly part. if (NOT FFMPEG_LIBRARIES) - set (FFMPEGSDK ENV${FFMPEG_HOME}) + set (FFMPEGSDK $ENV{FFMPEG_HOME}) if (FFMPEGSDK) set (FFMPEGSDK_INC "${FFMPEGSDK}/include") set (FFMPEGSDK_LIB "${FFMPEGSDK}/lib")