From 11ebae3be2d3d5750d532e56af511b2717b7c377 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 29 Apr 2012 03:33:10 +0200 Subject: [PATCH 01/76] toggleCompositors command useful for debugging --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwrender/renderingmanager.cpp | 45 ++++++++++++----------- apps/openmw/mwrender/renderingmanager.hpp | 6 +++ apps/openmw/mwrender/water.cpp | 20 ++++------ apps/openmw/mwrender/water.hpp | 4 +- apps/openmw/mwscript/docs/vmformat.txt | 3 +- apps/openmw/mwscript/miscextensions.cpp | 19 ++++++++++ apps/openmw/mwworld/world.hpp | 3 +- 8 files changed, 64 insertions(+), 37 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index fb0e1db69..deb57cfec 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -16,6 +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 shaderhelper + compositors ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a95a179c6..11d3dca6d 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -18,6 +18,7 @@ #include "shaderhelper.hpp" #include "localmap.hpp" #include "water.hpp" +#include "compositors.hpp" using namespace MWRender; using namespace Ogre; @@ -29,6 +30,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const { mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); + mCompositors = new Compositors(mRendering.getViewport()); + mWater = 0; //The fog type must be set before any terrain objects are created as if the @@ -67,15 +70,15 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // note that the order is important here if (useMRT()) { - CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "gbuffer"); - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", true); - CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "Underwater"); - CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "gbufferFinalizer"); - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", true); + mCompositors->addCompositor("gbuffer", 0); + mCompositors->setCompositorEnabled("gbuffer", true); + mCompositors->addCompositor("Underwater", 1); + mCompositors->addCompositor("gbufferFinalizer", 2); + mCompositors->setCompositorEnabled("gbufferFinalizer", true); } else { - CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "UnderwaterNoMRT"); + mCompositors->addCompositor("UnderwaterNoMRT", 0); } // Turn the entire scene (represented by the 'root' node) -90 @@ -120,6 +123,7 @@ RenderingManager::~RenderingManager () delete mTerrainManager; delete mLocalMap; delete mOcclusionQuery; + delete mCompositors; } MWRender::SkyManager* RenderingManager::getSkyManager() @@ -231,7 +235,7 @@ void RenderingManager::update (float duration){ void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){ if(store->cell->data.flags & store->cell->HasWater){ if(mWater == 0) - mWater = new MWRender::Water(mRendering.getCamera(), mSkyManager, store->cell); + mWater = new MWRender::Water(mRendering.getCamera(), this, store->cell); else mWater->changeCell(store->cell); mWater->setActive(true); @@ -292,35 +296,29 @@ void RenderingManager::skySetMoonColour (bool red){ bool RenderingManager::toggleRenderMode(int mode) { - if (mode != MWWorld::World::Render_Wireframe) + if (mode == MWWorld::World::Render_CollisionDebug || mode == MWWorld::World::Render_Pathgrid) return mDebugging->toggleRenderMode(mode); - else // if (mode == MWWorld::World::Render_Wireframe) + else if (mode == MWWorld::World::Render_Wireframe) { if (mRendering.getCamera()->getPolygonMode() == PM_SOLID) { - // disable compositors - if (useMRT()) - { - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", false); - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", false); - } + mCompositors->setEnabled(false); mRendering.getCamera()->setPolygonMode(PM_WIREFRAME); return true; } else { - // re-enable compositors - if (useMRT()) - { - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", true); - CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", true); - } + mCompositors->setEnabled(true); mRendering.getCamera()->setPolygonMode(PM_SOLID); return false; } } + else //if (mode == MWWorld::World::Render_Compositors) + { + return mCompositors->toggle(); + } } void RenderingManager::configureFog(ESMS::CellStore &mCell) @@ -518,4 +516,9 @@ void RenderingManager::switchToExterior() mRendering.getScene()->setCameraRelativeRendering(true); } +Compositors* RenderingManager::getCompositors() +{ + return mCompositors; +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 0d11b3d57..4e3296598 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -47,6 +47,7 @@ namespace MWRender class ShaderHelper; class LocalMap; class Water; + class Compositors; class RenderingManager: private RenderingInterface { @@ -67,6 +68,7 @@ class RenderingManager: private RenderingInterface { /// to internal details of the rendering system anymore SkyManager* getSkyManager(); + Compositors* getCompositors(); void toggleLight(); bool toggleRenderMode(int mode); @@ -157,6 +159,8 @@ class RenderingManager: private RenderingInterface { bool mSunEnabled; + bool mCompositorsEnabled; + SkyManager* mSkyManager; OcclusionQuery* mOcclusionQuery; @@ -192,6 +196,8 @@ class RenderingManager: private RenderingInterface { MWRender::Shadows* mShadows; MWRender::ShaderHelper* mShaderHelper; + + MWRender::Compositors* mCompositors; }; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index c81f23f54..19716f751 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -2,24 +2,20 @@ #include #include "sky.hpp" #include "renderingmanager.hpp" +#include "compositors.hpp" using namespace Ogre; namespace MWRender { -Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) : +Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell) : mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), mReflectionTarget(0), mActive(1), mToggled(1), - mReflectionRenderActive(false) + mReflectionRenderActive(false), mRendering(rend) { - mSky = sky; - - try - { - CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false); - } catch(...) {} + mSky = rend->getSkyManager(); mTop = cell->water; @@ -147,8 +143,6 @@ Water::~Water() mWaterNode->detachObject(mWater); mSceneManager->destroyEntity(mWater); mSceneManager->destroySceneNode(mWaterNode); - - CompositorManager::getSingleton().removeCompositorChain(mViewport); } void Water::changeCell(const ESM::Cell* cell) @@ -178,13 +172,13 @@ void Water::checkUnderwater(float y) { if (!mActive) { - CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false); + mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false); return; } if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID) { - CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false); + mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false); // tell the shader we are not underwater Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0); @@ -199,7 +193,7 @@ void Water::checkUnderwater(float y) if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID) { if (mUnderwaterEffect) - CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, true); + mRendering->getCompositors()->setCompositorEnabled(mCompositorName, true); // tell the shader we are underwater Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index c8b8d311e..25631b4af 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -9,6 +9,7 @@ namespace MWRender { class SkyManager; + class RenderingManager; /// Water rendering class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener @@ -40,6 +41,7 @@ namespace MWRender { void updateVisible(); + RenderingManager* mRendering; SkyManager* mSky; std::string mCompositorName; @@ -55,7 +57,7 @@ namespace MWRender { int mVisibilityFlags; public: - Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell); + Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell); ~Water(); void setActive(bool active); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 58960aac4..11df70bbc 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -144,4 +144,5 @@ op 0x200014d: ModDisposition op 0x200014e: ModDisposition, explicit reference op 0x200014f: ForceGreeting op 0x2000150: ForceGreeting, explicit reference -opcodes 0x2000151-0x3ffffff unused +op 0x2000152: ToggleCompositors +opcodes 0x2000153-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 4ba523937..95129bd76 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -194,6 +194,22 @@ namespace MWScript } }; + class OpToggleCompositors : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + InterpreterContext& context = + static_cast (runtime.getContext()); + + bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode(MWWorld::World::Render_Compositors); + + context.report (enabled ? + "Compositors -> On" : "Compositors -> Off"); + } + }; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -208,6 +224,7 @@ namespace MWScript const int opcodeFadeTo = 0x200013e; const int opcodeToggleWater = 0x2000144; const int opcodeTogglePathgrid = 0x2000146; + const int opcodeToggleCompositors = 0x2000152; void registerExtensions (Compiler::Extensions& extensions) { @@ -229,6 +246,7 @@ namespace MWScript extensions.registerInstruction ("twa", "", opcodeToggleWater); extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); + extensions.registerInstruction ("togglecompositors", "", opcodeToggleCompositors); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -247,6 +265,7 @@ namespace MWScript interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo); interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); + interpreter.installSegment5 (opcodeToggleCompositors, new OpToggleCompositors); } } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 77e5bcef6..583448e12 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -63,7 +63,8 @@ namespace MWWorld { Render_CollisionDebug, Render_Wireframe, - Render_Pathgrid + Render_Pathgrid, + Render_Compositors }; private: From 9cf6f27f9629904cadf07302ef760a7367f31149 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 29 Apr 2012 03:38:00 +0200 Subject: [PATCH 02/76] small fix --- apps/openmw/mwrender/compositors.cpp | 49 +++++++++++++++++++++ apps/openmw/mwrender/compositors.hpp | 53 +++++++++++++++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 2 - 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 apps/openmw/mwrender/compositors.cpp create mode 100644 apps/openmw/mwrender/compositors.hpp diff --git a/apps/openmw/mwrender/compositors.cpp b/apps/openmw/mwrender/compositors.cpp new file mode 100644 index 000000000..4c9f08b72 --- /dev/null +++ b/apps/openmw/mwrender/compositors.cpp @@ -0,0 +1,49 @@ +#include "compositors.hpp" + +#include +#include + +using namespace MWRender; + +Compositors::Compositors(Ogre::Viewport* vp) : + mViewport(vp) + , mEnabled(true) +{ +} + +Compositors::~Compositors() +{ + Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); +} + +void Compositors::setEnabled (const bool enabled) +{ + for (CompositorMap::iterator it=mCompositors.begin(); + it != mCompositors.end(); ++it) + { + Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, it->first, enabled && it->second.first); + } + mEnabled = enabled; +} + +void Compositors::addCompositor (const std::string& name, const int priority) +{ + int id = 0; + + for (CompositorMap::iterator it=mCompositors.begin(); + it != mCompositors.end(); ++it) + { + if (it->second.second > priority) + break; + ++id; + } + Ogre::CompositorManager::getSingleton().addCompositor (mViewport, name, id); + + mCompositors[name] = std::make_pair(false, priority); +} + +void Compositors::setCompositorEnabled (const std::string& name, const bool enabled) +{ + mCompositors[name].first = enabled; + Ogre::CompositorManager::getSingleton().setCompositorEnabled (mViewport, name, enabled && mEnabled); +} diff --git a/apps/openmw/mwrender/compositors.hpp b/apps/openmw/mwrender/compositors.hpp new file mode 100644 index 000000000..50b53f84a --- /dev/null +++ b/apps/openmw/mwrender/compositors.hpp @@ -0,0 +1,53 @@ +#ifndef GAME_MWRENDER_COMPOSITORS_H +#define GAME_MWRENDER_COMPOSITORS_H + +#include +#include + +namespace Ogre +{ + class Viewport; +} + +namespace MWRender +{ + typedef std::map < std::string, std::pair > CompositorMap; + + /// \brief Manages a set of compositors for one viewport + class Compositors + { + public: + Compositors(Ogre::Viewport* vp); + virtual ~Compositors(); + + /** + * enable or disable all compositors globally + */ + void setEnabled (const bool enabled); + + bool toggle() { setEnabled(!mEnabled); return mEnabled; } + + /** + * enable or disable a specific compositor + * @note enable has no effect if all compositors are globally disabled + */ + void setCompositorEnabled (const std::string& name, const bool enabled); + + /** + * @param name of compositor + * @param priority, lower number will be first in the chain + */ + void addCompositor (const std::string& name, const int priority); + + protected: + /// maps compositor name to its "enabled" state + CompositorMap mCompositors; + + bool mEnabled; + + Ogre::Viewport* mViewport; + }; + +} + +#endif diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 4e3296598..09aa1df6d 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -159,8 +159,6 @@ class RenderingManager: private RenderingInterface { bool mSunEnabled; - bool mCompositorsEnabled; - SkyManager* mSkyManager; OcclusionQuery* mOcclusionQuery; From 9e6531a6c6faf077e402ed1955682026cecfc7d8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 30 Apr 2012 21:22:26 +0200 Subject: [PATCH 03/76] fix for dark corners bug on some cards --- apps/openmw/mwrender/shaderhelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/shaderhelper.cpp b/apps/openmw/mwrender/shaderhelper.cpp index 1d29be2b8..59154a295 100644 --- a/apps/openmw/mwrender/shaderhelper.cpp +++ b/apps/openmw/mwrender/shaderhelper.cpp @@ -258,7 +258,7 @@ void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool s outStream << " float3 lightingFinal = lightColour.xyz * diffuse.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n" " float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n" - " oColor.xyz = lerp(lightingFinal * tex.xyz * vertexColour.xyz, fogColour.xyz, fogValue); \n" + " oColor.xyz = saturate(lerp(lightingFinal * tex.xyz * vertexColour.xyz, fogColour.xyz, fogValue)); \n" // saturate output to prevent negative output colors - TODO: replace this once there is HDR-rendering " oColor.a = tex.a * diffuse.a * vertexColour.a; \n"; if (mrt) outStream << From 02dad448fe54cd99f3e672ba3ccfd94f35c37651 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 3 May 2012 05:38:43 +0200 Subject: [PATCH 04/76] make the wireframe mode not affect sky --- apps/openmw/mwrender/sky.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index da2e7446a..72f88c6c5 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -113,6 +113,7 @@ void BillboardObject::init(const String& textureName, p->setSelfIllumination(1.0,1.0,1.0); p->setDiffuse(0.0,0.0,0.0,1.0); p->setAmbient(0.0,0.0,0.0); + p->setPolygonModeOverrideable(false); p->createTextureUnitState(textureName); mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount)); @@ -520,6 +521,7 @@ void SkyManager::create() mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName()); mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); + mp->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); mStarsMaterials[i] = mp; } @@ -535,6 +537,7 @@ void SkyManager::create() mAtmosphereDay = mRootNode->createChildSceneNode(); mAtmosphereDay->attachObject(atmosphere_ent); mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); // Atmosphere shader HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, @@ -598,6 +601,7 @@ void SkyManager::create() SceneNode* clouds_node = mRootNode->createChildSceneNode(); clouds_node->attachObject(clouds_ent); mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); + mCloudMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); clouds_ent->setCastShadows(false); // Clouds vertex shader From a54e52586b5d3a213ad8a1fa25de05eb3a3a64c5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 12:17:07 +0200 Subject: [PATCH 05/76] fix for a potential directx problem --- files/shadows/depthshadowcaster.material | 92 +++++++++++++----------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/files/shadows/depthshadowcaster.material b/files/shadows/depthshadowcaster.material index 9ff51c5b1..f645cad01 100644 --- a/files/shadows/depthshadowcaster.material +++ b/files/shadows/depthshadowcaster.material @@ -1,67 +1,73 @@ vertex_program depth_shadow_caster_vs cg { - source depthshadowcaster.cg - profiles vs_1_1 arbvp1 - entry_point main_vp + source depthshadowcaster.cg + profiles vs_1_1 arbvp1 + entry_point main_vp - default_params - { - param_named_auto wvpMat worldviewproj_matrix - } + default_params + { + param_named_auto wvpMat worldviewproj_matrix + } } fragment_program depth_shadow_caster_ps cg { - source depthshadowcaster.cg - profiles ps_2_0 arbfp1 - entry_point main_fp + source depthshadowcaster.cg + profiles ps_2_0 arbfp1 + entry_point main_fp - default_params - { - } + default_params + { + } } fragment_program depth_shadow_caster_ps_noalpha cg { - source depthshadowcaster.cg - profiles ps_2_0 arbfp1 - entry_point main_fp_noalpha + source depthshadowcaster.cg + profiles ps_2_0 arbfp1 + entry_point main_fp_noalpha - default_params - { - } + default_params + { + } } material depth_shadow_caster { - technique - { - pass - { - vertex_program_ref depth_shadow_caster_vs - { - } + technique + { + pass + { + // force-disable fog (relevant for DirectX profiles below SM3 that always apply fixed function fog) + fog_override true - fragment_program_ref depth_shadow_caster_ps - { - } - } - } + vertex_program_ref depth_shadow_caster_vs + { + } + + fragment_program_ref depth_shadow_caster_ps + { + } + } + } } material depth_shadow_caster_noalpha { - technique - { - pass - { - vertex_program_ref depth_shadow_caster_vs - { - } + technique + { + pass + { + // force-disable fog (relevant for DirectX profiles below SM3 that always apply fixed function fog) + fog_override true - fragment_program_ref depth_shadow_caster_ps_noalpha - { - } - } - } + vertex_program_ref depth_shadow_caster_vs + { + } + + fragment_program_ref depth_shadow_caster_ps_noalpha + { + } + } + } } From ddb0a9199408c68fbf9c378b80e8f1fae6246004 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 13 May 2012 12:19:49 +0200 Subject: [PATCH 06/76] addition to last commit --- components/nifogre/ogre_nif_loader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 05d35b85f..80b2fc469 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -326,6 +326,8 @@ void NIFLoader::createMaterial(const String &name, { material->getTechnique(0)->getPass(0)->setVertexProgram("main_vp"); material->getTechnique(0)->getPass(0)->setFragmentProgram("main_fp"); + + material->getTechnique(0)->getPass(0)->setFog(true); // force-disable fixed function fog, it is calculated in shader } // Create a fallback technique without shadows and without mrt @@ -338,6 +340,7 @@ void NIFLoader::createMaterial(const String &name, { pass2->setVertexProgram("main_fallback_vp"); pass2->setFragmentProgram("main_fallback_fp"); + pass2->setFog(true); // force-disable fixed function fog, it is calculated in shader } // Add material bells and whistles From 5f6e8224f44ef47e69f71fd363532a1733755c5b Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 10:48:25 +0200 Subject: [PATCH 07/76] skill progress --- apps/openmw/mwgui/stats_window.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 1dd82cf6a..cdf6a5871 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -376,6 +376,7 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const MWMechanics::Stat &stat = skillValues.find(skillId)->second; float base = stat.getBase(); float modified = stat.getModified(); + int progressPercent = (modified - float(static_cast(modified))) * 100; const ESM::Skill* skill = mWindowManager.getStore().skills.search(skillId); assert(skill); @@ -401,8 +402,9 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillDescription", skill->description); skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillAttribute", "#{sGoverningAttribute}: #{" + attr->name + "}"); skillWidgets[skillWidgets.size()-1-i]->setUserString("ImageTexture_SkillImage", icon); - skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillProgressText", "0/100"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillProgressText", boost::lexical_cast(progressPercent)+"/100"); skillWidgets[skillWidgets.size()-1-i]->setUserString("Range_SkillProgress", "100"); + skillWidgets[skillWidgets.size()-1-i]->setUserString("RangePosition_SkillProgress", boost::lexical_cast(progressPercent)); } skillWidgetMap[skillId] = widget; From 157dd81524cd83c820d640f25e6439aa16bbec7c Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 10:57:49 +0200 Subject: [PATCH 08/76] removed script instruction, will be in the settings window later --- apps/openmw/mwscript/docs/vmformat.txt | 1 - apps/openmw/mwscript/miscextensions.cpp | 18 ------------------ 2 files changed, 19 deletions(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 06e9a0ca7..de7248c0c 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -146,5 +146,4 @@ op 0x200014f: ForceGreeting op 0x2000150: ForceGreeting, explicit reference op 0x2000151: ToggleFullHelp op 0x2000152: Goodbye -op 0x2000153: ToggleCompositors opcodes 0x2000154-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 1467b0aeb..fe1a642fd 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -194,22 +194,6 @@ namespace MWScript } }; - class OpToggleCompositors : public Interpreter::Opcode0 - { - public: - - virtual void execute (Interpreter::Runtime& runtime) - { - InterpreterContext& context = - static_cast (runtime.getContext()); - - bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode(MWWorld::World::Render_Compositors); - - context.report (enabled ? - "Compositors -> On" : "Compositors -> Off"); - } - }; - const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -224,7 +208,6 @@ namespace MWScript const int opcodeFadeTo = 0x200013e; const int opcodeToggleWater = 0x2000144; const int opcodeTogglePathgrid = 0x2000146; - const int opcodeToggleCompositors = 0x2000153; void registerExtensions (Compiler::Extensions& extensions) { @@ -246,7 +229,6 @@ namespace MWScript extensions.registerInstruction ("twa", "", opcodeToggleWater); extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); - extensions.registerInstruction ("togglecompositors", "", opcodeToggleCompositors); } void installOpcodes (Interpreter::Interpreter& interpreter) From bda90b77bcbd89c7348b88af504315892755a211 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 21 May 2012 10:59:06 +0200 Subject: [PATCH 09/76] oops, forgot something --- apps/openmw/mwscript/miscextensions.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index fe1a642fd..4ba523937 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -247,7 +247,6 @@ namespace MWScript interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo); interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); - interpreter.installSegment5 (opcodeToggleCompositors, new OpToggleCompositors); } } } From 3673cd2531743e8ece156644c842eec9af46a5c9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 May 2012 12:41:15 +0200 Subject: [PATCH 10/76] increased version number --- CMakeLists.txt | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 668fcd83a..e11ad0c0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include (OpenMWMacros) # Version set (OPENMW_VERSION_MAJOR 0) -set (OPENMW_VERSION_MINOR 14) +set (OPENMW_VERSION_MINOR 15) set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") diff --git a/readme.txt b/readme.txt index 53f4a4c59..08e937010 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -Version: 0.14.0 +Version: 0.15.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org From 7aad0cc069daa098edb63461b7937d57b7d45a0f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 May 2012 12:44:57 +0200 Subject: [PATCH 11/76] updated readme file --- readme.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/readme.txt b/readme.txt index 08e937010..a8a312e62 100644 --- a/readme.txt +++ b/readme.txt @@ -132,6 +132,31 @@ Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Fil CHANGELOG +0.15.0 + +Bug #5: Physics reimplementation (fixes various issues) +Bug #258: Resizing arrow's background is not transparent +Bug #268: Widening the stats window in X direction causes layout problems +Bug #269: Topic pane in dialgoue window is too small for some longer topics +Bug #271: Dialog choices are sorted incorrectly +Bug #281: The single quote character is not rendered on dialog windows +Bug #285: Terrain not handled properly in cells that are not predefined +Bug #289: Dialogue filter isn't doing case smashing/folding for item IDs +Feature #15: Collision with Terrain +Feature #17: Inventory-, Container- and Trade-Windows +Feature #44: Floating Labels above Focussed Objects +Feature #80: Tooltips +Feature #90: Book and Scroll Windows +Feature #156: Item Stacking in Containers +Feature #213: Pulsating lights +Feature #218: Feather & Burden +Feature #256: Implement magic effect bookkeeping +Feature #259: Add missing information to Stats window +Feature #260: Correct case for dialogue topics +Feature #280: GUI texture atlasing +Feature #291: Ability to use GMST strings from GUI layout files +Task #255: Make MWWorld::Environment into a singleton + 0.14.0 Bug #1: Meshes rendered with wrong orientation From b494533bb2c343fca3083fce34482ecd83f16631 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 May 2012 12:54:23 +0200 Subject: [PATCH 12/76] another change to the readme file --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index a8a312e62..513474dd6 100644 --- a/readme.txt +++ b/readme.txt @@ -146,6 +146,7 @@ Feature #15: Collision with Terrain Feature #17: Inventory-, Container- and Trade-Windows Feature #44: Floating Labels above Focussed Objects Feature #80: Tooltips +Feature #83: Barter Dialogue Feature #90: Book and Scroll Windows Feature #156: Item Stacking in Containers Feature #213: Pulsating lights From 343bbaf0fd9a5cce41d8a027b22f65b6e5567f3e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 03:36:03 +0200 Subject: [PATCH 13/76] integrated video settings in the settings file, the launcher is now useless --- apps/openmw/engine.cpp | 34 ++-- components/files/configurationmanager.cpp | 7 - components/files/configurationmanager.hpp | 2 - files/settings-default.cfg | 23 +++ libs/openengine/ogre/renderer.cpp | 129 ++++++------ libs/openengine/ogre/renderer.hpp | 233 +++++++++++----------- 6 files changed, 216 insertions(+), 212 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 85b0557b1..a180849ff 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -268,15 +268,6 @@ void OMW::Engine::go() mOgre = new OEngine::Render::OgreRenderer; - //we need to ensure the path to the configuration exists before creating an - //instance of ogre root so that Ogre doesn't raise an exception when trying to - //access it - const boost::filesystem::path configPath = mCfgMgr.getOgreConfigPath().parent_path(); - if ( !boost::filesystem::exists(configPath) ) - { - boost::filesystem::create_directories(configPath); - } - // Create the settings manager and load default settings file Settings::Manager settings; const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg"; @@ -308,10 +299,20 @@ void OMW::Engine::go() else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg")) nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"); - mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()), - mCfgMgr.getOgreConfigPath().string(), + std::string renderSystem = settings.getString("render system", "Video"); + if (renderSystem == "") + { +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + renderSystem = "Direct3D9 Rendering Subsystem"; +#else + renderSystem = "OpenGL Rendering Subsystem"; +#endif + } + mOgre->configure( mCfgMgr.getLogPath().string(), - mCfgMgr.getPluginsConfigPath().string(), false); + mCfgMgr.getPluginsConfigPath().string(), + renderSystem, + false); // This has to be added BEFORE MyGUI is initialized, as it needs // to find core.xml here. @@ -325,7 +326,14 @@ void OMW::Engine::go() addZipResource(mResDir / "mygui" / "Obliviontt.zip"); // Create the window - mOgre->createWindow("OpenMW"); + OEngine::Render::WindowSettings windowSettings; + windowSettings.fullscreen = settings.getBool("fullscreen", "Video"); + windowSettings.window_x = settings.getInt("resolution x", "Video"); + windowSettings.window_y = settings.getInt("resolution y", "Video"); + windowSettings.vsync = settings.getBool("vsync", "Video"); + std::string aa = settings.getString("antialiasing", "Video"); + windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0"; + mOgre->createWindow("OpenMW", windowSettings); loadBSA(); diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index d5f322ebd..150a4fcd8 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -15,7 +15,6 @@ namespace Files { static const char* const openmwCfgFile = "openmw.cfg"; -static const char* const ogreCfgFile = "ogre.cfg"; static const char* const pluginsCfgFile = "plugins.cfg"; const char* const mwToken = "?mw?"; @@ -39,7 +38,6 @@ ConfigurationManager::ConfigurationManager() } } - mOgreCfgPath = mFixedPath.getUserPath() / ogreCfgFile; mLogPath = mFixedPath.getUserPath(); } @@ -164,11 +162,6 @@ const boost::filesystem::path& ConfigurationManager::getInstallPath() const return mFixedPath.getInstallPath(); } -const boost::filesystem::path& ConfigurationManager::getOgreConfigPath() const -{ - return mOgreCfgPath; -} - const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const { return mPluginsCfgPath; diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index 7fb3793c6..af9d02b91 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -41,7 +41,6 @@ struct ConfigurationManager const boost::filesystem::path& getLocalDataPath() const; const boost::filesystem::path& getInstallPath() const; - const boost::filesystem::path& getOgreConfigPath() const; const boost::filesystem::path& getPluginsConfigPath() const; const boost::filesystem::path& getLogPath() const; @@ -59,7 +58,6 @@ struct ConfigurationManager FixedPathType mFixedPath; - boost::filesystem::path mOgreCfgPath; boost::filesystem::path mPluginsCfgPath; boost::filesystem::path mLogPath; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index e4a0c020a..81df50fb6 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -1,6 +1,29 @@ # WARNING: Editing this file might have no effect, as these # settings are overwritten by your user settings file. +[Video] +resolution x = 800 +resolution y = 600 + +fullscreen = false + +# Render system +# blank means default +# Valid values: +# OpenGL Rendering Subsystem +# Direct3D9 Rendering Subsystem +render system = + +# Valid values: +# none +# MSAA 2 +# MSAA 4 +# MSAA 8 +# MSAA 16 +antialiasing = none + +vsync = false + [General] # Camera field of view field of view = 55 diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 4ded3343f..4c8a10c3f 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -13,17 +13,17 @@ using namespace OEngine::Render; void OgreRenderer::cleanup() { - if (mFader) - delete mFader; - - if(mRoot) - delete mRoot; - mRoot = NULL; + if (mFader) + delete mFader; + + if(mRoot) + delete mRoot; + mRoot = NULL; } void OgreRenderer::start() { - mRoot->startRendering(); + mRoot->startRendering(); } bool OgreRenderer::loadPlugins() @@ -53,96 +53,79 @@ bool OgreRenderer::loadPlugins() void OgreRenderer::update(float dt) { - mFader->update(dt); + mFader->update(dt); } void OgreRenderer::screenshot(const std::string &file) { - mWindow->writeContentsToFile(file); + mWindow->writeContentsToFile(file); } float OgreRenderer::getFPS() { - return mWindow->getLastFPS(); + return mWindow->getLastFPS(); } -bool OgreRenderer::configure(bool showConfig, - const std::string &cfgPath, - const std::string &logPath, - const std::string &pluginCfg, - bool _logging) +void OgreRenderer::configure(const std::string &logPath, + const std::string &pluginCfg, + const std::string& renderSystem, + bool _logging) { - // Set up logging first - new LogManager; - Log *log = LogManager::getSingleton().createLog(logPath + std::string("Ogre.log")); - logging = _logging; + // Set up logging first + new LogManager; + Log *log = LogManager::getSingleton().createLog(logPath + std::string("Ogre.log")); + logging = _logging; - if(logging) - // Full log detail - log->setLogDetail(LL_BOREME); - else - // Disable logging - log->setDebugOutputEnabled(false); + if(logging) + // Full log detail + log->setLogDetail(LL_BOREME); + else + // Disable logging + log->setDebugOutputEnabled(false); -#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX) - mRoot = new Root("", cfgPath, ""); - loadPlugins(); -#else - mRoot = new Root(pluginCfg, cfgPath, ""); -#endif + #if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX) + mRoot = new Root("", "", ""); + loadPlugins(); + #else + mRoot = new Root(pluginCfg, "", ""); + #endif - // Show the configuration dialog and initialise the system, if the - // showConfig parameter is specified. The settings are stored in - // ogre.cfg. If showConfig is false, the settings are assumed to - // already exist in ogre.cfg. - int result; - if(showConfig) - result = mRoot->showConfigDialog(); - else - result = mRoot->restoreConfig(); - - return !result; + RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem); + if (rs == 0) + throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded"); + mRoot->setRenderSystem(rs); } -bool OgreRenderer::configure(bool showConfig, - const std::string &cfgPath, - const std::string &pluginCfg, - bool _logging) +void OgreRenderer::createWindow(const std::string &title, const WindowSettings& settings) { - return configure(showConfig, cfgPath, cfgPath, pluginCfg, _logging); -} + assert(mRoot); + mRoot->initialise(false); -bool OgreRenderer::configure(bool showConfig, - const std::string &pluginCfg, - bool _logging) -{ - return configure(showConfig, "", pluginCfg, _logging); -} + 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")); -void OgreRenderer::createWindow(const std::string &title) -{ - assert(mRoot); - // Initialize OGRE window - mWindow = mRoot->initialise(true, title, ""); + mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms); } void OgreRenderer::createScene(const std::string camName, float fov, float nearClip) { - assert(mRoot); - assert(mWindow); - // Get the SceneManager, in this case a generic one - mScene = mRoot->createSceneManager(ST_GENERIC); + assert(mRoot); + assert(mWindow); + // Get the SceneManager, in this case a generic one + mScene = mRoot->createSceneManager(ST_GENERIC); - // Create the camera - mCamera = mScene->createCamera(camName); - mCamera->setNearClipDistance(nearClip); - mCamera->setFOVy(Degree(fov)); + // Create the camera + mCamera = mScene->createCamera(camName); + mCamera->setNearClipDistance(nearClip); + mCamera->setFOVy(Degree(fov)); - // Create one viewport, entire window - mView = mWindow->addViewport(mCamera); + // Create one viewport, entire window + mView = mWindow->addViewport(mCamera); - // Alter the camera aspect ratio to match the viewport - mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); - - mFader = new Fader(); + // Alter the camera aspect ratio to match the viewport + mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); + + mFader = new Fader(); } diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 179515aa9..7dc539e27 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -33,124 +33,123 @@ namespace Ogre class Viewport; } -namespace OEngine { -namespace Render +namespace OEngine { - class Fader; - class OgreRenderer - { - Ogre::Root *mRoot; - Ogre::RenderWindow *mWindow; - Ogre::SceneManager *mScene; - Ogre::Camera *mCamera; - Ogre::Viewport *mView; -#ifdef ENABLE_PLUGIN_CgProgramManager - Ogre::CgPlugin* mCgPlugin; -#endif -#ifdef ENABLE_PLUGIN_OctreeSceneManager - Ogre::OctreePlugin* mOctreePlugin; -#endif -#ifdef ENABLE_PLUGIN_ParticleFX - Ogre::ParticleFXPlugin* mParticleFXPlugin; -#endif -#ifdef ENABLE_PLUGIN_GL - Ogre::GLPlugin* mGLPlugin; -#endif -#ifdef ENABLE_PLUGIN_Direct3D9 - Ogre::D3D9Plugin* mD3D9Plugin; -#endif - Fader* mFader; - bool logging; - - public: - OgreRenderer() - : mRoot(NULL) - , mWindow(NULL) - , mScene(NULL) - , mCamera(NULL) - , mView(NULL) -#ifdef ENABLE_PLUGIN_CgProgramManager - , mCgPlugin(NULL) -#endif -#ifdef ENABLE_PLUGIN_OctreeSceneManager - , mOctreePlugin(NULL) -#endif -#ifdef ENABLE_PLUGIN_ParticleFX - , mParticleFXPlugin(NULL) -#endif -#ifdef ENABLE_PLUGIN_GL - , mGLPlugin(NULL) -#endif -#ifdef ENABLE_PLUGIN_Direct3D9 - , mD3D9Plugin(NULL) -#endif - , mFader(NULL) - , logging(false) + namespace Render { + struct WindowSettings + { + bool vsync; + bool fullscreen; + int window_x, window_y; + std::string fsaa; + }; + + class Fader; + class OgreRenderer + { + Ogre::Root *mRoot; + Ogre::RenderWindow *mWindow; + Ogre::SceneManager *mScene; + Ogre::Camera *mCamera; + Ogre::Viewport *mView; + #ifdef ENABLE_PLUGIN_CgProgramManager + Ogre::CgPlugin* mCgPlugin; + #endif + #ifdef ENABLE_PLUGIN_OctreeSceneManager + Ogre::OctreePlugin* mOctreePlugin; + #endif + #ifdef ENABLE_PLUGIN_ParticleFX + Ogre::ParticleFXPlugin* mParticleFXPlugin; + #endif + #ifdef ENABLE_PLUGIN_GL + Ogre::GLPlugin* mGLPlugin; + #endif + #ifdef ENABLE_PLUGIN_Direct3D9 + Ogre::D3D9Plugin* mD3D9Plugin; + #endif + Fader* mFader; + bool logging; + + public: + OgreRenderer() + : mRoot(NULL) + , mWindow(NULL) + , mScene(NULL) + , mCamera(NULL) + , mView(NULL) + #ifdef ENABLE_PLUGIN_CgProgramManager + , mCgPlugin(NULL) + #endif + #ifdef ENABLE_PLUGIN_OctreeSceneManager + , mOctreePlugin(NULL) + #endif + #ifdef ENABLE_PLUGIN_ParticleFX + , mParticleFXPlugin(NULL) + #endif + #ifdef ENABLE_PLUGIN_GL + , mGLPlugin(NULL) + #endif + #ifdef ENABLE_PLUGIN_Direct3D9 + , mD3D9Plugin(NULL) + #endif + , mFader(NULL) + , logging(false) + { + } + + ~OgreRenderer() { cleanup(); } + + /** Configure the renderer. This will load configuration files and + set up the Root and logging classes. */ + void configure( + const std::string &logPath, // Path to directory where to store log files + const std::string &pluginCfg, // plugin.cfg file + const std::string &renderSystem, + bool _logging); // Enable or disable logging + + /// Create a window with the given title + void createWindow(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 + float nearClip=5 // Near clip distance + ); + + /// Kill the renderer. + void cleanup(); + + /// Start the main rendering loop + void start(); + + bool loadPlugins(); + + void update(float dt); + + /// Write a screenshot to file + void screenshot(const std::string &file); + + float getFPS(); + + /// Get the Root + Ogre::Root *getRoot() { return mRoot; } + + /// Get the rendering window + Ogre::RenderWindow *getWindow() { return mWindow; } + + /// Get the scene manager + Ogre::SceneManager *getScene() { return mScene; } + + /// Get the screen colour fader + Fader *getFader() { return mFader; } + + /// Camera + Ogre::Camera *getCamera() { return mCamera; } + + /// Viewport + Ogre::Viewport *getViewport() { return mView; } + }; } - - ~OgreRenderer() { cleanup(); } - - /** Configure the renderer. This will load configuration files and - set up the Root and logging classes. */ - bool configure(bool showConfig, // Show config dialog box? - const std::string &cfgPath, // Path to directory where to store config files - const std::string &logPath, // Path to directory where to store log files - const std::string &pluginCfg, // plugin.cfg file - bool _logging); // Enable or disable logging - - bool configure(bool showConfig, // Show config dialog box? - const std::string &cfgPath, // Path to directory where to store config files - const std::string &pluginCfg, // plugin.cfg file - bool _logging); // Enable or disable logging - - /** Configure the renderer. This will load configuration files and - set up the Root and logging classes. */ - bool configure(bool showConfig, // Show config dialog box? - const std::string &pluginCfg, // plugin.cfg file - bool _logging); // Enable or disable logging - - /// Create a window with the given title - void createWindow(const std::string &title); - - /// Set up the scene manager, camera and viewport - void createScene(const std::string camName="Camera",// Camera name - float fov=55, // Field of view angle - float nearClip=5 // Near clip distance - ); - - /// Kill the renderer. - void cleanup(); - - /// Start the main rendering loop - void start(); - - bool loadPlugins(); - - void update(float dt); - - /// Write a screenshot to file - void screenshot(const std::string &file); - - float getFPS(); - - /// Get the Root - Ogre::Root *getRoot() { return mRoot; } - - /// Get the rendering window - Ogre::RenderWindow *getWindow() { return mWindow; } - - /// Get the scene manager - Ogre::SceneManager *getScene() { return mScene; } - - /// Get the screen colour fader - Fader *getFader() { return mFader; } - - /// Camera - Ogre::Camera *getCamera() { return mCamera; } - - /// Viewport - Ogre::Viewport *getViewport() { return mView; } - }; -}} +} #endif From 355268dae11d77556571f97452e8a4bdcb55f16e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 19:36:50 +0200 Subject: [PATCH 14/76] make the launcher build and run again, but it doesn't change settings --- apps/launcher/graphicspage.cpp | 35 ++++++---------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 95b38d53e..8a26ec444 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -150,9 +150,6 @@ void GraphicsPage::createPages() void GraphicsPage::setupConfig() { - QString ogreCfg = mCfgMgr.getOgreConfigPath().string().c_str(); - QFile file(ogreCfg); - mOgreConfig = new QSettings(ogreCfg, QSettings::IniFormat); } void GraphicsPage::setupOgre() @@ -164,32 +161,12 @@ void GraphicsPage::setupOgre() Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager; logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false); - QString ogreCfg = QString::fromStdString(mCfgMgr.getOgreConfigPath().string()); - file.setFileName(ogreCfg); - - //we need to check that the path to the configuration file exists before we - //try and create an instance of Ogre::Root otherwise Ogre raises an exception - QDir configDir = QFileInfo(file).dir(); - if ( !configDir.exists() && !configDir.mkpath(configDir.path()) ) - { - QMessageBox msgBox; - msgBox.setWindowTitle("Error creating config file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QString(tr("
Failed to create the configuration file

\ - Make sure you have write access to
%1

")).arg(configDir.path())); - msgBox.exec(); - - qApp->exit(1); - return; - } - try { #if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) - mOgre = new Ogre::Root("", file.fileName().toStdString(), "./launcherOgre.log"); + mOgre = new Ogre::Root("", "", "./launcherOgre.log"); #else - mOgre = new Ogre::Root(pluginCfg.toStdString(), file.fileName().toStdString(), "./launcherOgre.log"); + mOgre = new Ogre::Root(pluginCfg.toStdString(), "", "./launcherOgre.log"); #endif } catch(Ogre::Exception &ex) @@ -227,13 +204,13 @@ void GraphicsPage::setupOgre() mSelectedRenderSystem = *r; mRendererComboBox->addItem((*r)->getName().c_str()); } - +/* int index = mRendererComboBox->findText(mOgreConfig->value("Render System").toString()); if ( index != -1) { mRendererComboBox->setCurrentIndex(index); } - +*/ // Create separate rendersystems QString openGLName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("OpenGL"), Qt::MatchStartsWith)); QString direct3DName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("Direct3D"), Qt::MatchStartsWith)); @@ -460,11 +437,11 @@ void GraphicsPage::writeConfig() QString GraphicsPage::getConfigValue(const QString &key, Ogre::RenderSystem *renderer) { QString result; - +/* mOgreConfig->beginGroup(renderer->getName().c_str()); result = mOgreConfig->value(key).toString(); mOgreConfig->endGroup(); - +*/ return result; } From ad46049ee078bc9fde6ef92eaf45fd366e8e60dd Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 20:37:18 +0200 Subject: [PATCH 15/76] got the launcher working with the new settings system. --- apps/launcher/graphicspage.cpp | 375 ++++++--------------------------- apps/launcher/graphicspage.hpp | 26 +-- apps/launcher/maindialog.cpp | 27 +++ apps/launcher/maindialog.hpp | 2 + 4 files changed, 102 insertions(+), 328 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 8a26ec444..2cd8006ae 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -1,7 +1,11 @@ +#include "graphicspage.hpp" + #include -#include "graphicspage.hpp" +#include + #include +#include GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) : QWidget(parent) @@ -17,12 +21,9 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) renderSystemLayout->addWidget(rendererLabel, 0, 0, 1, 1); renderSystemLayout->addWidget(mRendererComboBox, 0, 1, 1, 1); - mRendererStackedWidget = new QStackedWidget(rendererGroup); - QVBoxLayout *rendererGroupLayout = new QVBoxLayout(rendererGroup); rendererGroupLayout->addLayout(renderSystemLayout); - rendererGroupLayout->addWidget(mRendererStackedWidget); // Display QGroupBox *displayGroup = new QGroupBox(tr("Display"), this); @@ -52,100 +53,29 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) void GraphicsPage::createPages() { - // OpenGL rendering settings - QWidget *mOGLRendererPage = new QWidget(); + QWidget *main = new QWidget(); + QGridLayout *grid = new QGridLayout(main); - QLabel *OGLRTTLabel = new QLabel(tr("Preferred RTT Mode:"), mOGLRendererPage); - mOGLRTTComboBox = new QComboBox(mOGLRendererPage); + mVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), main); + grid->addWidget(mVSyncCheckBox, 0, 0, 1, 1); - QLabel *OGLAntiAliasingLabel = new QLabel(tr("Antialiasing:"), mOGLRendererPage); - mOGLAntiAliasingComboBox = new QComboBox(mOGLRendererPage); + mFullScreenCheckBox = new QCheckBox(tr("Full Screen"), main); + grid->addWidget(mFullScreenCheckBox, 1, 0, 1, 1); + + QLabel *antiAliasingLabel = new QLabel(tr("Antialiasing:"), main); + mAntiAliasingComboBox = new QComboBox(main); + grid->addWidget(antiAliasingLabel, 2, 0, 1, 1); + grid->addWidget(mAntiAliasingComboBox, 2, 1, 1, 1); + + QLabel *resolutionLabel = new QLabel(tr("Resolution:"), main); + mResolutionComboBox = new QComboBox(main); + grid->addWidget(resolutionLabel, 3, 0, 1, 1); + grid->addWidget(mResolutionComboBox, 3, 1, 1, 1); - QGridLayout *OGLRendererLayout = new QGridLayout(mOGLRendererPage); QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding); + grid->addItem(vSpacer1, 4, 0, 1, 1); - OGLRendererLayout->addWidget(OGLRTTLabel, 0, 0, 1, 1); - OGLRendererLayout->addWidget(mOGLRTTComboBox, 0, 1, 1, 1); - OGLRendererLayout->addWidget(OGLAntiAliasingLabel, 1, 0, 1, 1); - OGLRendererLayout->addWidget(mOGLAntiAliasingComboBox, 1, 1, 1, 1); - OGLRendererLayout->addItem(vSpacer1, 2, 1, 1, 1); - - // OpenGL display settings - QWidget *mOGLDisplayPage = new QWidget(); - - QLabel *OGLResolutionLabel = new QLabel(tr("Resolution:"), mOGLDisplayPage); - mOGLResolutionComboBox = new QComboBox(mOGLDisplayPage); - - QLabel *OGLFrequencyLabel = new QLabel(tr("Display Frequency:"), mOGLDisplayPage); - mOGLFrequencyComboBox = new QComboBox(mOGLDisplayPage); - - mOGLVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), mOGLDisplayPage); - mOGLFullScreenCheckBox = new QCheckBox(tr("Full Screen"), mOGLDisplayPage); - - QGridLayout *OGLDisplayLayout = new QGridLayout(mOGLDisplayPage); - QSpacerItem *vSpacer2 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum); - - OGLDisplayLayout->addWidget(OGLResolutionLabel, 0, 0, 1, 1); - OGLDisplayLayout->addWidget(mOGLResolutionComboBox, 0, 1, 1, 1); - OGLDisplayLayout->addWidget(OGLFrequencyLabel, 1, 0, 1, 1); - OGLDisplayLayout->addWidget(mOGLFrequencyComboBox, 1, 1, 1, 1); - - OGLDisplayLayout->addItem(vSpacer2, 2, 1, 1, 1); - OGLDisplayLayout->addWidget(mOGLVSyncCheckBox, 3, 0, 1, 1); - OGLDisplayLayout->addWidget(mOGLFullScreenCheckBox, 6, 0, 1, 1); - - // Direct3D rendering settings - QWidget *mD3DRendererPage = new QWidget(); - - QLabel *D3DRenderDeviceLabel = new QLabel(tr("Rendering Device:"), mD3DRendererPage); - mD3DRenderDeviceComboBox = new QComboBox(mD3DRendererPage); - - QLabel *D3DAntiAliasingLabel = new QLabel(tr("Antialiasing:"), mD3DRendererPage); - mD3DAntiAliasingComboBox = new QComboBox(mD3DRendererPage); - - QLabel *D3DFloatingPointLabel = new QLabel(tr("Floating-point Mode:"), mD3DRendererPage); - mD3DFloatingPointComboBox = new QComboBox(mD3DRendererPage); - - mD3DNvPerfCheckBox = new QCheckBox(tr("Allow NVPerfHUD"), mD3DRendererPage); - - QGridLayout *D3DRendererLayout = new QGridLayout(mD3DRendererPage); - QSpacerItem *vSpacer3 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum); - QSpacerItem *vSpacer4 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding); - - D3DRendererLayout->addWidget(D3DRenderDeviceLabel, 0, 0, 1, 1); - D3DRendererLayout->addWidget(mD3DRenderDeviceComboBox, 0, 1, 1, 1); - D3DRendererLayout->addWidget(D3DAntiAliasingLabel, 1, 0, 1, 1); - D3DRendererLayout->addWidget(mD3DAntiAliasingComboBox, 1, 1, 1, 1); - D3DRendererLayout->addWidget(D3DFloatingPointLabel, 2, 0, 1, 1); - D3DRendererLayout->addWidget(mD3DFloatingPointComboBox, 2, 1, 1, 1); - D3DRendererLayout->addItem(vSpacer3, 3, 1, 1, 1); - D3DRendererLayout->addWidget(mD3DNvPerfCheckBox, 4, 0, 1, 1); - D3DRendererLayout->addItem(vSpacer4, 5, 1, 1, 1); - - // Direct3D display settings - QWidget *mD3DDisplayPage = new QWidget(); - - QLabel *D3DResolutionLabel = new QLabel(tr("Resolution:"), mD3DDisplayPage); - mD3DResolutionComboBox = new QComboBox(mD3DDisplayPage); - - mD3DVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), mD3DDisplayPage); - mD3DFullScreenCheckBox = new QCheckBox(tr("Full Screen"), mD3DDisplayPage); - - QGridLayout *mD3DDisplayLayout = new QGridLayout(mD3DDisplayPage); - QSpacerItem *vSpacer5 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum); - - mD3DDisplayLayout->addWidget(D3DResolutionLabel, 0, 0, 1, 1); - mD3DDisplayLayout->addWidget(mD3DResolutionComboBox, 0, 1, 1, 1); - mD3DDisplayLayout->addItem(vSpacer5, 1, 1, 1, 1); - mD3DDisplayLayout->addWidget(mD3DVSyncCheckBox, 2, 0, 1, 1); - mD3DDisplayLayout->addWidget(mD3DFullScreenCheckBox, 5, 0, 1, 1); - - // Add the created pages - mRendererStackedWidget->addWidget(mOGLRendererPage); - mRendererStackedWidget->addWidget(mD3DRendererPage); - - mDisplayStackedWidget->addWidget(mOGLDisplayPage); - mDisplayStackedWidget->addWidget(mD3DDisplayPage); + mDisplayStackedWidget->addWidget(main); } void GraphicsPage::setupConfig() @@ -204,13 +134,21 @@ void GraphicsPage::setupOgre() mSelectedRenderSystem = *r; mRendererComboBox->addItem((*r)->getName().c_str()); } -/* - int index = mRendererComboBox->findText(mOgreConfig->value("Render System").toString()); + + int index = mRendererComboBox->findText(QString::fromStdString(Settings::Manager::getString("render system", "Video"))); if ( index != -1) { mRendererComboBox->setCurrentIndex(index); } -*/ + else + { +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + mRendererComboBox->setCurrentIndex(mRendererComboBox->findText("Direct3D9 Rendering Subsystem")); +#else + mRendererComboBox->setCurrentIndex(mRendererComboBox->findText("OpenGL Rendering Subsystem")); +#endif + } + // Create separate rendersystems QString openGLName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("OpenGL"), Qt::MatchStartsWith)); QString direct3DName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("Direct3D"), Qt::MatchStartsWith)); @@ -232,217 +170,44 @@ void GraphicsPage::setupOgre() } // Now fill the GUI elements - // OpenGL - if (mOpenGLRenderSystem) { - mOGLRTTComboBox->addItems(getAvailableOptions(QString("RTT Preferred Mode"), mOpenGLRenderSystem)); - mOGLAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mOpenGLRenderSystem)); - mOGLResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mOpenGLRenderSystem)); - mOGLFrequencyComboBox->addItems(getAvailableOptions(QString("Display Frequency"), mOpenGLRenderSystem)); - } - - // Direct3D - if (mDirect3DRenderSystem) { - mD3DRenderDeviceComboBox->addItems(getAvailableOptions(QString("Rendering Device"), mDirect3DRenderSystem)); - mD3DAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mDirect3DRenderSystem)); - mD3DFloatingPointComboBox->addItems(getAvailableOptions(QString("Floating-point mode"), mDirect3DRenderSystem)); - mD3DResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mDirect3DRenderSystem)); - } + mAntiAliasingComboBox->clear(); + mResolutionComboBox->clear(); + mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); + mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem)); } void GraphicsPage::readConfig() { - // Read the config file settings - if (mOpenGLRenderSystem) { + if (Settings::Manager::getBool("vsync", "Video")) + mVSyncCheckBox->setCheckState(Qt::Checked); - int index = mOGLRTTComboBox->findText(getConfigValue("RTT Preferred Mode", mOpenGLRenderSystem)); - if ( index != -1) { - mOGLRTTComboBox->setCurrentIndex(index); - } + if (Settings::Manager::getBool("fullscreen", "Video")) + mFullScreenCheckBox->setCheckState(Qt::Checked); - index = mOGLAntiAliasingComboBox->findText(getConfigValue("FSAA", mOpenGLRenderSystem)); - if ( index != -1){ - mOGLAntiAliasingComboBox->setCurrentIndex(index); - } + int aaIndex = mAntiAliasingComboBox->findText(QString::fromStdString(Settings::Manager::getString("antialiasing", "Video"))); + if (aaIndex != -1) + mAntiAliasingComboBox->setCurrentIndex(aaIndex); - index = mOGLResolutionComboBox->findText(getConfigValue("Video Mode", mOpenGLRenderSystem)); - if ( index != -1) { - mOGLResolutionComboBox->setCurrentIndex(index); - } - - index = mOGLFrequencyComboBox->findText(getConfigValue("Display Frequency", mOpenGLRenderSystem)); - if ( index != -1) { - mOGLFrequencyComboBox->setCurrentIndex(index); - } - - // Now we do the same for the checkboxes - if (getConfigValue("VSync", mOpenGLRenderSystem) == QLatin1String("Yes")) { - mOGLVSyncCheckBox->setCheckState(Qt::Checked); - } - - if (getConfigValue("Full Screen", mOpenGLRenderSystem) == QLatin1String("Yes")) { - mOGLFullScreenCheckBox->setCheckState(Qt::Checked); - } - } - - if (mDirect3DRenderSystem) { - - int index = mD3DRenderDeviceComboBox->findText(getConfigValue("Rendering Device", mDirect3DRenderSystem)); - if ( index != -1) { - mD3DRenderDeviceComboBox->setCurrentIndex(index); - } - - index = mD3DAntiAliasingComboBox->findText(getConfigValue("FSAA", mDirect3DRenderSystem)); - if ( index != -1) { - mD3DAntiAliasingComboBox->setCurrentIndex(index); - } - - index = mD3DFloatingPointComboBox->findText(getConfigValue("Floating-point mode", mDirect3DRenderSystem)); - if ( index != -1) { - mD3DFloatingPointComboBox->setCurrentIndex(index); - } - - index = mD3DResolutionComboBox->findText(getConfigValue("Video Mode", mDirect3DRenderSystem)); - if ( index != -1) { - mD3DResolutionComboBox->setCurrentIndex(index); - } - - if (getConfigValue("Allow NVPerfHUD", mDirect3DRenderSystem) == QLatin1String("Yes")) { - mD3DNvPerfCheckBox->setCheckState(Qt::Checked); - } - - if (getConfigValue("VSync", mDirect3DRenderSystem) == QLatin1String("Yes")) { - mD3DVSyncCheckBox->setCheckState(Qt::Checked); - } - - if (getConfigValue("Full Screen", mDirect3DRenderSystem) == QLatin1String("Yes")) { - mD3DFullScreenCheckBox->setCheckState(Qt::Checked); - } - } + std::string resolution = boost::lexical_cast(Settings::Manager::getInt("resolution x", "Video")) + + " x " + boost::lexical_cast(Settings::Manager::getInt("resolution y", "Video")); + int resIndex = mResolutionComboBox->findText(QString::fromStdString(resolution)); + if (resIndex != -1) + mResolutionComboBox->setCurrentIndex(resIndex); } void GraphicsPage::writeConfig() { - mOgre->setRenderSystem(mSelectedRenderSystem); + Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState()); + Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState()); + Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString()); - if (mDirect3DRenderSystem) { - // Nvidia Performance HUD - if (mD3DNvPerfCheckBox->checkState() == Qt::Checked) { - mDirect3DRenderSystem->setConfigOption("Allow NVPerfHUD", "Yes"); - } else { - mDirect3DRenderSystem->setConfigOption("Allow NVPerfHUD", "No"); - } - - // Antialiasing - mDirect3DRenderSystem->setConfigOption("FSAA", mD3DAntiAliasingComboBox->currentText().toStdString()); - - // Full screen - if (mD3DFullScreenCheckBox->checkState() == Qt::Checked) { - mDirect3DRenderSystem->setConfigOption("Full Screen", "Yes"); - } else { - mDirect3DRenderSystem->setConfigOption("Full Screen", "No"); - } - - // Rendering device - mDirect3DRenderSystem->setConfigOption("Rendering Device", mD3DRenderDeviceComboBox->currentText().toStdString()); - - // VSync - if (mD3DVSyncCheckBox->checkState() == Qt::Checked) { - mDirect3DRenderSystem->setConfigOption("VSync", "Yes"); - } else { - mDirect3DRenderSystem->setConfigOption("VSync", "No"); - } - - // Resolution - mDirect3DRenderSystem->setConfigOption("Video Mode", mD3DResolutionComboBox->currentText().toStdString()); - } - - if (mOpenGLRenderSystem) { - // Display Frequency - mOpenGLRenderSystem->setConfigOption("Display Frequency", mOGLFrequencyComboBox->currentText().toStdString()); - - // Antialiasing - mOpenGLRenderSystem->setConfigOption("FSAA", mOGLAntiAliasingComboBox->currentText().toStdString()); - - // Full screen - if (mOGLFullScreenCheckBox->checkState() == Qt::Checked) { - mOpenGLRenderSystem->setConfigOption("Full Screen", "Yes"); - } else { - mOpenGLRenderSystem->setConfigOption("Full Screen", "No"); - } - - // RTT mode - mOpenGLRenderSystem->setConfigOption("RTT Preferred Mode", mOGLRTTComboBox->currentText().toStdString()); - - // VSync - if (mOGLVSyncCheckBox->checkState() == Qt::Checked) { - mOpenGLRenderSystem->setConfigOption("VSync", "Yes"); - } else { - mOpenGLRenderSystem->setConfigOption("VSync", "No"); - } - - // Resolution - mOpenGLRenderSystem->setConfigOption("Video Mode", mOGLResolutionComboBox->currentText().toStdString()); - } - - // Now we validate the options - QString ogreError = QString::fromStdString(mSelectedRenderSystem->validateConfigOptions()); - - if (!ogreError.isEmpty()) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error validating Ogre configuration"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
A problem occured while validating the graphics options

\ - The graphics options could not be saved.

\ - Press \"Show Details...\" for more information.
")); - msgBox.setDetailedText(ogreError); - msgBox.exec(); - - Ogre::LogManager::getSingletonPtr()->logMessage( "Caught exception in validateConfigOptions"); - - qCritical("Error validating configuration"); - - qApp->exit(1); - return; - } - - // Write the settings to the config file - - - try - { - mOgre->saveConfig(); - } - catch(Ogre::Exception &ex) - { - QString ogreError = QString::fromStdString(ex.getFullDescription().c_str()); - QMessageBox msgBox; - msgBox.setWindowTitle("Error writing Ogre configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not write the graphics configuration

\ - Please make sure you have the right permissions and try again.

\ - Press \"Show Details...\" for more information.
")); - msgBox.setDetailedText(ogreError); - msgBox.exec(); - - qCritical("Error saving Ogre configuration, the error reported was:\n %s", qPrintable(ogreError)); - - qApp->exit(1); - return; - } - -} - -QString GraphicsPage::getConfigValue(const QString &key, Ogre::RenderSystem *renderer) -{ - QString result; -/* - mOgreConfig->beginGroup(renderer->getName().c_str()); - result = mOgreConfig->value(key).toString(); - mOgreConfig->endGroup(); -*/ - return result; + std::string resolution = mResolutionComboBox->currentText().toStdString(); + // parse resolution x and y from a string like "800 x 600" + size_t xPos = resolution.find("x"); + int resX = boost::lexical_cast(resolution.substr(0, xPos-1)); + int resY = boost::lexical_cast(resolution.substr(xPos+2, resolution.size()-(xPos+2))); + Settings::Manager::setInt("resolution x", "Video", resX); + Settings::Manager::setInt("resolution y", "Video", resY); } QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer) @@ -461,7 +226,9 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy { if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) - result << QString::fromStdString((*opt_it).c_str()).simplified(); + { + result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified(); + } } } @@ -471,15 +238,11 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy void GraphicsPage::rendererChanged(const QString &renderer) { - if (renderer.contains("Direct3D")) { - mRendererStackedWidget->setCurrentIndex(1); - mDisplayStackedWidget->setCurrentIndex(1); - } - - if (renderer.contains("OpenGL")) { - mRendererStackedWidget->setCurrentIndex(0); - mDisplayStackedWidget->setCurrentIndex(0); - } - mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString()); + + mAntiAliasingComboBox->clear(); + mResolutionComboBox->clear(); + + mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); + mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem)); } diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 6a91a0628..1b0c6f388 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -49,33 +49,15 @@ private: QComboBox *mRendererComboBox; - QStackedWidget *mRendererStackedWidget; QStackedWidget *mDisplayStackedWidget; - // OpenGL - QComboBox *mOGLRTTComboBox; - QComboBox *mOGLAntiAliasingComboBox; - QComboBox *mOGLResolutionComboBox; - QComboBox *mOGLFrequencyComboBox; - - QCheckBox *mOGLVSyncCheckBox; - QCheckBox *mOGLFullScreenCheckBox; - - // Direct3D - QComboBox *mD3DRenderDeviceComboBox; - QComboBox *mD3DAntiAliasingComboBox; - QComboBox *mD3DFloatingPointComboBox; - QComboBox *mD3DResolutionComboBox; - - QCheckBox *mD3DNvPerfCheckBox; - QCheckBox *mD3DVSyncCheckBox; - QCheckBox *mD3DFullScreenCheckBox; - - QSettings *mOgreConfig; + QComboBox *mAntiAliasingComboBox; + QComboBox *mResolutionComboBox; + QCheckBox *mVSyncCheckBox; + QCheckBox *mFullScreenCheckBox; Files::ConfigurationManager &mCfgMgr; - QString getConfigValue(const QString &key, Ogre::RenderSystem *renderer); QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); void createPages(); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 8bb618dd6..d404fed8e 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -7,6 +7,28 @@ MainDialog::MainDialog() { + // Create the settings manager and load default settings file + const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg"; + const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/settings-default.cfg"; + + // prefer local + if (boost::filesystem::exists(localdefault)) + mSettings.loadDefault(localdefault); + else if (boost::filesystem::exists(globaldefault)) + mSettings.loadDefault(globaldefault); + else + throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed."); + + // load user settings if they exist, otherwise just load the default settings as user settings + const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg"; + 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); + + mIconWidget = new QListWidget; mIconWidget->setObjectName("IconWidget"); mIconWidget->setViewMode(QListView::IconMode); @@ -178,6 +200,11 @@ void MainDialog::closeEvent(QCloseEvent *event) // Now write all config files mDataFilesPage->writeConfig(); mGraphicsPage->writeConfig(); + + // Save user settings + const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg"; + mSettings.saveUser(settingspath); + event->accept(); } diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index d6d0e9974..0065aa8c4 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -4,6 +4,7 @@ #include #include +#include class QListWidget; class QListWidgetItem; @@ -41,6 +42,7 @@ private: DataFilesPage *mDataFilesPage; Files::ConfigurationManager mCfgMgr; + Settings::Manager mSettings; }; #endif From b25d62a7e2ad30cf41ee9f19110ebcfb4f328334 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 20:52:38 +0200 Subject: [PATCH 16/76] rename antialiasing mode "MSAA 0" to "none" to avoid confusion. --- apps/launcher/graphicspage.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 2cd8006ae..e156e4fbc 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -222,14 +222,17 @@ 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++) - { + 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(); - } - } + if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) + { + if (key == "FSAA" && *opt_it == "0") + result << QString("none"); + else + result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified(); + } + } } From 313294c52297753aed1c168d61b553dc7d5615ef Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 21:40:42 +0200 Subject: [PATCH 17/76] settings window (hotkey F2) which does nothing. Yay! --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/mode.hpp | 1 + apps/openmw/mwgui/settingswindow.cpp | 25 ++++++++++++++++++ apps/openmw/mwgui/settingswindow.hpp | 26 +++++++++++++++++++ apps/openmw/mwgui/window_manager.cpp | 9 ++++++- apps/openmw/mwgui/window_manager.hpp | 2 ++ apps/openmw/mwinput/inputmanager.cpp | 15 +++++++++++ files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_settings_window_layout.xml | 14 ++++++++++ 9 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 apps/openmw/mwgui/settingswindow.cpp create mode 100644 apps/openmw/mwgui/settingswindow.hpp create mode 100644 files/mygui/openmw_settings_window_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c08c91c02..fd2fdf575 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -27,7 +27,7 @@ add_openmw_dir (mwgui text_input widgets race class birth review window_manager console dialogue dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list - formatting itemwidget inventorywindow container hud countdialog tradewindow + formatting itemwidget inventorywindow container hud countdialog tradewindow settingswindow ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 775fe4a03..ad54ed1df 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -6,6 +6,7 @@ namespace MWGui enum GuiMode { GM_Game, // Game mode, only HUD + GM_Settings, // Settings window GM_Inventory, // Inventory mode GM_Container, GM_MainMenu, // Main menu mode diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp new file mode 100644 index 000000000..3641a63a4 --- /dev/null +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -0,0 +1,25 @@ +#include "settingswindow.hpp" + +#include "window_manager.hpp" + +namespace MWGui +{ + SettingsWindow::SettingsWindow(WindowManager& parWindowManager) : + WindowBase("openmw_settings_window_layout.xml", parWindowManager) + { + getWidget(mOkButton, "OkButton"); + + mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); + + center(); + + int okSize = mOkButton->getTextSize().width + 24; + mOkButton->setCoord(mMainWidget->getWidth()-16-okSize, mOkButton->getTop(), + okSize, mOkButton->getHeight()); + } + + void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) + { + mWindowManager.setGuiMode(GM_Game); + } +} diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp new file mode 100644 index 000000000..e37c00f7e --- /dev/null +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -0,0 +1,26 @@ +#ifndef MWGUI_SETTINGS_H +#define MWGUI_SETTINGS_H + +#include "window_base.hpp" + +namespace MWGui +{ + class WindowManager; +} + +namespace MWGui +{ + class SettingsWindow : public WindowBase + { + public: + SettingsWindow(WindowManager& parWindowManager); + + protected: + MyGUI::Button* mOkButton; + + void onOkButtonClicked(MyGUI::Widget* _sender); + }; +} + +#endif + diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 2cacf2346..4bb34cf24 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -16,6 +16,7 @@ #include "mainmenu.hpp" #include "countdialog.hpp" #include "tradewindow.hpp" +#include "settingswindow.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -45,11 +46,12 @@ WindowManager::WindowManager( , mMessageBoxManager(NULL) , console(NULL) , mJournal(NULL) - , mDialogueWindow(nullptr) + , mDialogueWindow(NULL) , mBookWindow(NULL) , mScrollWindow(NULL) , mCountDialog(NULL) , mTradeWindow(NULL) + , mSettingsWindow(NULL) , mCharGen(NULL) , playerClass() , playerName() @@ -118,6 +120,7 @@ WindowManager::WindowManager( mScrollWindow = new ScrollWindow(*this); mBookWindow = new BookWindow(*this); mCountDialog = new CountDialog(*this); + mSettingsWindow = new SettingsWindow(*this); // The HUD is always on hud->setVisible(true); @@ -217,6 +220,7 @@ void WindowManager::updateVisible() mScrollWindow->setVisible(false); mBookWindow->setVisible(false); mTradeWindow->setVisible(false); + mSettingsWindow->setVisible(false); // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); @@ -233,6 +237,9 @@ void WindowManager::updateVisible() case GM_MainMenu: menu->setVisible(true); break; + case GM_Settings: + mSettingsWindow->setVisible(true); + break; case GM_Console: console->enable(); break; diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 22fe973a5..aab307035 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -77,6 +77,7 @@ namespace MWGui class MessageBoxManager; class CountDialog; class TradeWindow; + class SettingsWindow; struct ClassPoint { @@ -230,6 +231,7 @@ namespace MWGui BookWindow* mBookWindow; CountDialog* mCountDialog; TradeWindow* mTradeWindow; + SettingsWindow* mSettingsWindow; CharacterCreation* mCharGen; diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 8f8f1e1ee..8fd6a9c6b 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -71,6 +71,8 @@ namespace MWInput A_ToggleFps, // Toggle FPS display (this is temporary) + A_Settings, // Temporary hotkey + A_LAST // Marker for the last item }; @@ -140,6 +142,16 @@ namespace MWInput windows.messageBox ("Screenshot saved", empty); } + void showSettings() + { + if (mDragDrop) + return; + + MWGui::GuiMode mode = windows.getMode(); + if (mode != MWGui::GM_Settings) + setGuiMode(MWGui::GM_Settings); + } + /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ void toggleInventory() { @@ -261,6 +273,8 @@ namespace MWInput "Ready hands"); disp->funcs.bind(A_ToggleFps, boost::bind(&InputImpl::toggleFps, this), "Toggle FPS display"); + disp->funcs.bind(A_Settings, boost::bind(&InputImpl::showSettings, this), + "Show settings window"); // Add the exit listener ogre.getRoot()->addFrameListener(&exit); @@ -308,6 +322,7 @@ namespace MWInput disp->bind(A_ToggleWeapon,KC_F); disp->bind(A_ToggleSpell,KC_R); disp->bind(A_ToggleFps, KC_F10); + disp->bind(A_Settings, KC_F2); // Key bindings for polled keys // NOTE: These keys are constantly being polled. Only add keys that must be checked each frame. diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index cacfb7c5a..9f43f2d89 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -57,6 +57,7 @@ configure_file("${SDIR}/openmw_scroll_skin.xml" "${DDIR}/openmw_scroll_skin.xml" configure_file("${SDIR}/openmw_book_layout.xml" "${DDIR}/openmw_book_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_count_window_layout.xml" "${DDIR}/openmw_count_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_window_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_settings_window_layout.xml" "${DDIR}/openmw_settings_window_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml new file mode 100644 index 000000000..eaf9191bc --- /dev/null +++ b/files/mygui/openmw_settings_window_layout.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + From 972c035e97dc0aac9b714685628f3910b5ddc546 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 22 May 2012 23:35:05 +0200 Subject: [PATCH 18/76] TabControl skin, settings window categories --- files/mygui/openmw_resources.xml | 15 +++++++++++++++ files/mygui/openmw_settings_window_layout.xml | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index 4c509ae13..b47de005d 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -113,6 +113,8 @@ + + @@ -124,4 +126,17 @@ + + + + + + + + + + + + + diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index eaf9191bc..387a8587e 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -3,7 +3,21 @@ - + + + + + + + + + + + + + + + From 656a8f1be9fd3cf181de8140ba343778851e49c3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 23 May 2012 01:32:36 +0200 Subject: [PATCH 19/76] working menu transparency slider --- apps/openmw/mwgui/settingswindow.cpp | 38 ++++++++++++++++ apps/openmw/mwgui/settingswindow.hpp | 4 ++ apps/openmw/mwrender/renderingmanager.cpp | 24 ++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 6 +++ apps/openmw/mwworld/world.cpp | 5 ++ apps/openmw/mwworld/world.hpp | 3 ++ files/mygui/CMakeLists.txt | 1 - files/mygui/openmw_list.skin.xml | 23 ++++++++++ files/mygui/openmw_resources.xml | 2 +- files/mygui/openmw_settings_window_layout.xml | 43 ++++++++++++++++-- files/mygui/transparent.png | Bin 150 -> 0 bytes files/settings-default.cfg | 4 ++ libs/openengine/ogre/renderer.cpp | 15 ++++++ libs/openengine/ogre/renderer.hpp | 4 ++ 14 files changed, 166 insertions(+), 6 deletions(-) delete mode 100644 files/mygui/transparent.png diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 3641a63a4..af909ea8c 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -1,5 +1,13 @@ #include "settingswindow.hpp" +#include +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" + #include "window_manager.hpp" namespace MWGui @@ -8,18 +16,48 @@ namespace MWGui WindowBase("openmw_settings_window_layout.xml", parWindowManager) { getWidget(mOkButton, "OkButton"); + getWidget(mResolutionList, "ResolutionList"); + getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); + getWidget(mViewDistanceSlider, "ViewDistanceSlider"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); + mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); center(); int okSize = mOkButton->getTextSize().width + 24; mOkButton->setCoord(mMainWidget->getWidth()-16-okSize, mOkButton->getTop(), okSize, mOkButton->getHeight()); + + // fill resolution list + Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); + const Ogre::StringVector& videoModes = rs->getConfigOptions()["Video Mode"].possibleValues; + for (Ogre::StringVector::const_iterator it=videoModes.begin(); + it!=videoModes.end(); ++it) + { + mResolutionList->addItem(*it); + } + + // read settings + int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI"); + mMenuTransparencySlider->setScrollPosition(menu_transparency); + onSliderChangePosition(mMenuTransparencySlider, menu_transparency); } void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) { mWindowManager.setGuiMode(GM_Game); } + + void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) + { + float val = pos / float(scroller->getScrollRange()-1); + if (scroller == mMenuTransparencySlider) + { + Settings::Manager::setFloat("menu transparency", "GUI", val); + } + + MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); + } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index e37c00f7e..597f8dec1 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -17,8 +17,12 @@ namespace MWGui protected: MyGUI::Button* mOkButton; + MyGUI::ListBox* mResolutionList; + MyGUI::ScrollBar* mMenuTransparencySlider; + MyGUI::ScrollBar* mViewDistanceSlider; void onOkButtonClicked(MyGUI::Widget* _sender); + void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 6d0b1b21c..86c1f752c 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -114,6 +114,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mDebugging = new Debugging(mMwRoot, engine); mLocalMap = new MWRender::LocalMap(&mRendering, this); + + setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } RenderingManager::~RenderingManager () @@ -563,4 +565,26 @@ Compositors* RenderingManager::getCompositors() return mCompositors; } +void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) +{ + for (Settings::CategorySettingVector::const_iterator it=settings.begin(); + it != settings.end(); ++it) + { + if (it->second == "menu transparency" && it->first == "GUI") + { + setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); + } + } +} + +void RenderingManager::setMenuTransparency(float val) +{ + Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName("transparent.png"); + std::vector buffer; + buffer.resize(1); + buffer[0] = (int(255*val) << 24); + memcpy(tex->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], 1*4); + tex->getBuffer()->unlock(); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 5ef43a2e2..edee193f3 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -13,6 +13,8 @@ #include #include +#include + #include #include @@ -157,10 +159,14 @@ class RenderingManager: private RenderingInterface { ///< transform the specified bounding box (in world coordinates) into screen coordinates. /// @return packed vector4 (min_x, min_y, max_x, max_y) + void processChangedSettings(const Settings::CategorySettingVector& settings); + private: void setAmbientMode(); + void setMenuTransparency(float val); + bool mSunEnabled; SkyManager* mSkyManager; diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index c0107d9af..772dc71cb 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -1024,4 +1024,9 @@ namespace MWWorld mWorldScene->insertObject(object, cell); } + + void World::processChangedSettings(const Settings::CategorySettingVector& settings) + { + mRendering->processChangedSettings(settings); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 1b0ad7fd8..e8391773b 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -7,6 +7,7 @@ #include #include +#include #include "../mwrender/debugging.hpp" #include "../mwrender/renderingmanager.hpp" @@ -279,6 +280,8 @@ namespace MWWorld bool canPlaceObject(float cursorX, float cursorY); ///< @return true if it is possible to place on object at specified cursor location + + void processChangedSettings(const Settings::CategorySettingVector& settings); }; } diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 9f43f2d89..90a0c1fce 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -60,7 +60,6 @@ configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_wi configure_file("${SDIR}/openmw_settings_window_layout.xml" "${DDIR}/openmw_settings_window_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) -configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) configure_file("${SDIR}/Obliviontt.zip" "${DDIR}/Obliviontt.zip" COPYONLY) configure_file("${SDIR}/VeraMono.ttf" "${DDIR}/VeraMono.ttf" COPYONLY) diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index e1fbc49b6..64435451a 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -151,6 +151,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -170,6 +192,7 @@ + diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index b47de005d..e96aeb918 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -130,7 +130,7 @@ - + diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 387a8587e..9c6716ff0 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -6,17 +6,52 @@ - + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/transparent.png b/files/mygui/transparent.png deleted file mode 100644 index 32d2ed1975611dbfc9baf5550b92118fee2d73b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPggaCRPzfaZ{P!_CO&qPZ!4!iOb0; m2?-I$8rTgC1sD!HGcs&^z_3mHan=i<3I @@ -107,6 +110,18 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& 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. + // has to be created in code with TU_DYNAMIC_WRITE_ONLY_DISCARDABLE param + // so that it can be modified at runtime. + mTransparentBGTexture = Ogre::TextureManager::getSingleton().createManual( + "transparent.png", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, + 1, 1, + 0, + Ogre::PF_A8R8G8B8, + Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); } void OgreRenderer::createScene(const std::string camName, float fov, float nearClip) diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 7dc539e27..50fe64015 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -24,6 +24,8 @@ # include "OgreD3D9Plugin.h" #endif +#include "OgreTexture.h" + namespace Ogre { class Root; @@ -71,6 +73,8 @@ namespace OEngine Fader* mFader; bool logging; + Ogre::TexturePtr mTransparentBGTexture; + public: OgreRenderer() : mRoot(NULL) From 689cf7ce054554354a08c49dedabc51fb98f7dd6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 23 May 2012 05:28:25 +0200 Subject: [PATCH 20/76] ConfirmationDialog --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwgui/confirmationdialog.cpp | 68 ++++++++++++++++++ apps/openmw/mwgui/confirmationdialog.hpp | 34 +++++++++ apps/openmw/mwgui/countdialog.cpp | 3 - apps/openmw/mwgui/settingswindow.cpp | 69 ++++++++++++++++++- apps/openmw/mwgui/settingswindow.hpp | 4 ++ apps/openmw/mwgui/window_manager.cpp | 5 ++ apps/openmw/mwgui/window_manager.hpp | 3 + components/settings/settings.cpp | 4 ++ files/mygui/CMakeLists.txt | 1 + .../openmw_confirmation_dialog_layout.xml | 25 +++++++ files/mygui/openmw_count_window_layout.xml | 8 ++- files/mygui/openmw_settings_window_layout.xml | 5 +- 13 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 apps/openmw/mwgui/confirmationdialog.cpp create mode 100644 apps/openmw/mwgui/confirmationdialog.hpp create mode 100644 files/mygui/openmw_confirmation_dialog_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index fd2fdf575..a3c147b94 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -28,6 +28,7 @@ add_openmw_dir (mwgui dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list formatting itemwidget inventorywindow container hud countdialog tradewindow settingswindow + confirmationdialog ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/confirmationdialog.cpp b/apps/openmw/mwgui/confirmationdialog.cpp new file mode 100644 index 000000000..a54bdb1d8 --- /dev/null +++ b/apps/openmw/mwgui/confirmationdialog.cpp @@ -0,0 +1,68 @@ +#include "confirmationdialog.hpp" + +#include + +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" + +namespace MWGui +{ + ConfirmationDialog::ConfirmationDialog(WindowManager& parWindowManager) : + WindowBase("openmw_confirmation_dialog_layout.xml", parWindowManager) + { + getWidget(mMessage, "Message"); + getWidget(mOkButton, "OkButton"); + getWidget(mCancelButton, "CancelButton"); + + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onCancelButtonClicked); + mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onOkButtonClicked); + } + + void ConfirmationDialog::open(const std::string& message) + { + setVisible(true); + + mMessage->setCaptionWithReplacing(message); + + int height = mMessage->getTextSize().height + 72; + + mMainWidget->setSize(mMainWidget->getWidth(), height); + + mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height+24); + + center(); + + // make other gui elements inaccessible while this dialog is open + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); + + int okButtonWidth = mOkButton->getTextSize().width + 24; + mOkButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth, + mOkButton->getTop(), + okButtonWidth, + mOkButton->getHeight()); + + int cancelButtonWidth = mCancelButton->getTextSize().width + 24; + mCancelButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth - cancelButtonWidth - 8, + mCancelButton->getTop(), + cancelButtonWidth, + mCancelButton->getHeight()); + } + + void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender) + { + close(); + } + + void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender) + { + eventOkClicked(); + + close(); + } + + void ConfirmationDialog::close() + { + setVisible(false); + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); + } +} diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp new file mode 100644 index 000000000..a20034171 --- /dev/null +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -0,0 +1,34 @@ +#ifndef MWGUI_CONFIRMATIONDIALOG_H +#define MWGUI_CONFIRMATIONDIALOG_H + +#include "window_base.hpp" + +namespace MWGui +{ + class ConfirmationDialog : public WindowBase + { + public: + ConfirmationDialog(WindowManager& parWindowManager); + void open(const std::string& message); + + typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; + + /** Event : Ok button was clicked.\n + signature : void method()\n + */ + EventHandle_Void eventOkClicked; + + private: + MyGUI::EditBox* mMessage; + MyGUI::Button* mOkButton; + MyGUI::Button* mCancelButton; + + void onCancelButtonClicked(MyGUI::Widget* _sender); + void onOkButtonClicked(MyGUI::Widget* _sender); + + void close(); + }; + +} + +#endif diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp index 16e3f9aab..e0a9bb908 100644 --- a/apps/openmw/mwgui/countdialog.cpp +++ b/apps/openmw/mwgui/countdialog.cpp @@ -17,9 +17,6 @@ namespace MWGui getWidget(mOkButton, "OkButton"); getWidget(mCancelButton, "CancelButton"); - mOkButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOk")->str); - mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str); - mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked); mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index af909ea8c..6eaf31ce9 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -2,6 +2,9 @@ #include #include +#include + +#include #include @@ -9,6 +12,7 @@ #include "../mwworld/world.hpp" #include "window_manager.hpp" +#include "confirmationdialog.hpp" namespace MWGui { @@ -19,10 +23,13 @@ namespace MWGui getWidget(mResolutionList, "ResolutionList"); getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); getWidget(mViewDistanceSlider, "ViewDistanceSlider"); + getWidget(mFullscreenButton, "FullscreenButton"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); + mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); center(); @@ -42,7 +49,15 @@ namespace MWGui // read settings int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI"); mMenuTransparencySlider->setScrollPosition(menu_transparency); - onSliderChangePosition(mMenuTransparencySlider, menu_transparency); + + float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-2000)/(5600-2000); + int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; + mViewDistanceSlider->setScrollPosition(viewdist); + + std::string on = mWindowManager.getGameSettingString("sOn", "On"); + std::string off = mWindowManager.getGameSettingString("sOff", "On"); + + mFullscreenButton->setCaption(Settings::Manager::getBool("fullscreen", "Video") ? on : off); } void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) @@ -50,6 +65,54 @@ namespace MWGui mWindowManager.setGuiMode(GM_Game); } + void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index) + { + if (index == MyGUI::ITEM_NONE) + return; + + ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); + dialog->open("#{sNotifyMessage67}"); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); + } + + void SettingsWindow::onResolutionAccept() + { + std::string resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected()); + size_t xPos = resStr.find("x"); + std::string resXStr = resStr.substr(0, xPos-1); + Ogre::StringUtil::trim(resXStr); + std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2)); + Ogre::StringUtil::trim(resYStr); + int resX = boost::lexical_cast(resXStr); + int resY = boost::lexical_cast(resYStr); + + Settings::Manager::setInt("resolution x", "Video", resX); + Settings::Manager::setInt("resolution y", "Video", resY); + + MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); + } + + void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) + { + std::string on = mWindowManager.getGameSettingString("sOn", "On"); + std::string off = mWindowManager.getGameSettingString("sOff", "On"); + bool newState; + if (_sender->castType()->getCaption() == on) + { + _sender->castType()->setCaption(off); + newState = false; + } + else + { + _sender->castType()->setCaption(on); + newState = true; + } + + if (_sender == mFullscreenButton) + Settings::Manager::setBool("fullscreen", "Video", newState); + } + void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) { float val = pos / float(scroller->getScrollRange()-1); @@ -57,6 +120,10 @@ namespace MWGui { Settings::Manager::setFloat("menu transparency", "GUI", val); } + else if (scroller == mViewDistanceSlider) + { + Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); + } MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 597f8dec1..785b0c9b1 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -18,11 +18,15 @@ namespace MWGui protected: MyGUI::Button* mOkButton; MyGUI::ListBox* mResolutionList; + MyGUI::Button* mFullscreenButton; MyGUI::ScrollBar* mMenuTransparencySlider; MyGUI::ScrollBar* mViewDistanceSlider; void onOkButtonClicked(MyGUI::Widget* _sender); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); + void onButtonToggled(MyGUI::Widget* _sender); + void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); + void onResolutionAccept(); }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 4bb34cf24..09ea6543a 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -17,6 +17,7 @@ #include "countdialog.hpp" #include "tradewindow.hpp" #include "settingswindow.hpp" +#include "confirmationdialog.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -52,6 +53,7 @@ WindowManager::WindowManager( , mCountDialog(NULL) , mTradeWindow(NULL) , mSettingsWindow(NULL) + , mConfirmationDialog(NULL) , mCharGen(NULL) , playerClass() , playerName() @@ -121,6 +123,7 @@ WindowManager::WindowManager( mBookWindow = new BookWindow(*this); mCountDialog = new CountDialog(*this); mSettingsWindow = new SettingsWindow(*this); + mConfirmationDialog = new ConfirmationDialog(*this); // The HUD is always on hud->setVisible(true); @@ -161,6 +164,8 @@ WindowManager::~WindowManager() delete mBookWindow; delete mScrollWindow; delete mTradeWindow; + delete mSettingsWindow; + delete mConfirmationDialog; cleanupGarbage(); } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index aab307035..9ccc42b1e 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -78,6 +78,7 @@ namespace MWGui class CountDialog; class TradeWindow; class SettingsWindow; + class ConfirmationDialog; struct ClassPoint { @@ -140,6 +141,7 @@ namespace MWGui MWGui::BookWindow* getBookWindow() {return mBookWindow;} MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;} MWGui::CountDialog* getCountDialog() {return mCountDialog;} + MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;} MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} MyGUI::Gui* getGui() const { return gui; } @@ -232,6 +234,7 @@ namespace MWGui CountDialog* mCountDialog; TradeWindow* mTradeWindow; SettingsWindow* mSettingsWindow; + ConfirmationDialog* mConfirmationDialog; CharacterCreation* mCharGen; diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 28201eda2..9b941e253 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -131,7 +131,11 @@ void Manager::setString (const std::string& setting, const std::string& category } } else + { + if (mDefaultFile.getSetting(setting, category) != value) + mChangedSettings.push_back(std::make_pair(category, setting)); mNewSettings[s] = value; + } } } diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 90a0c1fce..89ebd8f94 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -58,6 +58,7 @@ configure_file("${SDIR}/openmw_book_layout.xml" "${DDIR}/openmw_book_layout.xml" configure_file("${SDIR}/openmw_count_window_layout.xml" "${DDIR}/openmw_count_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_settings_window_layout.xml" "${DDIR}/openmw_settings_window_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_confirmation_dialog_layout.xml" "${DDIR}/openmw_confirmation_dialog_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) diff --git a/files/mygui/openmw_confirmation_dialog_layout.xml b/files/mygui/openmw_confirmation_dialog_layout.xml new file mode 100644 index 000000000..7b8bd2a1f --- /dev/null +++ b/files/mygui/openmw_confirmation_dialog_layout.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_count_window_layout.xml b/files/mygui/openmw_count_window_layout.xml index 38ba7644f..ae6635dff 100644 --- a/files/mygui/openmw_count_window_layout.xml +++ b/files/mygui/openmw_count_window_layout.xml @@ -20,8 +20,12 @@ - - + + + + + + diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 9c6716ff0..2fa332d9a 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -34,9 +34,10 @@ - - + + + From 7ebbc099b37024d4aee29da8f2ac4b4483efc6b2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 23 May 2012 12:23:35 +0200 Subject: [PATCH 21/76] allow stacking gui modes --- apps/openmw/engine.cpp | 8 +- apps/openmw/mwdialogue/dialoguemanager.cpp | 4 +- apps/openmw/mwgui/bookwindow.cpp | 9 +- apps/openmw/mwgui/charactercreation.cpp | 118 ++++++++++++++------- apps/openmw/mwgui/charactercreation.hpp | 1 - apps/openmw/mwgui/container.cpp | 4 +- apps/openmw/mwgui/dialogue.cpp | 16 ++- apps/openmw/mwgui/dialogue.hpp | 2 - apps/openmw/mwgui/messagebox.cpp | 1 - apps/openmw/mwgui/mode.hpp | 1 - apps/openmw/mwgui/scrollwindow.cpp | 9 +- apps/openmw/mwgui/tradewindow.cpp | 4 +- apps/openmw/mwgui/window_manager.cpp | 69 ++++++------ apps/openmw/mwgui/window_manager.hpp | 24 ++--- apps/openmw/mwinput/inputmanager.cpp | 73 ++++++------- apps/openmw/mwinput/inputmanager.hpp | 4 +- apps/openmw/mwscript/guiextensions.cpp | 2 +- apps/openmw/mwworld/actionopen.cpp | 2 +- apps/openmw/mwworld/actionread.cpp | 4 +- 19 files changed, 194 insertions(+), 161 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 85b0557b1..412050ff2 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -105,7 +105,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) // frame. // passing of time - if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game) + if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) MWBase::Environment::get().getWorld()->advanceTime ( mEnvironment.getFrameDuration()*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600); @@ -116,9 +116,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) // update actors std::vector > movement; MWBase::Environment::get().getMechanicsManager()->update (movement, mEnvironment.getFrameDuration(), - MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game); + MWBase::Environment::get().getWindowManager()->isGuiMode()); - if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game) + if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) MWBase::Environment::get().getWorld()->doPhysics (movement, mEnvironment.getFrameDuration()); // update world @@ -413,7 +413,7 @@ void OMW::Engine::go() void OMW::Engine::activate() { - if (MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game) + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index af589469e..716f472a0 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -635,7 +635,7 @@ namespace MWDialogue actorKnownTopics.clear(); //initialise the GUI - MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Dialogue); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue); MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor)); @@ -843,7 +843,7 @@ namespace MWDialogue void DialogueManager::goodbyeSelected() { - MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } void DialogueManager::questionAnswered(std::string answere) diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index c6411175d..f1873b550 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -1,13 +1,14 @@ #include "bookwindow.hpp" -#include "formatting.hpp" +#include #include "../mwbase/environment.hpp" #include "../mwinput/inputmanager.hpp" #include "../mwsound/soundmanager.hpp" #include "../mwworld/actiontake.hpp" -#include +#include "formatting.hpp" +#include "window_manager.hpp" using namespace MWGui; @@ -91,7 +92,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) // no 3d sounds because the object could be in a container. MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game); + mWindowManager.popGuiMode(); } void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -101,7 +102,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mBook); take.execute(); - MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); + mWindowManager.popGuiMode(); } void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index afb168d32..691fd4a91 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -110,7 +110,6 @@ using namespace MWGui; CharacterCreation::CharacterCreation(WindowManager* _wm) : mNameDialog(0) , mRaceDialog(0) - , mDialogueWindow(0) , mClassChoiceDialog(0) , mGenerateClassQuestionDialog(0) , mGenerateClassResultDialog(0) @@ -253,7 +252,7 @@ void CharacterCreation::onReviewDialogDone(WindowBase* parWindow) if (mReviewDialog) mWM->removeDialog(mReviewDialog); - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } void CharacterCreation::onReviewDialogBack() @@ -261,7 +260,7 @@ void CharacterCreation::onReviewDialogBack() if (mReviewDialog) mWM->removeDialog(mReviewDialog); - mWM->setGuiMode(GM_Birth); + mWM->pushGuiMode(GM_Birth); } void CharacterCreation::onReviewActivateDialog(int parDialog) @@ -270,19 +269,21 @@ void CharacterCreation::onReviewActivateDialog(int parDialog) mWM->removeDialog(mReviewDialog); mCreationStage = CSE_ReviewNext; + mWM->popGuiMode(); + switch(parDialog) { case ReviewDialog::NAME_DIALOG: - mWM->setGuiMode(GM_Name); + mWM->pushGuiMode(GM_Name); break; case ReviewDialog::RACE_DIALOG: - mWM->setGuiMode(GM_Race); + mWM->pushGuiMode(GM_Race); break; case ReviewDialog::CLASS_DIALOG: - mWM->setGuiMode(GM_Class); + mWM->pushGuiMode(GM_Class); break; case ReviewDialog::BIRTHSIGN_DIALOG: - mWM->setGuiMode(GM_Birth); + mWM->pushGuiMode(GM_Birth); }; } @@ -304,13 +305,19 @@ void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow) //TODO This bit gets repeated a few times; wrap it in a function if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else if (mCreationStage >= CSE_ClassChosen) - mWM->setGuiMode(GM_Birth); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Birth); + } else { mCreationStage = CSE_ClassChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -324,7 +331,8 @@ void CharacterCreation::onPickClassDialogBack() mWM->removeDialog(mPickClassDialog); } - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); } void CharacterCreation::onClassChoice(int _index) @@ -334,19 +342,21 @@ void CharacterCreation::onClassChoice(int _index) mWM->removeDialog(mClassChoiceDialog); } + mWM->popGuiMode(); + switch(_index) { case ClassChoiceDialog::Class_Generate: - mWM->setGuiMode(GM_ClassGenerate); + mWM->pushGuiMode(GM_ClassGenerate); break; case ClassChoiceDialog::Class_Pick: - mWM->setGuiMode(GM_ClassPick); + mWM->pushGuiMode(GM_ClassPick); break; case ClassChoiceDialog::Class_Create: - mWM->setGuiMode(GM_ClassCreate); + mWM->pushGuiMode(GM_ClassCreate); break; case ClassChoiceDialog::Class_Back: - mWM->setGuiMode(GM_Race); + mWM->pushGuiMode(GM_Race); break; }; @@ -363,13 +373,19 @@ void CharacterCreation::onNameDialogDone(WindowBase* parWindow) } if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else if (mCreationStage >= CSE_NameChosen) - mWM->setGuiMode(GM_Race); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Race); + } else { mCreationStage = CSE_NameChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -383,7 +399,8 @@ void CharacterCreation::onRaceDialogBack() mWM->removeDialog(mRaceDialog); } - mWM->setGuiMode(GM_Name); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Name); } void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) @@ -398,13 +415,19 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) } if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); - else if(mCreationStage >= CSE_RaceChosen) - mWM->setGuiMode(GM_Class); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } + else if (mCreationStage >= CSE_NameChosen) + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); + } else { - mCreationStage = CSE_RaceChosen; - mWM->setGuiMode(GM_Game); + mCreationStage = CSE_NameChosen; + mWM->popGuiMode(); } } @@ -419,11 +442,14 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow) } if (mCreationStage >= CSE_BirthSignChosen) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else { mCreationStage = CSE_BirthSignChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -435,7 +461,8 @@ void CharacterCreation::onBirthSignDialogBack() mWM->removeDialog(mBirthSignDialog); } - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); } void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) @@ -470,13 +497,19 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) } if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else if (mCreationStage >= CSE_ClassChosen) - mWM->setGuiMode(GM_Birth); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Birth); + } else { mCreationStage = CSE_ClassChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -485,7 +518,8 @@ void CharacterCreation::onCreateClassDialogBack() if (mCreateClassDialog) mWM->removeDialog(mCreateClassDialog); - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); } void CharacterCreation::onClassQuestionChosen(int _index) @@ -496,7 +530,8 @@ void CharacterCreation::onClassQuestionChosen(int _index) mWM->removeDialog(mGenerateClassQuestionDialog); if (_index < 0 || _index >= 3) { - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); return; } @@ -581,7 +616,8 @@ void CharacterCreation::showClassQuestionDialog() if (mGenerateClassStep > sGenerateClassSteps.size()) { - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); return; } @@ -610,7 +646,8 @@ void CharacterCreation::onGenerateClassBack() mWM->removeDialog(mGenerateClassResultDialog); MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); - mWM->setGuiMode(GM_Class); + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Class); } void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) @@ -620,13 +657,19 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); if (mCreationStage == CSE_ReviewNext) - mWM->setGuiMode(GM_Review); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Review); + } else if (mCreationStage >= CSE_ClassChosen) - mWM->setGuiMode(GM_Birth); + { + mWM->popGuiMode(); + mWM->pushGuiMode(GM_Birth); + } else { mCreationStage = CSE_ClassChosen; - mWM->setGuiMode(GM_Game); + mWM->popGuiMode(); } } @@ -634,7 +677,6 @@ CharacterCreation::~CharacterCreation() { delete mNameDialog; delete mRaceDialog; - delete mDialogueWindow; delete mClassChoiceDialog; delete mGenerateClassQuestionDialog; delete mGenerateClassResultDialog; diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index 222754cdc..dfb07853e 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -46,7 +46,6 @@ namespace MWGui //Dialogs TextInputDialog* mNameDialog; RaceDialog* mRaceDialog; - DialogueWindow* mDialogueWindow; ClassChoiceDialog* mClassChoiceDialog; InfoBoxDialog* mGenerateClassQuestionDialog; GenerateClassResultDialog* mGenerateClassResultDialog; diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index be21987ef..8ac876c07 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -636,7 +636,7 @@ void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { - MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } @@ -667,6 +667,6 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) containerStore.clear(); - MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 53ab98aeb..8a68ff666 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -112,15 +112,6 @@ void DialogueWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) history->setVScrollPosition(history->getVScrollPosition() - _rel*0.3); } -void DialogueWindow::open() -{ - topicsList->clear(); - pTopicsText.clear(); - history->eraseText(0,history->getTextLength()); - updateOptions(); - setVisible(true); -} - void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) { MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); @@ -133,7 +124,7 @@ void DialogueWindow::onSelectTopic(std::string topic) if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str) { /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? - mWindowManager.setGuiMode(GM_Barter); + mWindowManager.pushGuiMode(GM_Barter); mWindowManager.getTradeWindow()->startTrade(mActor); } @@ -147,6 +138,11 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) mActor = actor; topicsList->setEnabled(true); setTitle(npcName); + + topicsList->clear(); + pTopicsText.clear(); + history->eraseText(0,history->getTextLength()); + updateOptions(); } void DialogueWindow::setKeywords(std::list keyWords) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 7f69f972c..d3106ad38 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -30,8 +30,6 @@ namespace MWGui public: DialogueWindow(WindowManager& parWindowManager); - void open(); - // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index a6b9025ce..9a0671478 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -58,7 +58,6 @@ void MessageBoxManager::onFrame (float frameDuration) if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { delete mInterMessageBoxe; mInterMessageBoxe = NULL; - mWindowManager->setNextMode(GM_Game); } } diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 775fe4a03..d465aa0c5 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -5,7 +5,6 @@ namespace MWGui { enum GuiMode { - GM_Game, // Game mode, only HUD GM_Inventory, // Inventory mode GM_Container, GM_MainMenu, // Main menu mode diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index 877864cfe..f4d45fc26 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -1,12 +1,13 @@ #include "scrollwindow.hpp" -#include "formatting.hpp" - #include "../mwbase/environment.hpp" #include "../mwinput/inputmanager.hpp" #include "../mwworld/actiontake.hpp" #include "../mwsound/soundmanager.hpp" +#include "formatting.hpp" +#include "window_manager.hpp" + using namespace MWGui; ScrollWindow::ScrollWindow (WindowManager& parWindowManager) : @@ -55,7 +56,7 @@ void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) { MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); - MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); + mWindowManager.popGuiMode(); } void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -65,5 +66,5 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mScroll); take.execute(); - MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); + mWindowManager.popGuiMode(); } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 60cc06cb8..311ea6c95 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -210,7 +210,7 @@ namespace MWGui std::string sound = "Item Gold Up"; MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - mWindowManager.setGuiMode(GM_Game); + mWindowManager.popGuiMode(); } void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) @@ -220,7 +220,7 @@ namespace MWGui // now gimme back my stuff! mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); - mWindowManager.setGuiMode(GM_Game); + mWindowManager.popGuiMode(); } void TradeWindow::updateLabels() diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 2cacf2346..123323168 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -62,9 +62,6 @@ WindowManager::WindowManager( , playerMagicka() , playerFatigue() , gui(NULL) - , mode(GM_Game) - , nextMode(GM_Game) - , needModeChange(false) , garbageDialogs() , shown(GW_ALL) , allowed(newGame ? GW_None : GW_ALL) @@ -178,12 +175,6 @@ void WindowManager::cleanupGarbage() void WindowManager::update() { cleanupGarbage(); - if (needModeChange) - { - needModeChange = false; - MWBase::Environment::get().getInputManager()->setGuiMode(nextMode); - nextMode = GM_Game; - } if (showFPSLevel > 0) { hud->setFPS(mFPS); @@ -192,17 +183,6 @@ void WindowManager::update() } } -void WindowManager::setNextMode(GuiMode newMode) -{ - nextMode = newMode; - needModeChange = true; -} - -void WindowManager::setGuiMode(GuiMode newMode) -{ - MWBase::Environment::get().getInputManager()->setGuiMode(newMode); -} - void WindowManager::updateVisible() { // Start out by hiding everything except the HUD @@ -221,15 +201,20 @@ void WindowManager::updateVisible() // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); - if (mode == GM_Game) + bool gameMode = !isGuiMode(); + + if (gameMode) mToolTips->enterGameMode(); else mToolTips->enterGuiMode(); + // If in game mode, don't show anything. + if (gameMode) + return; + + GuiMode mode = mGuiModes.back(); + switch(mode) { - case GM_Game: - // If in game mode, don't show anything. - break; case GM_MainMenu: menu->setVisible(true); break; @@ -273,7 +258,7 @@ void WindowManager::updateVisible() mInventoryWindow->openInventory(); break; case GM_Dialogue: - mDialogueWindow->open(); + mDialogueWindow->setVisible(true); break; case GM_Barter: mInventoryWindow->setVisible(true); @@ -281,9 +266,6 @@ void WindowManager::updateVisible() mTradeWindow->setVisible(true); break; case GM_InterMessageBox: - if(!mMessageBoxManager->isInteractiveMessageBox()) { - setGuiMode(GM_Game); - } break; case GM_Journal: mJournal->setVisible(true); @@ -291,9 +273,6 @@ void WindowManager::updateVisible() break; default: // Unsupported mode, switch back to game - // Note: The call will eventually end up this method again but - // will stop at the check if mode is GM_Game. - setGuiMode(GM_Game); break; } } @@ -427,7 +406,7 @@ void WindowManager::messageBox (const std::string& message, const std::vectorcreateInteractiveMessageBox(message, buttons); - setGuiMode(GM_InterMessageBox); + pushGuiMode(GM_InterMessageBox); } } @@ -452,7 +431,7 @@ void WindowManager::onDialogueWindowBye() //removeDialog(dialogueWindow); mDialogueWindow->setVisible(false); } - setGuiMode(GM_Game); + popGuiMode(); } void WindowManager::onFrame (float frameDuration) @@ -597,3 +576,27 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r if (setting && setting->type == ESM::VT_String) _result = setting->str; } + +void WindowManager::pushGuiMode(GuiMode mode) +{ + if (mode==GM_Inventory && allowed==GW_None) + return; + + mGuiModes.push_back(mode); + + bool gameMode = !isGuiMode(); + MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); + + updateVisible(); +} + +void WindowManager::popGuiMode() +{ + if (mGuiModes.size()) + mGuiModes.pop_back(); + + bool gameMode = !isGuiMode(); + MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); + + updateVisible(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 22fe973a5..d519d2e49 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -96,8 +96,6 @@ namespace MWGui WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath); virtual ~WindowManager(); - void setGuiMode(GuiMode newMode); - /** * Should be called each frame to update windows/gui elements. * This could mean updating sizes of gui elements or opening @@ -105,19 +103,17 @@ namespace MWGui */ void update(); - void setMode(GuiMode newMode) + void pushGuiMode(GuiMode mode); + void popGuiMode(); + + GuiMode getMode() const { - if (newMode==GM_Inventory && allowed==GW_None) - return; - - mode = newMode; - updateVisible(); + if (mGuiModes.empty()) + throw std::runtime_error ("getMode() called, but there is no active mode"); + return mGuiModes.back(); } - void setNextMode(GuiMode newMode); - GuiMode getMode() const { return mode; } - - bool isGuiMode() const { return getMode() != GM_Game; } // Everything that is not game mode is considered "gui mode" + bool isGuiMode() const { return !mGuiModes.empty(); } // Disallow all inventory mode windows void disallowAll() @@ -244,9 +240,7 @@ namespace MWGui MyGUI::Gui *gui; // Gui - GuiMode mode; // Current gui mode - GuiMode nextMode; // Next mode to activate in update() - bool needModeChange; //Whether a mode change is needed in update() [will use nextMode] + std::vector mGuiModes; std::vector garbageDialogs; void cleanupGarbage(); diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 8f8f1e1ee..c074731d8 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -143,20 +143,20 @@ namespace MWInput /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ void toggleInventory() { - using namespace MWGui; + using namespace MWGui; - if (mDragDrop) - return; + if (mDragDrop) + return; - GuiMode mode = windows.getMode(); + bool gameMode = !windows.isGuiMode(); - // Toggle between game mode and inventory mode - if(mode == GM_Game) - setGuiMode(GM_Inventory); - else if(mode == GM_Inventory) - setGuiMode(GM_Game); + // Toggle between game mode and inventory mode + if(gameMode) + windows.pushGuiMode(GM_Inventory); + else if(windows.getMode() == GM_Inventory) + windows.popGuiMode(); - // .. but don't touch any other mode. + // .. but don't touch any other mode. } // Toggle console @@ -167,28 +167,33 @@ namespace MWInput if (mDragDrop) return; - GuiMode mode = windows.getMode(); + bool gameMode = !windows.isGuiMode(); // Switch to console mode no matter what mode we are currently // in, except of course if we are already in console mode - if(mode == GM_Console) - setGuiMode(GM_Game); - else setGuiMode(GM_Console); + if (!gameMode) + { + if (windows.getMode() == GM_Console) + windows.popGuiMode(); + else + windows.pushGuiMode(GM_Console); + } + else + windows.pushGuiMode(GM_Console); } void toggleJournal() { - using namespace MWGui; + using namespace MWGui; - GuiMode mode = windows.getMode(); + // Toggle between game mode and journal mode + bool gameMode = !windows.isGuiMode(); - // Toggle between game mode and journal mode - if(mode == GM_Game) - setGuiMode(GM_Journal); - else if(mode == GM_Journal) - setGuiMode(GM_Game); - - // .. but don't touch any other mode. + if(gameMode) + windows.pushGuiMode(GM_Journal); + else if(windows.getMode() == GM_Journal) + windows.popGuiMode(); + // .. but don't touch any other mode. } void activate() @@ -282,8 +287,7 @@ namespace MWInput lst->add(guiEvents,Event::EV_ALL); } - // Start out in game mode - setGuiMode(MWGui::GM_Game); + changeInputMode(false); /********************************** Key binding section @@ -348,6 +352,7 @@ namespace MWInput windows.update(); // Disable movement in Gui mode + if (windows.isGuiMode()) return; // Configure player movement according to keyboard input. Actual movement will @@ -388,14 +393,10 @@ namespace MWInput // Switch between gui modes. Besides controlling the Gui windows // this also makes sure input is directed to the right place - void setGuiMode(MWGui::GuiMode mode) + void changeInputMode(bool guiMode) { - // Tell the GUI what to show (this also takes care of the mouse - // pointer) - windows.setMode(mode); - // Are we in GUI mode now? - if(windows.isGuiMode()) + if(guiMode) { // Disable mouse look mouse->setCamera(NULL); @@ -431,11 +432,6 @@ namespace MWInput delete impl; } - void MWInputManager::setGuiMode(MWGui::GuiMode mode) - { - impl->setGuiMode(mode); - } - void MWInputManager::update() { impl->update(); @@ -445,4 +441,9 @@ namespace MWInput { impl->setDragDrop(dragDrop); } + + void MWInputManager::changeInputMode(bool guiMode) + { + impl->changeInputMode(guiMode); + } } diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index 158d05f0e..b8d98ed56 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -50,9 +50,9 @@ namespace MWInput void update(); - void setDragDrop(bool dragDrop); + void changeInputMode(bool guiMode); - void setGuiMode(MWGui::GuiMode mode); + void setDragDrop(bool dragDrop); }; } #endif diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index c4d9e9fab..b267cc6e4 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -44,7 +44,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWBase::Environment::get().getInputManager()->setGuiMode(mDialogue); + MWBase::Environment::get().getWindowManager()->pushGuiMode(mDialogue); } }; diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index e450585e6..e2c8ec5cf 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -16,7 +16,7 @@ namespace MWWorld void ActionOpen::execute () { - MWBase::Environment::get().getWindowManager()->setGuiMode(MWGui::GM_Container); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container); MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(mContainer); } } diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 0d37e06f5..34e95cbd0 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -18,12 +18,12 @@ namespace MWWorld if (ref->base->data.isScroll) { - MWBase::Environment::get().getWindowManager()->setGuiMode(MWGui::GM_Scroll); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Scroll); MWBase::Environment::get().getWindowManager()->getScrollWindow()->open(mObject); } else { - MWBase::Environment::get().getWindowManager()->setGuiMode(MWGui::GM_Book); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Book); MWBase::Environment::get().getWindowManager()->getBookWindow()->open(mObject); } } From a1907e7b88ceff1bfc54ace08b498d55a12c9cb0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 03:48:02 +0200 Subject: [PATCH 22/76] cleaning up mwgui/widgets part 1 --- apps/openmw/mwgui/widgets.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 74da7fc93..6e230e2c6 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -23,6 +23,18 @@ namespace MWGui { void fixTexturePath(std::string &path); + struct SpellEffectParams + { + bool mHasTarget; // potion effects for example have no target (target is always the player) + bool mIsConstant; // constant effect means that duration will not be displayed + std::string effectID; + + // note that the ESM::MagicEffect (retrieved through effectID) might already store skill and attribute, + // in that case the ESM::MagicEffect skill/attribute is preferred. this is just here for ingredients which + // have them defined elsewhere. + signed char skill, attribute; + }; + class MYGUI_EXPORT MWSkill : public Widget { MYGUI_RTTI_DERIVED( MWSkill ); From cb35f4d208d4760634b10aa28c341d3fd71ac9ed Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 03:50:02 +0200 Subject: [PATCH 23/76] some unrelated gui cleanup --- apps/openmw/mwgui/map_window.cpp | 6 +- apps/openmw/mwgui/stats_window.cpp | 115 -------------------- apps/openmw/mwgui/stats_window.hpp | 2 - apps/openmw/mwgui/window_manager.cpp | 2 + files/mygui/openmw_stats_window_layout.xml | 120 ++++++++++++++++++--- 5 files changed, 109 insertions(+), 136 deletions(-) diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index 78ca70798..a44571d0a 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -102,7 +102,7 @@ MapWindow::MapWindow(WindowManager& parWindowManager) : getWidget(mButton, "WorldButton"); mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); - mButton->setCaption(mWindowManager.getGameSettingString("sWorld", "")); + mButton->setCaptionWithReplacing("#{sWorld}"); int width = mButton->getTextSize().width + 24; mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22); @@ -172,8 +172,8 @@ void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender) mGlobalMap->setVisible(mGlobal); mLocalMap->setVisible(!mGlobal); - mButton->setCaption( mGlobal ? mWindowManager.getGameSettingString("sWorld", "") : - mWindowManager.getGameSettingString("sLocal", "")); + mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : + "#{sWorld}"); int width = mButton->getTextSize().width + 24; mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22); } diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index cdf6a5871..54d9d7d4e 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -77,8 +77,6 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager) MyGUI::WindowPtr t = static_cast(mMainWidget); t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize); - - setupToolTips(); } void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos) @@ -633,116 +631,3 @@ void StatsWindow::onPinToggled() { mWindowManager.setHMSVisibility(!mPinned); } - -void StatsWindow::setupToolTips() -{ - - const ESMS::ESMStore &store = mWindowManager.getStore(); - MyGUI::Widget* widget; - - /// \todo move this into the .layout file! - - getWidget(widget, "Attrib1"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeStrength")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sStrDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_strength.dds"); - getWidget(widget, "AttribVal1"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeStrength")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sStrDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_strength.dds"); - - getWidget(widget, "Attrib2"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeIntelligence")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sIntDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_int.dds"); - getWidget(widget, "AttribVal2"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeIntelligence")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sIntDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_int.dds"); - - getWidget(widget, "Attrib3"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeWillpower")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sWilDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_wilpower.dds"); - getWidget(widget, "AttribVal3"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeWillpower")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sWilDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_wilpower.dds"); - - getWidget(widget, "Attrib4"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeAgility")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sAgiDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_agility.dds"); - getWidget(widget, "AttribVal4"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeAgility")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sAgiDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_agility.dds"); - - getWidget(widget, "Attrib5"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeSpeed")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sSpdDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_speed.dds"); - getWidget(widget, "AttribVal5"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeSpeed")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sSpdDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_speed.dds"); - - getWidget(widget, "Attrib6"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeEndurance")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sEndDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_endurance.dds"); - getWidget(widget, "AttribVal6"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeEndurance")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sEndDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_endurance.dds"); - - getWidget(widget, "Attrib7"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributePersonality")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sPerDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_personality.dds"); - getWidget(widget, "AttribVal7"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributePersonality")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sPerDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_personality.dds"); - - getWidget(widget, "Attrib8"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeLuck")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sLucDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_luck.dds"); - getWidget(widget, "AttribVal8"); - widget->setUserString("ToolTipType", "Layout"); - widget->setUserString("ToolTipLayout", "AttributeToolTip"); - widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeLuck")->str); - widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sLucDesc")->str); - widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_luck.dds"); -} diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp index 50a83bb29..bbd916585 100644 --- a/apps/openmw/mwgui/stats_window.hpp +++ b/apps/openmw/mwgui/stats_window.hpp @@ -50,8 +50,6 @@ namespace MWGui MyGUI::Widget* addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void updateScroller(); - void setupToolTips(); - void setFactions (const FactionList& factions); void setBirthSign (const std::string &signId); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 09ea6543a..6be712509 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -608,4 +608,6 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().gameSettings.search(_tag); if (setting && setting->type == ESM::VT_String) _result = setting->str; + else + _result = _tag; } diff --git a/files/mygui/openmw_stats_window_layout.xml b/files/mygui/openmw_stats_window_layout.xml index 4729e3bca..81d70f704 100644 --- a/files/mygui/openmw_stats_window_layout.xml +++ b/files/mygui/openmw_stats_window_layout.xml @@ -99,29 +99,117 @@ - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + From 9b94edd561d27a69ba137c89f225ed49cbd5bf2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 04:34:53 +0200 Subject: [PATCH 24/76] audio tab with volume sliders --- apps/openmw/mwgui/settingswindow.cpp | 44 ++++++++++++++++--- apps/openmw/mwgui/settingswindow.hpp | 9 ++++ apps/openmw/mwsound/soundmanager.cpp | 16 +++++-- apps/openmw/mwsound/soundmanager.hpp | 8 ++++ files/mygui/openmw_settings_window_layout.xml | 43 ++++++++++++++++-- files/settings-default.cfg | 4 +- 6 files changed, 109 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 6eaf31ce9..d8e1072e3 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -24,6 +24,11 @@ namespace MWGui getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); getWidget(mViewDistanceSlider, "ViewDistanceSlider"); getWidget(mFullscreenButton, "FullscreenButton"); + getWidget(mMasterVolumeSlider, "MasterVolume"); + getWidget(mVoiceVolumeSlider, "VoiceVolume"); + getWidget(mEffectsVolumeSlider, "EffectsVolume"); + getWidget(mFootstepsVolumeSlider, "FootstepsVolume"); + getWidget(mMusicVolumeSlider, "MusicVolume"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -31,6 +36,12 @@ namespace MWGui mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); + mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mEffectsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mFootstepsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mMusicVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + center(); int okSize = mOkButton->getTextSize().width + 24; @@ -54,6 +65,12 @@ namespace MWGui int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; mViewDistanceSlider->setScrollPosition(viewdist); + mMasterVolumeSlider->setScrollPosition(Settings::Manager::getFloat("master volume", "Sound") * (mMasterVolumeSlider->getScrollRange()-1)); + mMusicVolumeSlider->setScrollPosition(Settings::Manager::getFloat("music volume", "Sound") * (mMusicVolumeSlider->getScrollRange()-1)); + mEffectsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("sfx volume", "Sound") * (mEffectsVolumeSlider->getScrollRange()-1)); + mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1)); + mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); + std::string on = mWindowManager.getGameSettingString("sOn", "On"); std::string off = mWindowManager.getGameSettingString("sOff", "On"); @@ -90,7 +107,7 @@ namespace MWGui Settings::Manager::setInt("resolution x", "Video", resX); Settings::Manager::setInt("resolution y", "Video", resY); - MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); + apply(); } void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) @@ -117,14 +134,27 @@ namespace MWGui { float val = pos / float(scroller->getScrollRange()-1); if (scroller == mMenuTransparencySlider) - { Settings::Manager::setFloat("menu transparency", "GUI", val); - } else if (scroller == mViewDistanceSlider) - { - Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); - } + Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); + else if (scroller == mMasterVolumeSlider) + Settings::Manager::setFloat("master volume", "Sound", val); + else if (scroller == mVoiceVolumeSlider) + Settings::Manager::setFloat("voice volume", "Sound", val); + else if (scroller == mEffectsVolumeSlider) + Settings::Manager::setFloat("sfx volume", "Sound", val); + else if (scroller == mFootstepsVolumeSlider) + Settings::Manager::setFloat("footsteps volume", "Sound", val); + else if (scroller == mMusicVolumeSlider) + Settings::Manager::setFloat("music volume", "Sound", val); - MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::apply()); + apply(); + } + + void SettingsWindow::apply() + { + const Settings::CategorySettingVector changed = Settings::Manager::apply(); + MWBase::Environment::get().getWorld()->processChangedSettings(changed); + MWBase::Environment::get().getWorld()->processChangedSettings(changed); } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 785b0c9b1..62acc5649 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -22,11 +22,20 @@ namespace MWGui MyGUI::ScrollBar* mMenuTransparencySlider; MyGUI::ScrollBar* mViewDistanceSlider; + // audio + MyGUI::ScrollBar* mMasterVolumeSlider; + MyGUI::ScrollBar* mVoiceVolumeSlider; + MyGUI::ScrollBar* mEffectsVolumeSlider; + MyGUI::ScrollBar* mFootstepsVolumeSlider; + MyGUI::ScrollBar* mMusicVolumeSlider; + void onOkButtonClicked(MyGUI::Widget* _sender); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onButtonToggled(MyGUI::Widget* _sender); void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); void onResolutionAccept(); + + void apply(); }; } diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 8deab3c04..11576e22a 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -7,7 +7,6 @@ #include #include -#include #include "../mwbase/environment.hpp" @@ -53,6 +52,8 @@ namespace MWSound , mMasterVolume(1.0f) , mSFXVolume(1.0f) , mMusicVolume(1.0f) + , mFootstepsVolume(1.0f) + , mVoiceVolume(1.0f) { if(!useSound) return; @@ -210,7 +211,7 @@ namespace MWSound try { // The range values are not tested - float basevol = mMasterVolume * mSFXVolume; + float basevol = mMasterVolume * mVoiceVolume; std::string filePath = "Sound/"+filename; const ESM::Position &pos = ptr.getCellRef().pos; const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]); @@ -234,7 +235,7 @@ namespace MWSound return; try { - float basevol = mMasterVolume * mSFXVolume; + float basevol = mMasterVolume * mVoiceVolume; std::string filePath = "Sound/"+filename; SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal); @@ -527,6 +528,15 @@ namespace MWSound } + void SoundManager::processChangedSettings(const Settings::CategorySettingVector& settings) + { + mMasterVolume = Settings::Manager::getFloat("master volume", "Sound"); + mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); + mSFXVolume = Settings::Manager::getFloat("sfx volume", "Sound"); + mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); + mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); + } + // Default readAll implementation, for decoders that can't do anything // better void Sound_Decoder::readAll(std::vector &output) diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index e1816cd1f..562b2af00 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -7,6 +7,8 @@ #include +#include + #include "../mwworld/ptr.hpp" @@ -52,6 +54,10 @@ namespace MWSound float mMasterVolume; float mSFXVolume; float mMusicVolume; + float mVoiceVolume; + + // not implemented + float mFootstepsVolume; boost::shared_ptr mMusic; std::string mCurrentPlaylist; @@ -78,6 +84,8 @@ namespace MWSound SoundManager(bool useSound); ~SoundManager(); + void processChangedSettings(const Settings::CategorySettingVector& settings); + void stopMusic(); ///< Stops music if it's playing diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 2fa332d9a..dc1cbfa9e 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -9,23 +9,58 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index ab0b75ff2..a6623656c 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -131,7 +131,9 @@ underwater effect = true # Device name. Blank means default device = -# Volumes. Sfx and music volumes are both affected by the master volume +# Volumes. master volume affects all other volumes. master volume = 1.0 sfx volume = 1.0 music volume = 0.4 +footsteps volume = 0.6 +voice volume = 1.0 From 189b044392b6fc94464d3450ca73754b38abb1ef Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 04:37:41 +0200 Subject: [PATCH 25/76] small correction --- apps/openmw/mwsound/soundmanager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 11576e22a..b6f4296aa 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -64,6 +64,10 @@ namespace MWSound mSFXVolume = std::min(std::max(mSFXVolume, 0.0f), 1.0f); mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); mMusicVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); + mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); + mVoiceVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); + mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); + mFootstepsVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); std::cout << "Sound output: " << SOUND_OUT << std::endl; std::cout << "Sound decoder: " << SOUND_IN << std::endl; From cbe89f7e32eede6ea7773a5d606066329b01344b Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 08:56:45 +0200 Subject: [PATCH 26/76] copy&paste mistake --- apps/openmw/mwsound/soundmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index b6f4296aa..27294ae77 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -65,9 +65,9 @@ namespace MWSound mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); mMusicVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); - mVoiceVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); + mVoiceVolume = std::min(std::max(mVoiceVolume, 0.0f), 1.0f); mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); - mFootstepsVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); + mFootstepsVolume = std::min(std::max(mFootstepsVolume, 0.0f), 1.0f); std::cout << "Sound output: " << SOUND_OUT << std::endl; std::cout << "Sound decoder: " << SOUND_IN << std::endl; From 6ea7bdb224c07a6965482610508d02c6f78c9b89 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 11:50:48 +0200 Subject: [PATCH 27/76] vsync & fps buttons, sound volume apply fix --- apps/openmw/mwgui/settingswindow.cpp | 42 ++++++++++++-- apps/openmw/mwgui/settingswindow.hpp | 8 ++- apps/openmw/mwgui/window_manager.cpp | 13 ++--- apps/openmw/mwgui/window_manager.hpp | 6 +- apps/openmw/mwinput/inputmanager.cpp | 10 ---- files/mygui/openmw_settings_window_layout.xml | 58 +++++++++++++------ 6 files changed, 92 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index d8e1072e3..ce7f0d0e2 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -10,10 +10,24 @@ #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" #include "confirmationdialog.hpp" +namespace +{ + std::string fpsLevelToStr(int level) + { + if (level == 0) + return "#{sOff}"; + else if (level == 1) + return "Basic"; + else + return "Detailed"; + } +} + namespace MWGui { SettingsWindow::SettingsWindow(WindowManager& parWindowManager) : @@ -24,6 +38,8 @@ namespace MWGui getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); getWidget(mViewDistanceSlider, "ViewDistanceSlider"); getWidget(mFullscreenButton, "FullscreenButton"); + getWidget(mVSyncButton, "VSyncButton"); + getWidget(mFPSButton, "FPSButton"); getWidget(mMasterVolumeSlider, "MasterVolume"); getWidget(mVoiceVolumeSlider, "VoiceVolume"); getWidget(mEffectsVolumeSlider, "EffectsVolume"); @@ -32,6 +48,8 @@ namespace MWGui mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); @@ -71,10 +89,9 @@ namespace MWGui mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1)); mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); - std::string on = mWindowManager.getGameSettingString("sOn", "On"); - std::string off = mWindowManager.getGameSettingString("sOff", "On"); - - mFullscreenButton->setCaption(Settings::Manager::getBool("fullscreen", "Video") ? on : off); + mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}"); + mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}"); + mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD"))); } void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) @@ -128,6 +145,20 @@ namespace MWGui if (_sender == mFullscreenButton) Settings::Manager::setBool("fullscreen", "Video", newState); + else if (_sender == mVSyncButton) + { + Settings::Manager::setBool("vsync", "Video", newState); + MWBase::Environment::get().getWindowManager()-> + messageBox("VSync will be applied after a restart", std::vector()); + } + } + + void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) + { + int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3; + Settings::Manager::setInt("fps", "HUD", newLevel); + mFPSButton->setCaptionWithReplacing(fpsLevelToStr(newLevel)); + apply(); } void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) @@ -155,6 +186,7 @@ namespace MWGui { const Settings::CategorySettingVector changed = Settings::Manager::apply(); MWBase::Environment::get().getWorld()->processChangedSettings(changed); - MWBase::Environment::get().getWorld()->processChangedSettings(changed); + MWBase::Environment::get().getSoundManager()->processChangedSettings(changed); + MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 62acc5649..79af03994 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -17,9 +17,14 @@ namespace MWGui protected: MyGUI::Button* mOkButton; + + MyGUI::ScrollBar* mMenuTransparencySlider; + + // graphics MyGUI::ListBox* mResolutionList; MyGUI::Button* mFullscreenButton; - MyGUI::ScrollBar* mMenuTransparencySlider; + MyGUI::Button* mVSyncButton; + MyGUI::Button* mFPSButton; MyGUI::ScrollBar* mViewDistanceSlider; // audio @@ -30,6 +35,7 @@ namespace MWGui MyGUI::ScrollBar* mMusicVolumeSlider; void onOkButtonClicked(MyGUI::Widget* _sender); + void onFpsToggled(MyGUI::Widget* _sender); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onButtonToggled(MyGUI::Widget* _sender); void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 6be712509..b71edc718 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -554,14 +554,6 @@ void WindowManager::toggleFogOfWar() hud->toggleFogOfWar(); } -int WindowManager::toggleFps() -{ - showFPSLevel = (showFPSLevel+1)%3; - hud->setFpsLevel(showFPSLevel); - Settings::Manager::setInt("fps", "HUD", showFPSLevel); - return showFPSLevel; -} - void WindowManager::setFocusObject(const MWWorld::Ptr& focus) { mToolTips->setFocusObject(focus); @@ -611,3 +603,8 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r else _result = _tag; } + +void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) +{ + hud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 9ccc42b1e..f585ac3ba 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -17,6 +17,7 @@ #include "MyGUI_UString.h" #include +#include #include #include @@ -182,9 +183,6 @@ namespace MWGui void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) bool getFullHelp() const; - int toggleFps(); - ///< toggle fps display @return resulting fps level - void setInteriorMapTexture(const int x, const int y); ///< set the index of the map texture that should be used (for interiors) @@ -215,6 +213,8 @@ namespace MWGui const ESMS::ESMStore& getStore() const; + void processChangedSettings(const Settings::CategorySettingVector& changed); + private: OEngine::GUI::MyGUIManager *mGuiManager; HUD *hud; diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 8fd6a9c6b..3ae1daadf 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -69,8 +69,6 @@ namespace MWInput A_ToggleWeapon, A_ToggleSpell, - A_ToggleFps, // Toggle FPS display (this is temporary) - A_Settings, // Temporary hotkey A_LAST // Marker for the last item @@ -95,11 +93,6 @@ namespace MWInput /* InputImpl Methods */ - void toggleFps() - { - windows.toggleFps(); - } - void toggleSpell() { if (windows.isGuiMode()) return; @@ -271,8 +264,6 @@ namespace MWInput "Draw Weapon"); disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this), "Ready hands"); - disp->funcs.bind(A_ToggleFps, boost::bind(&InputImpl::toggleFps, this), - "Toggle FPS display"); disp->funcs.bind(A_Settings, boost::bind(&InputImpl::showSettings, this), "Show settings window"); // Add the exit listener @@ -321,7 +312,6 @@ namespace MWInput disp->bind(A_ToggleWalk, KC_C); disp->bind(A_ToggleWeapon,KC_F); disp->bind(A_ToggleSpell,KC_R); - disp->bind(A_ToggleFps, KC_F10); disp->bind(A_Settings, KC_F2); // Key bindings for polled keys diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index dc1cbfa9e..9b5826765 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -68,25 +68,47 @@ - - - - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 57d834b14bcea471c335cf2581a0bb2c900ff33f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 12:05:43 +0200 Subject: [PATCH 28/76] fixed an issue with interactive messagebox --- apps/openmw/mwgui/messagebox.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 9a0671478..9df80476e 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -58,6 +58,7 @@ void MessageBoxManager::onFrame (float frameDuration) if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { delete mInterMessageBoxe; mInterMessageBoxe = NULL; + mWindowManager->popGuiMode(); } } From c0ee382c7211e027a22608cbf5194e4d7008bd5d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 May 2012 13:21:52 +0200 Subject: [PATCH 29/76] Issue #176: made actor deregistration more robust --- apps/openmw/mwmechanics/actors.cpp | 5 ++++- apps/openmw/mwmechanics/actors.hpp | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 5a17d50e4..8f8fd6871 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -71,7 +71,10 @@ namespace MWMechanics void Actors::removeActor (const MWWorld::Ptr& ptr) { - mActors.erase (ptr); + std::set::iterator iter = mActors.find (ptr); + + if (iter!=mActors.end()) + mActors.erase (iter); } void Actors::dropActors (const MWWorld::Ptr::CellStore *cellStore) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 30e73ccf7..1be29463f 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -32,6 +32,8 @@ namespace MWMechanics void removeActor (const MWWorld::Ptr& ptr); ///< Deregister an actor for stats management + /// + /// \note Ignored, if \a ptr is not a registered actor. void dropActors (const MWWorld::Ptr::CellStore *cellStore); ///< Deregister all actors in the given cell. From 684208dfc9eb457c20bd7c473e0a5c5993db5458 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 May 2012 13:26:07 +0200 Subject: [PATCH 30/76] Issue #176: when deleting objects, don't go through disable to remove actors from the mechanics manager --- apps/openmw/mwworld/world.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index c0107d9af..6d42560d2 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -553,16 +553,17 @@ namespace MWWorld { ptr.getRefData().setCount (0); + if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()) + { + MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); - if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()){ -// Class::get (ptr).disable (ptr, mEnvironment); /// \todo this line needs to be removed - MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); + MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); - mPhysics->removeObject (ptr.getRefData().getHandle()); - mRendering->removeObject(ptr); + mPhysics->removeObject (ptr.getRefData().getHandle()); + mRendering->removeObject(ptr); - mLocalScripts.remove (ptr); - } + mLocalScripts.remove (ptr); + } } } From 05fd8f0211967781ce0848c82d8138e3eb749eee Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 24 May 2012 05:30:22 -0700 Subject: [PATCH 31/76] Update the actual sounds and music volume when settings change --- apps/openmw/mwsound/soundmanager.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 27294ae77..ff618ac33 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -539,6 +539,30 @@ namespace MWSound mSFXVolume = Settings::Manager::getFloat("sfx volume", "Sound"); mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); + + SoundMap::iterator snditer = mActiveSounds.begin(); + while(snditer != mActiveSounds.end()) + { + if(snditer->second.second != "_say_sound") + { + float basevol = mMasterVolume * mSFXVolume; + float min, max; + lookup(snditer->second.second, basevol, min, max); + snditer->first->mBaseVolume = basevol; + } + else + { + float basevol = mMasterVolume * mVoiceVolume; + snditer->first->mBaseVolume = basevol; + } + snditer->first->update(); + snditer++; + } + if(mMusic) + { + mMusic->mBaseVolume = mMasterVolume * mMusicVolume; + mMusic->update(); + } } // Default readAll implementation, for decoders that can't do anything From a3a22e9096c1f055e20014690c359694c4033e59 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 14:47:57 +0200 Subject: [PATCH 32/76] ingredient tooltip shows possible effects --- apps/openmw/mwclass/ingredient.cpp | 13 ++ apps/openmw/mwclass/potion.cpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 6 +- apps/openmw/mwgui/tooltips.hpp | 9 +- apps/openmw/mwgui/widgets.cpp | 195 ++++++++++++++++++----------- apps/openmw/mwgui/widgets.hpp | 56 ++++++--- 6 files changed, 178 insertions(+), 103 deletions(-) diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index c0186da37..0c7fa7e69 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -135,6 +135,19 @@ namespace MWClass text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); } + MWGui::Widgets::SpellEffectList list; + for (int i=0; i<4; ++i) + { + if (ref->base->data.effectID[i] < 0) + continue; + MWGui::Widgets::SpellEffectParams params; + params.mEffectID = ref->base->data.effectID[i]; + params.mAttribute = ref->base->data.attributes[i]; + params.mSkill = ref->base->data.skills[i]; + list.push_back(params); + } + info.effects = list; + info.text = text; return info; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index ffc838639..157af01f5 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -132,7 +132,7 @@ namespace MWClass text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); - info.effects = &ref->base->effects; + info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->base->effects); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 3ade598ba..c61aa56a3 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -285,7 +285,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)), ((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight ); - if (info.effects != 0) + if (!info.effects.empty()) { Widget* effectArea = mDynamicToolTipBox->createWidget("", IntCoord(0, totalSize.height, 300, 300-totalSize.height), @@ -305,7 +305,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) effectsWidget->setEffectList(info.effects); std::vector effectItems; - effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, Widgets::MWEffectList::EF_Potion); + effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, Widgets::MWEffectList::EF_NoTarget); totalSize.height += coord.top-6; totalSize.width = std::max(totalSize.width, coord.width); } @@ -321,7 +321,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget ("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget"); enchantWidget->setWindowManager(mWindowManager); - enchantWidget->setEffectList(&enchant->effects); + enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->effects)); std::vector enchantEffectItems; int flag = (enchant->data.type == ESM::Enchantment::ConstantEffect) ? Widgets::MWEffectList::EF_Constant : 0; diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 4be0baff9..6d4a205d1 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -5,6 +5,8 @@ #include #include "../mwworld/ptr.hpp" +#include "widgets.hpp" + namespace MWGui { class WindowManager; @@ -13,11 +15,6 @@ namespace MWGui struct ToolTipInfo { public: - ToolTipInfo() : - effects(0) - { - }; - std::string caption; std::string text; std::string icon; @@ -26,7 +23,7 @@ namespace MWGui std::string enchant; // effects (for potions, ingredients) - const ESM::EffectList* effects; + Widgets::SpellEffectList effects; }; class ToolTips : public OEngine::GUI::Layout diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 0422bb0e2..2fd40b7c2 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -234,8 +234,17 @@ void MWSpell::createEffectWidgets(std::vector &effects, MyGUI: { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); effect->setWindowManager(mWindowManager); - effect->setFlags(flags); - effect->setSpellEffect(*it); + SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + params.mIsConstant = (flags & MWEffectList::EF_Constant); + params.mNoTarget = (flags & MWEffectList::EF_NoTarget); + effect->setSpellEffect(params); effects.push_back(effect); coord.top += effect->getHeight(); coord.width = std::max(coord.width, effect->getRequestedWidth()); @@ -274,7 +283,7 @@ MWEffectList::MWEffectList() { } -void MWEffectList::setEffectList(const ESM::EffectList* list) +void MWEffectList::setEffectList(const SpellEffectList& list) { mEffectList = list; updateWidgets(); @@ -283,25 +292,26 @@ void MWEffectList::setEffectList(const ESM::EffectList* list) void MWEffectList::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr 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 + // 2 steps: first, create all widgets and check their width.... MWSpellEffectPtr effect = nullptr; - std::vector::const_iterator end = mEffectList->list.end(); int maxwidth = coord.width; - for (std::vector::const_iterator it = mEffectList->list.begin(); it != end; ++it) + + for (SpellEffectList::iterator it=mEffectList.begin(); + it != mEffectList.end(); ++it) { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); effect->setWindowManager(mWindowManager); - effect->setFlags(flags); + it->mIsConstant = (flags & EF_Constant); + it->mNoTarget = (flags & EF_NoTarget); effect->setSpellEffect(*it); effects.push_back(effect); - if (effect->getRequestedWidth() > maxwidth) maxwidth = effect->getRequestedWidth(); coord.top += effect->getHeight(); } - // then adjust the size for all widgets + // ... then adjust the size for all widgets for (std::vector::iterator it = effects.begin(); it != effects.end(); ++it) { effect = static_cast(*it); @@ -334,6 +344,25 @@ MWEffectList::~MWEffectList() { } +SpellEffectList MWEffectList::effectListFromESM(const ESM::EffectList* effects) +{ + SpellEffectList result; + std::vector::const_iterator end = effects->list.end(); + for (std::vector::const_iterator it = effects->list.begin(); it != end; ++it) + { + SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + result.push_back(params); + } + return result; +} + /* MWSpellEffect */ MWSpellEffect::MWSpellEffect() @@ -341,13 +370,12 @@ MWSpellEffect::MWSpellEffect() , imageWidget(nullptr) , textWidget(nullptr) , mRequestedWidth(0) - , mFlags(0) { } -void MWSpellEffect::setSpellEffect(SpellEffectValue value) +void MWSpellEffect::setSpellEffect(const SpellEffectParams& params) { - effect = value; + mEffectParams = params; updateWidgets(); } @@ -357,74 +385,71 @@ void MWSpellEffect::updateWidgets() return; const ESMS::ESMStore &store = mWindowManager->getStore(); - const ESM::MagicEffect *magicEffect = store.magicEffects.search(effect.effectID); + const ESM::MagicEffect *magicEffect = store.magicEffects.search(mEffectParams.mEffectID); + if (!magicEffect) + return; if (textWidget) { - if (magicEffect) + std::string pt = mWindowManager->getGameSettingString("spoint", ""); + std::string pts = mWindowManager->getGameSettingString("spoints", ""); + std::string to = " " + mWindowManager->getGameSettingString("sTo", "") + " "; + std::string sec = " " + mWindowManager->getGameSettingString("ssecond", ""); + std::string secs = " " + mWindowManager->getGameSettingString("sseconds", ""); + + std::string effectIDStr = effectIDToString(mEffectParams.mEffectID); + std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, ""); + if (effectInvolvesSkill(effectIDStr) && mEffectParams.mSkill >= 0 && mEffectParams.mSkill < ESM::Skill::Length) { - std::string pt = mWindowManager->getGameSettingString("spoint", ""); - std::string pts = mWindowManager->getGameSettingString("spoints", ""); - std::string to = " " + mWindowManager->getGameSettingString("sTo", "") + " "; - std::string sec = " " + mWindowManager->getGameSettingString("ssecond", ""); - std::string secs = " " + mWindowManager->getGameSettingString("sseconds", ""); - - std::string effectIDStr = effectIDToString(effect.effectID); - std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, ""); - if (effect.skill >= 0 && effect.skill < ESM::Skill::Length) - { - spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[effect.skill], ""); - } - if (effect.attribute >= 0 && effect.attribute < 8) - { - static const char *attributes[8] = { - "sAttributeStrength", - "sAttributeIntelligence", - "sAttributeWillpower", - "sAttributeAgility", - "sAttributeSpeed", - "sAttributeEndurance", - "sAttributePersonality", - "sAttributeLuck" - }; - spellLine += " " + mWindowManager->getGameSettingString(attributes[effect.attribute], ""); - } - - if ((effect.magnMin >= 0 || effect.magnMax >= 0) && effectHasMagnitude(effectIDStr)) - { - if (effect.magnMin == effect.magnMax) - spellLine += " " + boost::lexical_cast(effect.magnMin) + " " + ((effect.magnMin == 1) ? pt : pts); - else - { - spellLine += " " + boost::lexical_cast(effect.magnMin) + to + boost::lexical_cast(effect.magnMax) + " " + pts; - } - } - - // constant effects have no duration and no target - if (!(mFlags & MWEffectList::EF_Constant)) - { - if (effect.duration >= 0 && effectHasDuration(effectIDStr)) - { - spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast(effect.duration) + ((effect.duration == 1) ? sec : secs); - } - - // potions have no target - if (!(mFlags & MWEffectList::EF_Potion)) - { - std::string on = mWindowManager->getGameSettingString("sonword", ""); - if (effect.range == ESM::RT_Self) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", ""); - else if (effect.range == ESM::RT_Touch) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", ""); - else if (effect.range == ESM::RT_Target) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", ""); - } - } - - static_cast(textWidget)->setCaption(spellLine); - mRequestedWidth = textWidget->getTextSize().width + 24; + spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[mEffectParams.mSkill], ""); } - else - static_cast(textWidget)->setCaption(""); + if (effectInvolvesAttribute(effectIDStr) && mEffectParams.mAttribute >= 0 && mEffectParams.mAttribute < 8) + { + static const char *attributes[8] = { + "sAttributeStrength", + "sAttributeIntelligence", + "sAttributeWillpower", + "sAttributeAgility", + "sAttributeSpeed", + "sAttributeEndurance", + "sAttributePersonality", + "sAttributeLuck" + }; + spellLine += " " + mWindowManager->getGameSettingString(attributes[mEffectParams.mAttribute], ""); + } + + if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && effectHasMagnitude(effectIDStr)) + { + if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + " " + ((mEffectParams.mMagnMin == 1) ? pt : pts); + else + { + spellLine += " " + boost::lexical_cast(mEffectParams.mMagnMin) + to + boost::lexical_cast(mEffectParams.mMagnMax) + " " + pts; + } + } + + // constant effects have no duration and no target + if (!mEffectParams.mIsConstant) + { + if (mEffectParams.mDuration >= 0 && effectHasDuration(effectIDStr)) + { + spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs); + } + + // potions have no target + if (!mEffectParams.mNoTarget) + { + std::string on = mWindowManager->getGameSettingString("sonword", ""); + if (mEffectParams.mRange == ESM::RT_Self) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", ""); + else if (mEffectParams.mRange == ESM::RT_Touch) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", ""); + else if (mEffectParams.mRange == ESM::RT_Target) + spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", ""); + } + } + + static_cast(textWidget)->setCaption(spellLine); + mRequestedWidth = textWidget->getTextSize().width + 24; } if (imageWidget) { @@ -677,6 +702,24 @@ bool MWSpellEffect::effectHasMagnitude(const std::string& effect) return (std::find(effectsWithoutMagnitude.begin(), effectsWithoutMagnitude.end(), effect) == effectsWithoutMagnitude.end()); } +bool MWSpellEffect::effectInvolvesAttribute (const std::string& effect) +{ + return (effect == "sEffectRestoreAttribute" + || effect == "sEffectAbsorbAttribute" + || effect == "sEffectDrainAttribute" + || effect == "sEffectFortifyAttribute" + || effect == "sEffectDamageAttribute"); +} + +bool MWSpellEffect::effectInvolvesSkill (const std::string& effect) +{ + return (effect == "sEffectRestoreSkill" + || effect == "sEffectAbsorbSkill" + || effect == "sEffectDrainSkill" + || effect == "sEffectFortifySkill" + || effect == "sEffectDamageSkill"); +} + MWSpellEffect::~MWSpellEffect() { } diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 6e230e2c6..54a278f1c 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -21,20 +21,40 @@ namespace MWGui namespace Widgets { + class MWEffectList; + void fixTexturePath(std::string &path); struct SpellEffectParams { - bool mHasTarget; // potion effects for example have no target (target is always the player) - bool mIsConstant; // constant effect means that duration will not be displayed - std::string effectID; + SpellEffectParams() + : mMagnMin(-1) + , mMagnMax(-1) + , mRange(-1) + , mDuration(-1) + , mSkill(-1) + , mAttribute(-1) + , mEffectID(-1) + , mNoTarget(false) + , mIsConstant(false) + { + } - // note that the ESM::MagicEffect (retrieved through effectID) might already store skill and attribute, - // in that case the ESM::MagicEffect skill/attribute is preferred. this is just here for ingredients which - // have them defined elsewhere. - signed char skill, attribute; + bool mNoTarget; // potion effects for example have no target (target is always the player) + bool mIsConstant; // constant effect means that duration will not be displayed + + // value of -1 here means the effect is unknown to the player + short mEffectID; + + // value of -1 here means there is no skill/attribute + signed char mSkill, mAttribute; + + // value of -1 here means the value is unavailable + int mMagnMin, mMagnMax, mRange, mDuration; }; + typedef std::vector SpellEffectList; + class MYGUI_EXPORT MWSkill : public Widget { MYGUI_RTTI_DERIVED( MWSkill ); @@ -120,6 +140,9 @@ namespace MWGui }; typedef MWAttribute* MWAttributePtr; + /** + * @todo remove this class and use MWEffectList instead + */ class MWSpellEffect; class MYGUI_EXPORT MWSpell : public Widget { @@ -167,12 +190,14 @@ namespace MWGui enum EffectFlags { - EF_Potion = 0x01, // potions have no target (target is always the player) + EF_NoTarget = 0x01, // potions have no target (target is always the player) EF_Constant = 0x02 // constant effect means that duration will not be displayed }; void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } - void setEffectList(const ESM::EffectList* list); + void setEffectList(const SpellEffectList& list); + + static SpellEffectList effectListFromESM(const ESM::EffectList* effects); /** * @param vector to store the created effect widgets @@ -192,7 +217,7 @@ namespace MWGui void updateWidgets(); WindowManager* mWindowManager; - const ESM::EffectList* mEffectList; + SpellEffectList mEffectList; }; typedef MWEffectList* MWEffectListPtr; @@ -205,14 +230,13 @@ namespace MWGui typedef ESM::ENAMstruct SpellEffectValue; void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } - void setSpellEffect(SpellEffectValue value); - void setFlags(int flags) { mFlags = flags; } + void setSpellEffect(const SpellEffectParams& params); std::string effectIDToString(const short effectID); bool effectHasMagnitude (const std::string& effect); bool effectHasDuration (const std::string& effect); - - const SpellEffectValue &getSpellEffect() const { return effect; } + bool effectInvolvesAttribute (const std::string& effect); + bool effectInvolvesSkill (const std::string& effect); int getRequestedWidth() const { return mRequestedWidth; } @@ -226,8 +250,7 @@ namespace MWGui void updateWidgets(); WindowManager* mWindowManager; - SpellEffectValue effect; - int mFlags; + SpellEffectParams mEffectParams; MyGUI::ImageBox* imageWidget; MyGUI::TextBox* textWidget; int mRequestedWidth; @@ -259,7 +282,6 @@ namespace MWGui MyGUI::TextBox* barTextWidget; }; typedef MWDynamicStat* MWDynamicStatPtr; - } } From c2b818373e075af0c3b8be49e9caacfa4e78d871 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 24 May 2012 15:11:45 +0200 Subject: [PATCH 33/76] adjust tooltip skin, now is never transparent --- apps/openmw/mwgui/tooltips.cpp | 8 +++---- files/mygui/openmw_hud_box.skin.xml | 37 +++++++++++++++++++++++++++++ files/mygui/openmw_tooltips.xml | 18 +++++++------- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 3ade598ba..49e68bd86 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -37,10 +37,10 @@ void ToolTips::setEnabled(bool enabled) void ToolTips::onFrame(float frameDuration) { - MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox); - mDynamicToolTipBox = mMainWidget->createWidget("HUD_Box", - IntCoord(0, 0, mMainWidget->getCoord().width, mMainWidget->getCoord().height), - Align::Stretch, "DynamicToolTipBox"); + while (mDynamicToolTipBox->getChildCount()) + { + MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox->getChildAt(0)); + } // start by hiding everything for (unsigned int i=0; i < mMainWidget->getChildCount(); ++i) diff --git a/files/mygui/openmw_hud_box.skin.xml b/files/mygui/openmw_hud_box.skin.xml index 86b63fcf6..ce231e5bb 100644 --- a/files/mygui/openmw_hud_box.skin.xml +++ b/files/mygui/openmw_hud_box.skin.xml @@ -38,4 +38,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index a1673d346..262fd2020 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -4,12 +4,12 @@ - + - + @@ -22,7 +22,7 @@ - + @@ -40,7 +40,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -78,7 +78,7 @@ - + @@ -98,7 +98,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -156,7 +156,7 @@ - + From 09c870ad68d79424eb089ab50c4cda569805a4af Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 12:58:28 +0200 Subject: [PATCH 34/76] first alchemy window layout (not pretty) --- apps/openmw/mwgui/alchemywindow.cpp | 27 +++++++ apps/openmw/mwgui/alchemywindow.hpp | 7 ++ files/mygui/openmw_alchemy_window_layout.xml | 80 ++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 570a1f6d4..90326c3d7 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -1,10 +1,37 @@ #include "alchemywindow.hpp" +#include "window_manager.hpp" + namespace MWGui { AlchemyWindow::AlchemyWindow(WindowManager& parWindowManager) : WindowBase("openmw_alchemy_window_layout.xml", parWindowManager) { + getWidget(mCreateButton, "CreateButton"); + getWidget(mCancelButton, "CancelButton"); + + + MyGUI::Widget* buttonBox = mCancelButton->getParent(); + int cancelButtonWidth = mCancelButton->getTextSize().width + 24; + mCancelButton->setCoord(buttonBox->getWidth() - cancelButtonWidth, + mCancelButton->getTop(), cancelButtonWidth, mCancelButton->getHeight()); + int createButtonWidth = mCreateButton->getTextSize().width + 24; + mCreateButton->setCoord(buttonBox->getWidth() - createButtonWidth - cancelButtonWidth - 4, + mCreateButton->getTop(), createButtonWidth, mCreateButton->getHeight()); + + mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked); + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked); + center(); } + + void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender) + { + mWindowManager.popGuiMode(); + mWindowManager.popGuiMode(); + } + + void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) + { + } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 37e50413b..d43bb6d33 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -9,6 +9,13 @@ namespace MWGui { public: AlchemyWindow(WindowManager& parWindowManager); + + protected: + MyGUI::Button* mCreateButton; + MyGUI::Button* mCancelButton; + + void onCancelButtonClicked(MyGUI::Widget* _sender); + void onCreateButtonClicked(MyGUI::Widget* _sender); }; } diff --git a/files/mygui/openmw_alchemy_window_layout.xml b/files/mygui/openmw_alchemy_window_layout.xml index c6c4b1caa..22511f013 100644 --- a/files/mygui/openmw_alchemy_window_layout.xml +++ b/files/mygui/openmw_alchemy_window_layout.xml @@ -3,6 +3,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6eb15f7680be9c48409cc5c0eeb1e7e413fe6b1d Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 15:24:33 +0200 Subject: [PATCH 35/76] auto-select the alchemy tools with highest quality --- apps/openmw/mwgui/alchemywindow.cpp | 173 ++++++++++++++++++++++++++ apps/openmw/mwgui/alchemywindow.hpp | 21 +++- apps/openmw/mwgui/container.cpp | 10 +- apps/openmw/mwgui/container.hpp | 6 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/window_base.cpp | 9 ++ apps/openmw/mwgui/window_base.hpp | 1 + apps/openmw/mwgui/window_manager.cpp | 3 - 9 files changed, 218 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 90326c3d7..60ad123a5 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -1,15 +1,46 @@ #include "alchemywindow.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/containerstore.hpp" + #include "window_manager.hpp" +namespace +{ + std::string getIconPath(MWWorld::Ptr ptr) + { + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(ptr).getInventoryIcon(ptr); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + return path; + } +} + namespace MWGui { AlchemyWindow::AlchemyWindow(WindowManager& parWindowManager) : WindowBase("openmw_alchemy_window_layout.xml", parWindowManager) + , ContainerBase(0) { getWidget(mCreateButton, "CreateButton"); getWidget(mCancelButton, "CancelButton"); + getWidget(mIngredient1, "Ingredient1"); + getWidget(mIngredient2, "Ingredient2"); + getWidget(mIngredient3, "Ingredient3"); + getWidget(mIngredient4, "Ingredient4"); + getWidget(mApparatus1, "Apparatus1"); + getWidget(mApparatus2, "Apparatus2"); + getWidget(mApparatus3, "Apparatus3"); + getWidget(mApparatus4, "Apparatus4"); + mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); + mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); + mIngredient3->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); + mIngredient4->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); MyGUI::Widget* buttonBox = mCancelButton->getParent(); int cancelButtonWidth = mCancelButton->getTextSize().width + 24; @@ -22,6 +53,12 @@ namespace MWGui mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked); + MyGUI::ScrollView* itemView; + MyGUI::Widget* containerWidget; + getWidget(containerWidget, "Items"); + getWidget(itemView, "ItemView"); + setWidgets(containerWidget, itemView); + center(); } @@ -34,4 +71,140 @@ namespace MWGui void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) { } + + void AlchemyWindow::open() + { + openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + setFilter(ContainerBase::Filter_Ingredients); + + // pick the best available apparatus + MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + MWWorld::Ptr bestAlbemic; + MWWorld::Ptr bestMortarPestle; + MWWorld::Ptr bestCalcinator; + MWWorld::Ptr bestRetort; + + for (MWWorld::ContainerStoreIterator it(store.begin(MWWorld::ContainerStore::Type_Apparatus)); + it != store.end(); ++it) + { + ESMS::LiveCellRef* ref = it->get(); + if (ref->base->data.type == ESM::Apparatus::Albemic + && (bestAlbemic.isEmpty() || ref->base->data.quality > bestAlbemic.get()->base->data.quality)) + bestAlbemic = *it; + else if (ref->base->data.type == ESM::Apparatus::MortarPestle + && (bestMortarPestle.isEmpty() || ref->base->data.quality > bestMortarPestle.get()->base->data.quality)) + bestMortarPestle = *it; + else if (ref->base->data.type == ESM::Apparatus::Calcinator + && (bestCalcinator.isEmpty() || ref->base->data.quality > bestCalcinator.get()->base->data.quality)) + bestCalcinator = *it; + else if (ref->base->data.type == ESM::Apparatus::Retort + && (bestRetort.isEmpty() || ref->base->data.quality > bestRetort.get()->base->data.quality)) + bestRetort = *it; + } + + if (!bestMortarPestle.isEmpty()) + { + mApparatus1->setUserString("ToolTipType", "ItemPtr"); + mApparatus1->setUserData(bestMortarPestle); + mApparatus1->setImageTexture(getIconPath(bestMortarPestle)); + } + if (!bestAlbemic.isEmpty()) + { + mApparatus2->setUserString("ToolTipType", "ItemPtr"); + mApparatus2->setUserData(bestAlbemic); + mApparatus2->setImageTexture(getIconPath(bestAlbemic)); + } + if (!bestCalcinator.isEmpty()) + { + mApparatus3->setUserString("ToolTipType", "ItemPtr"); + mApparatus3->setUserData(bestCalcinator); + mApparatus3->setImageTexture(getIconPath(bestCalcinator)); + } + if (!bestRetort.isEmpty()) + { + mApparatus4->setUserString("ToolTipType", "ItemPtr"); + mApparatus4->setUserData(bestRetort); + mApparatus4->setImageTexture(getIconPath(bestRetort)); + } + } + + void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender) + { + _sender->clearUserStrings(); + static_cast(_sender)->setImageTexture(""); + if (_sender->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(_sender->getChildAt(0)); + drawItems(); + update(); + } + + void AlchemyWindow::onSelectedItemImpl(MWWorld::Ptr item) + { + MyGUI::ImageBox* add = NULL; + + if (!mIngredient1->isUserString("ToolTipType")) + add = mIngredient1; + if (add == NULL && !mIngredient2->isUserString("ToolTipType")) + add = mIngredient2; + if (add == NULL && !mIngredient3->isUserString("ToolTipType")) + add = mIngredient3; + if (add == NULL && !mIngredient4->isUserString("ToolTipType")) + add = mIngredient4; + + if (add != NULL) + { + add->setUserString("ToolTipType", "ItemPtr"); + add->setUserData(item); + add->setImageTexture(getIconPath(item)); + drawItems(); + update(); + } + } + + std::vector AlchemyWindow::itemsToIgnore() + { + std::vector ignore; + // don't show ingredients that are currently selected in the "available ingredients" box. + if (mIngredient1->isUserString("ToolTipType")) + ignore.push_back(*mIngredient1->getUserData()); + if (mIngredient2->isUserString("ToolTipType")) + ignore.push_back(*mIngredient2->getUserData()); + if (mIngredient3->isUserString("ToolTipType")) + ignore.push_back(*mIngredient3->getUserData()); + if (mIngredient4->isUserString("ToolTipType")) + ignore.push_back(*mIngredient4->getUserData()); + + return ignore; + } + + void AlchemyWindow::update() + { + // update ingredient count labels + for (int i=0; i<4; ++i) + { + MyGUI::ImageBox* ingredient; + if (i==0) + ingredient = mIngredient1; + else if (i==1) + ingredient = mIngredient2; + else if (i==2) + ingredient = mIngredient3; + else if (i==3) + ingredient = mIngredient4; + + if (!ingredient->isUserString("ToolTipType")) + continue; + + if (ingredient->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); + + MyGUI::TextBox* text = ingredient->createWidget("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); + text->setTextAlign(MyGUI::Align::Right); + text->setNeedMouseFocus(false); + text->setTextShadow(true); + text->setTextShadowColour(MyGUI::Colour(0,0,0)); + text->setCaption(getCountString(ingredient->getUserData()->getRefData().getCount())); + } + } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index d43bb6d33..365ad9642 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -2,20 +2,39 @@ #define MWGUI_ALCHEMY_H #include "window_base.hpp" +#include "container.hpp" namespace MWGui { - class AlchemyWindow : public WindowBase + class AlchemyWindow : public WindowBase, public ContainerBase { public: AlchemyWindow(WindowManager& parWindowManager); + virtual void open(); + protected: MyGUI::Button* mCreateButton; MyGUI::Button* mCancelButton; + MyGUI::ImageBox* mIngredient1; + MyGUI::ImageBox* mIngredient2; + MyGUI::ImageBox* mIngredient3; + MyGUI::ImageBox* mIngredient4; + + MyGUI::ImageBox* mApparatus1; + MyGUI::ImageBox* mApparatus2; + MyGUI::ImageBox* mApparatus3; + MyGUI::ImageBox* mApparatus4; + void onCancelButtonClicked(MyGUI::Widget* _sender); void onCreateButtonClicked(MyGUI::Widget* _sender); + void onIngredientSelected(MyGUI::Widget* _sender); + + virtual void onSelectedItemImpl(MWWorld::Ptr item); + virtual std::vector itemsToIgnore(); + + void update(); }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 8ac876c07..6aabeb2c6 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -119,7 +119,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) else onContainerClicked(mContainerWidget); } - else + else if (isTrading()) { MWWorld::Ptr object = (*_sender->getUserData()); int count = object.getRefData().getCount(); @@ -179,6 +179,10 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) } } } + else + { + onSelectedItemImpl(*_sender->getUserData()); + } } void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) @@ -383,6 +387,8 @@ void ContainerBase::drawItems() + MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light + MWWorld::ContainerStore::Type_Apparatus; } + else if (mFilter == Filter_Ingredients) + categories = MWWorld::ContainerStore::Type_Ingredient; /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them @@ -514,6 +520,7 @@ void ContainerBase::drawItems() text->setNeedMouseFocus(false); text->setTextShadow(true); text->setTextShadowColour(MyGUI::Colour(0,0,0)); + text->setCaption(getCountString(displayCount)); y += 42; if (y > maxHeight) @@ -522,7 +529,6 @@ void ContainerBase::drawItems() y = 0; } - text->setCaption(getCountString(displayCount)); } } diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 66cac82ce..26e78149a 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -55,7 +55,9 @@ namespace MWGui Filter_Weapon = 0x02, Filter_Apparel = 0x03, Filter_Magic = 0x04, - Filter_Misc = 0x05 + Filter_Misc = 0x05, + + Filter_Ingredients = 0x06 }; enum ItemState @@ -116,6 +118,8 @@ namespace MWGui virtual bool isTrading() { return false; } + virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; } + virtual bool ignoreEquippedItems() { return false; } virtual std::vector itemsToIgnore() { return std::vector(); } }; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 59be6a495..04a30b69b 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -97,7 +97,7 @@ namespace MWGui openContainer(player); } - void InventoryWindow::openInventory() + void InventoryWindow::open() { updateEncumbranceBar(); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index fdb443829..86f7ee3c7 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -11,7 +11,7 @@ namespace MWGui public: InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); - void openInventory(); + virtual void open(); /// start trading, disables item drag&drop void startTrade(); diff --git a/apps/openmw/mwgui/window_base.cpp b/apps/openmw/mwgui/window_base.cpp index 1eb126a74..45206214b 100644 --- a/apps/openmw/mwgui/window_base.cpp +++ b/apps/openmw/mwgui/window_base.cpp @@ -13,6 +13,15 @@ void WindowBase::open() { } +void WindowBase::setVisible(bool visible) +{ + bool wasVisible = mMainWidget->getVisible(); + mMainWidget->setVisible(visible); + + if (!wasVisible && visible) + open(); +} + void WindowBase::center() { // Centre dialog diff --git a/apps/openmw/mwgui/window_base.hpp b/apps/openmw/mwgui/window_base.hpp index 99ddbe918..9cfdbe261 100644 --- a/apps/openmw/mwgui/window_base.hpp +++ b/apps/openmw/mwgui/window_base.hpp @@ -16,6 +16,7 @@ namespace MWGui typedef MyGUI::delegates::CMultiDelegate1 EventHandle_WindowBase; virtual void open(); + virtual void setVisible(bool visible); // calls open() if visible is true and was false before void center(); /** Event : Dialog finished, OK button clicked.\n diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index a29dd96a6..96469d105 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -269,20 +269,17 @@ void WindowManager::updateVisible() map -> setVisible( (eff & GW_Map) != 0 ); mStatsWindow -> setVisible( (eff & GW_Stats) != 0 ); mInventoryWindow->setVisible(true); - mInventoryWindow->openInventory(); break; } case GM_Container: mContainerWindow->setVisible(true); mInventoryWindow->setVisible(true); - mInventoryWindow->openInventory(); break; case GM_Dialogue: mDialogueWindow->setVisible(true); break; case GM_Barter: mInventoryWindow->setVisible(true); - mInventoryWindow->openInventory(); mTradeWindow->setVisible(true); break; case GM_InterMessageBox: From 1df1b521a4d06edd482f18a36b4410b13d2c9021 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 16:20:57 +0200 Subject: [PATCH 36/76] show the list of potion effects --- apps/openmw/mwgui/alchemywindow.cpp | 107 ++++++++++++++++++- apps/openmw/mwgui/alchemywindow.hpp | 4 + apps/openmw/mwgui/widgets.hpp | 7 ++ files/mygui/openmw_alchemy_window_layout.xml | 2 +- 4 files changed, 118 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 60ad123a5..c9548e05d 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -4,6 +4,7 @@ #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" #include "../mwworld/containerstore.hpp" +#include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" @@ -36,6 +37,7 @@ namespace MWGui getWidget(mApparatus2, "Apparatus2"); getWidget(mApparatus3, "Apparatus3"); getWidget(mApparatus4, "Apparatus4"); + getWidget(mEffectsBox, "CreatedEffects"); mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); @@ -143,6 +145,41 @@ namespace MWGui { MyGUI::ImageBox* add = NULL; + // don't allow to add an ingredient that is already added + // (which could happen if two similiar ingredients don't stack because of script / owner) + bool alreadyAdded = false; + std::string name = MWWorld::Class::get(item).getName(item); + if (mIngredient1->isUserString("ToolTipType")) + { + MWWorld::Ptr item2 = *mIngredient1->getUserData(); + std::string name2 = MWWorld::Class::get(item2).getName(item2); + if (name == name2) + alreadyAdded = true; + } + if (mIngredient2->isUserString("ToolTipType")) + { + MWWorld::Ptr item2 = *mIngredient2->getUserData(); + std::string name2 = MWWorld::Class::get(item2).getName(item2); + if (name == name2) + alreadyAdded = true; + } + if (mIngredient3->isUserString("ToolTipType")) + { + MWWorld::Ptr item2 = *mIngredient3->getUserData(); + std::string name2 = MWWorld::Class::get(item2).getName(item2); + if (name == name2) + alreadyAdded = true; + } + if (mIngredient4->isUserString("ToolTipType")) + { + MWWorld::Ptr item2 = *mIngredient4->getUserData(); + std::string name2 = MWWorld::Class::get(item2).getName(item2); + if (name == name2) + alreadyAdded = true; + } + if (alreadyAdded) + return; + if (!mIngredient1->isUserString("ToolTipType")) add = mIngredient1; if (add == NULL && !mIngredient2->isUserString("ToolTipType")) @@ -159,6 +196,9 @@ namespace MWGui add->setImageTexture(getIconPath(item)); drawItems(); update(); + + std::string sound = MWWorld::Class::get(item).getUpSoundId(item); + MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); } } @@ -180,7 +220,8 @@ namespace MWGui void AlchemyWindow::update() { - // update ingredient count labels + Widgets::SpellEffectList effects; + for (int i=0; i<4; ++i) { MyGUI::ImageBox* ingredient; @@ -196,6 +237,20 @@ namespace MWGui if (!ingredient->isUserString("ToolTipType")) continue; + // add the effects of this ingredient to list of effects + ESMS::LiveCellRef* ref = ingredient->getUserData()->get(); + for (int i=0; i<4; ++i) + { + if (ref->base->data.effectID[i] < 0) + continue; + MWGui::Widgets::SpellEffectParams params; + params.mEffectID = ref->base->data.effectID[i]; + params.mAttribute = ref->base->data.attributes[i]; + params.mSkill = ref->base->data.skills[i]; + effects.push_back(params); + } + + // update ingredient count labels if (ingredient->getChildCount()) MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); @@ -206,5 +261,55 @@ namespace MWGui text->setTextShadowColour(MyGUI::Colour(0,0,0)); text->setCaption(getCountString(ingredient->getUserData()->getRefData().getCount())); } + + // now remove effects that are only present once + Widgets::SpellEffectList::iterator it = effects.begin(); + while (it != effects.end()) + { + Widgets::SpellEffectList::iterator next = it; + ++next; + bool found = false; + for (; next != effects.end(); ++next) + { + if (*next == *it) + found = true; + } + + if (!found) + it = effects.erase(it); + else + ++it; + } + + // now remove duplicates + Widgets::SpellEffectList old = effects; + effects.clear(); + for (Widgets::SpellEffectList::iterator it = old.begin(); + it != old.end(); ++it) + { + bool found = false; + for (Widgets::SpellEffectList::iterator it2 = effects.begin(); + it2 != effects.end(); ++it2) + { + if (*it2 == *it) + found = true; + } + if (!found) + effects.push_back(*it); + } + mEffects = effects; + + while (mEffectsBox->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0)); + + MyGUI::IntCoord coord(0, 0, mEffectsBox->getWidth(), 24); + Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget + ("MW_StatName", coord, Align::Left | Align::Top); + effectsWidget->setWindowManager(&mWindowManager); + effectsWidget->setEffectList(effects); + + std::vector effectItems; + effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0); + effectsWidget->setCoord(coord); } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 365ad9642..17f363e92 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -27,6 +27,10 @@ namespace MWGui MyGUI::ImageBox* mApparatus3; MyGUI::ImageBox* mApparatus4; + MyGUI::Widget* mEffectsBox; + + Widgets::SpellEffectList mEffects; // effects of created potion + void onCancelButtonClicked(MyGUI::Widget* _sender); void onCreateButtonClicked(MyGUI::Widget* _sender); void onIngredientSelected(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 54a278f1c..c66bf5dd0 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -51,6 +51,13 @@ namespace MWGui // value of -1 here means the value is unavailable int mMagnMin, mMagnMax, mRange, mDuration; + + bool operator==(const SpellEffectParams& other) const + { + return (other.mEffectID == mEffectID + && other.mSkill == mSkill + && other.mAttribute == mAttribute); + } }; typedef std::vector SpellEffectList; diff --git a/files/mygui/openmw_alchemy_window_layout.xml b/files/mygui/openmw_alchemy_window_layout.xml index 22511f013..8eb5e1265 100644 --- a/files/mygui/openmw_alchemy_window_layout.xml +++ b/files/mygui/openmw_alchemy_window_layout.xml @@ -72,7 +72,7 @@ - + From 63b3b82657fb5a3c4d3782eaf3848ffd32c4258a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 16:23:49 +0200 Subject: [PATCH 37/76] don't allow more than 4 potion effects --- apps/openmw/mwgui/alchemywindow.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index c9548e05d..bd2f05289 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -281,9 +281,10 @@ namespace MWGui ++it; } - // now remove duplicates + // now remove duplicates, and don't allow more than 4 effects Widgets::SpellEffectList old = effects; effects.clear(); + int i=0; for (Widgets::SpellEffectList::iterator it = old.begin(); it != old.end(); ++it) { @@ -294,8 +295,11 @@ namespace MWGui if (*it2 == *it) found = true; } - if (!found) + if (!found && i<4) + { + ++i; effects.push_back(*it); + } } mEffects = effects; From 36885b2e4004bff3610b08ee283828b4d081b2fa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 May 2012 17:04:33 +0200 Subject: [PATCH 38/76] Issue #176: removed enable/disable functions from Creature, Npc and Light --- apps/openmw/mwclass/creature.cpp | 9 --------- apps/openmw/mwclass/creature.hpp | 6 ------ apps/openmw/mwclass/light.cpp | 6 ------ apps/openmw/mwclass/light.hpp | 5 ----- apps/openmw/mwclass/npc.cpp | 29 ++++++----------------------- apps/openmw/mwclass/npc.hpp | 6 ------ 6 files changed, 6 insertions(+), 55 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 653fabd08..e33fd322a 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -81,24 +81,15 @@ namespace MWClass ESMS::LiveCellRef *ref = ptr.get(); - const std::string &model = ref->base->model; assert (ref->base != NULL); if(!model.empty()){ physics.insertActorPhysics(ptr, "meshes\\" + model); } - } - void Creature::enable (const MWWorld::Ptr& ptr) const - { MWBase::Environment::get().getMechanicsManager()->addActor (ptr); } - void Creature::disable (const MWWorld::Ptr& ptr) const - { - MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); - } - std::string Creature::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 9d9491579..237f54e82 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -22,12 +22,6 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - - virtual void disable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index d9af2e73f..12ae517ef 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -55,12 +55,6 @@ namespace MWClass if(!model.empty()){ physics.insertObjectPhysics(ptr, "meshes\\" + model); } - } - - void Light::enable (const MWWorld::Ptr& ptr) const - { - ESMS::LiveCellRef *ref = - ptr.get(); if (!ref->base->sound.empty()) { diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 4f21a0f8e..cd963d842 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -14,11 +14,6 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - /// \attention This is not the same as the script instruction with the same name. References - /// should only be enabled while in an active cell. - virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index e7f6cc527..4c964c700 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -110,44 +110,27 @@ namespace MWClass void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - - renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr)); - } void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { - - ESMS::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); - std::string headID = ref->base->head; - std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); - bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; - + std::string headID = ref->base->head; + std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); + bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; std::string smodel = "meshes\\base_anim.nif"; - if(beast) - smodel = "meshes\\base_animkna.nif"; - physics.insertActorPhysics(ptr, smodel); + if(beast) + smodel = "meshes\\base_animkna.nif"; + physics.insertActorPhysics(ptr, smodel); - - } - - void Npc::enable (const MWWorld::Ptr& ptr) const - { MWBase::Environment::get().getMechanicsManager()->addActor (ptr); } - void Npc::disable (const MWWorld::Ptr& ptr) const - { - MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); - } - std::string Npc::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index ef154bad4..4cb733977 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -19,12 +19,6 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; - virtual void enable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - - virtual void disable (const MWWorld::Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part - virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. From 0131c53005e01fc2e5ab6b1ed3264e5dfe8a9b74 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 May 2012 17:28:27 +0200 Subject: [PATCH 39/76] Issue #176: removed enable/disable functions from MWWorld::Class --- apps/openmw/mwworld/class.cpp | 10 ---------- apps/openmw/mwworld/class.hpp | 10 ---------- apps/openmw/mwworld/scene.cpp | 15 +++++++++++++-- apps/openmw/mwworld/scene.hpp | 6 ++++++ apps/openmw/mwworld/world.cpp | 29 +++++++---------------------- 5 files changed, 26 insertions(+), 44 deletions(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 15bc405ce..fe39406fe 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -32,16 +32,6 @@ namespace MWWorld } - void Class::enable (const Ptr& ptr) const - { - - } - - void Class::disable (const Ptr& ptr) const - { - - } - MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const { throw std::runtime_error ("class does not have creature stats"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index a8f2aba17..46781d516 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -68,16 +68,6 @@ namespace MWWorld virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics) const; ///< Add reference into a cell for rendering (default implementation: don't render anything). - virtual void enable (const Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part (default implementation: ignore) - /// \attention This is not the same as the script instruction with the same name. References - /// should only be enabled while in an active cell. - - virtual void disable (const Ptr& ptr) const; - ///< Enable reference; only does the non-rendering part (default implementation: ignore) - /// \attention This is not the same as the script instruction with the same name. References - /// should only be enabled while in an active cell. - virtual std::string getName (const Ptr& ptr) const = 0; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 94f0c69a9..47238ee71 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -41,7 +41,6 @@ namespace { rendering.addObject(ptr); class_.insertObject(ptr, physics); - class_.enable (ptr); } catch (const std::exception& e) { @@ -459,8 +458,20 @@ namespace MWWorld mRendering.addObject(newPtr); MWWorld::Class::get(newPtr).insertObject(newPtr, *mPhysics); - MWWorld::Class::get(newPtr).enable(newPtr); } + void Scene::addObjectToScene (const Ptr& ptr) + { + mRendering.addObject (ptr); + MWWorld::Class::get (ptr).insertObject (ptr, *mPhysics); + } + + void Scene::removeObjectFromScene (const Ptr& ptr) + { + MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); + MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); + mPhysics->removeObject (ptr.getRefData().getHandle()); + mRendering.removeObject (ptr); + } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 857ee50d1..906580ff4 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -105,6 +105,12 @@ namespace MWWorld void insertObject(MWWorld::Ptr object, Ptr::CellStore* cell); void update (float duration); + + void addObjectToScene (const Ptr& ptr); + ///< Add an object that already exists in the world model to the scene. + + void removeObjectFromScene (const Ptr& ptr); + ///< Remove an object from the scene, but not from the world model. }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 6d42560d2..8f3d6c838 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -357,12 +357,8 @@ namespace MWWorld { reference.getRefData().enable(); - - //render->enable (reference.getRefData().getHandle()); - if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end()) - Class::get (reference).enable (reference); - - + if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end() && reference.getRefData().getCount()) + mWorldScene->addObjectToScene (reference); } } @@ -372,14 +368,8 @@ namespace MWWorld { reference.getRefData().disable(); - - //render->disable (reference.getRefData().getHandle()); - if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()){ - Class::get (reference).disable (reference); - MWBase::Environment::get().getSoundManager()->stopSound3D (reference); - } - - + if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end() && reference.getRefData().getCount()) + mWorldScene->removeObjectFromScene (reference); } } @@ -553,15 +543,10 @@ namespace MWWorld { ptr.getRefData().setCount (0); - if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()) + if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end() && + ptr.getRefData().isEnabled()) { - MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); - - MWBase::Environment::get().getSoundManager()->stopSound3D (ptr); - - mPhysics->removeObject (ptr.getRefData().getHandle()); - mRendering->removeObject(ptr); - + mWorldScene->removeObjectFromScene (ptr); mLocalScripts.remove (ptr); } } From 6fe53aa3205fa438895c76b7cab5f74e68e97f3b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 May 2012 17:55:00 +0200 Subject: [PATCH 40/76] Issue #277: containers in cells were not filled up on cell load when the cell was preloaded before --- apps/openmw/mwworld/cells.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 8c657a5c8..b6d3e38ce 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -78,8 +78,6 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) std::map, Ptr::CellStore>::iterator result = mExteriors.find (std::make_pair (x, y)); - bool fill = false; - if (result==mExteriors.end()) { const ESM::Cell *cell = mStore.cells.searchExt (x, y); @@ -100,15 +98,13 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) result = mExteriors.insert (std::make_pair ( std::make_pair (x, y), Ptr::CellStore (cell))).first; - - fill = true; } if (result->second.mState!=Ptr::CellStore::State_Loaded) + { result->second.load (mStore, mReader); - - if (fill) fillContainers (result->second); + } return &result->second; } @@ -117,22 +113,18 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name) { std::map::iterator result = mInteriors.find (name); - bool fill = false; - if (result==mInteriors.end()) { const ESM::Cell *cell = mStore.cells.findInt (name); result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; - - fill = true; } if (result->second.mState!=Ptr::CellStore::State_Loaded) + { result->second.load (mStore, mReader); - - if (fill) fillContainers (result->second); + } return &result->second; } From 750259973e13824836963753ef509fa36a76cd71 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 18:00:13 +0200 Subject: [PATCH 41/76] potion creating works, most of the values are bogus --- apps/openmw/mwgui/alchemywindow.cpp | 161 ++++++++++++++++++++++- apps/openmw/mwgui/alchemywindow.hpp | 4 + apps/openmw/mwgui/messagebox.cpp | 2 +- files/mygui/openmw_layers.xml | 1 + files/mygui/openmw_messagebox_layout.xml | 2 +- 5 files changed, 163 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index bd2f05289..4fdd6588f 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -1,8 +1,11 @@ #include "alchemywindow.hpp" +#include + #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" +#include "../mwworld/manualref.hpp" #include "../mwworld/containerstore.hpp" #include "../mwsound/soundmanager.hpp" @@ -38,6 +41,7 @@ namespace MWGui getWidget(mApparatus3, "Apparatus3"); getWidget(mApparatus4, "Apparatus4"); getWidget(mEffectsBox, "CreatedEffects"); + getWidget(mNameEdit, "NameEdit"); mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected); @@ -72,6 +76,145 @@ namespace MWGui void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) { + // check if mortar & pestle is available (always needed) + /// \todo check albemic, calcinator, retort (sometimes needed) + if (!mApparatus1->isUserString("ToolTipType")) + { + mWindowManager.messageBox("#{sNotifyMessage45}", std::vector()); + return; + } + + // make sure 2 or more ingredients were selected + int numIngreds = 0; + if (mIngredient1->isUserString("ToolTipType")) + ++numIngreds; + if (mIngredient2->isUserString("ToolTipType")) + ++numIngreds; + if (mIngredient3->isUserString("ToolTipType")) + ++numIngreds; + if (mIngredient4->isUserString("ToolTipType")) + ++numIngreds; + if (numIngreds < 2) + { + mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector()); + return; + } + + // make sure a name was entered + std::string name = mNameEdit->getCaption(); + boost::algorithm::trim(name); + if (name == "") + { + mWindowManager.messageBox("#{sNotifyMessage37}", std::vector()); + return; + } + + // if there are no created effects, the potion will always fail (but the ingredients won't be destroyed) + if (mEffects.empty()) + { + mWindowManager.messageBox("#{sNotifyMessage8}", std::vector()); + MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); + return; + } + + if (rand() % 2 == 0) /// \todo + { + ESM::Potion newPotion; + newPotion.name = mNameEdit->getCaption(); + ESM::EffectList effects; + for (unsigned int i=0; i<4; ++i) + { + if (mEffects.size() >= i+1) + { + ESM::ENAMstruct effect; + effect.effectID = mEffects[i].mEffectID; + effect.range = ESM::RT_Self; + effect.skill = mEffects[i].mSkill; + effect.attribute = mEffects[i].mAttribute; + effect.magnMin = 1; /// \todo + effect.magnMax = 10; /// \todo + effect.duration = 60; /// \todo + effects.list.push_back(effect); + } + } + + // UESP Wiki / Morrowind:Alchemy + // "The weight of a potion is an average of the weight of the ingredients, rounded down." + // note by scrawl: not rounding down here, I can't imagine a created potion to + // have 0 weight when using ingredients with 0.1 weight respectively + float weight = 0; + if (mIngredient1->isUserString("ToolTipType")) + weight += mIngredient1->getUserData()->get()->base->data.weight; + if (mIngredient2->isUserString("ToolTipType")) + weight += mIngredient2->getUserData()->get()->base->data.weight; + if (mIngredient3->isUserString("ToolTipType")) + weight += mIngredient3->getUserData()->get()->base->data.weight; + if (mIngredient4->isUserString("ToolTipType")) + weight += mIngredient4->getUserData()->get()->base->data.weight; + newPotion.data.weight = weight / float(numIngreds); + + newPotion.data.value = 100; /// \todo + newPotion.effects = effects; + // pick a random mesh and icon + std::vector names; + /// \todo is the mesh/icon dependent on alchemy skill? + names.push_back("standard"); + names.push_back("bargain"); + names.push_back("cheap"); + names.push_back("fresh"); + names.push_back("exclusive"); + names.push_back("quality"); + int random = rand() % names.size(); + newPotion.model = "m\\misc_potion_" + names[random ] + "_01.nif"; + newPotion.icon = "m\\tx_potion_" + names[random ] + "_01.dds"; + std::pair result = MWBase::Environment::get().getWorld()->createRecord(newPotion); + + // create a reference and add it to player inventory + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), result.first); + MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + ref.getPtr().getRefData().setCount(1); + store.add(ref.getPtr()); + + mWindowManager.messageBox("#{sPotionSuccess}", std::vector()); + MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f); + } + else + { + // potion failed + mWindowManager.messageBox("#{sNotifyMessage8}", std::vector()); + MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); + } + + // reduce count of the ingredients + if (mIngredient1->isUserString("ToolTipType")) + { + MWWorld::Ptr ingred = *mIngredient1->getUserData(); + ingred.getRefData().setCount(ingred.getRefData().getCount()-1); + if (ingred.getRefData().getCount() == 0) + removeIngredient(mIngredient1); + } + if (mIngredient2->isUserString("ToolTipType")) + { + MWWorld::Ptr ingred = *mIngredient2->getUserData(); + ingred.getRefData().setCount(ingred.getRefData().getCount()-1); + if (ingred.getRefData().getCount() == 0) + removeIngredient(mIngredient2); + } + if (mIngredient3->isUserString("ToolTipType")) + { + MWWorld::Ptr ingred = *mIngredient3->getUserData(); + ingred.getRefData().setCount(ingred.getRefData().getCount()-1); + if (ingred.getRefData().getCount() == 0) + removeIngredient(mIngredient3); + } + if (mIngredient4->isUserString("ToolTipType")) + { + MWWorld::Ptr ingred = *mIngredient4->getUserData(); + ingred.getRefData().setCount(ingred.getRefData().getCount()-1); + if (ingred.getRefData().getCount() == 0) + removeIngredient(mIngredient4); + } + update(); } void AlchemyWindow::open() @@ -133,10 +276,7 @@ namespace MWGui void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender) { - _sender->clearUserStrings(); - static_cast(_sender)->setImageTexture(""); - if (_sender->getChildCount()) - MyGUI::Gui::getInstance().destroyWidget(_sender->getChildAt(0)); + removeIngredient(_sender); drawItems(); update(); } @@ -292,7 +432,10 @@ namespace MWGui for (Widgets::SpellEffectList::iterator it2 = effects.begin(); it2 != effects.end(); ++it2) { - if (*it2 == *it) + // MW considers all "foritfy attribute" effects as the same effect. See the + // "Can't create multi-state boost potions" discussion on http://www.uesp.net/wiki/Morrowind_talk:Alchemy + // thus, we are only checking effectID here and not attribute or skill + if (it2->mEffectID == it->mEffectID) found = true; } if (!found && i<4) @@ -316,4 +459,12 @@ namespace MWGui effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0); effectsWidget->setCoord(coord); } + + void AlchemyWindow::removeIngredient(MyGUI::Widget* ingredient) + { + ingredient->clearUserStrings(); + static_cast(ingredient)->setImageTexture(""); + if (ingredient->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); + } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 17f363e92..e75597bcd 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -29,6 +29,8 @@ namespace MWGui MyGUI::Widget* mEffectsBox; + MyGUI::EditBox* mNameEdit; + Widgets::SpellEffectList mEffects; // effects of created potion void onCancelButtonClicked(MyGUI::Widget* _sender); @@ -38,6 +40,8 @@ namespace MWGui virtual void onSelectedItemImpl(MWWorld::Ptr item); virtual std::vector itemsToIgnore(); + void removeIngredient(MyGUI::Widget* ingredient); + void update(); }; } diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 9df80476e..0bb7d3c1c 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -161,7 +161,7 @@ MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::strin getWidget(mMessageWidget, "message"); mMessageWidget->setOverflowToTheLeft(true); - mMessageWidget->addText(cMessage); + mMessageWidget->setCaptionWithReplacing(cMessage); MyGUI::IntSize size; size.width = mFixedWidth; diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index a5044fb78..56f800ea3 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -7,6 +7,7 @@ + diff --git a/files/mygui/openmw_messagebox_layout.xml b/files/mygui/openmw_messagebox_layout.xml index c99c00a49..c5a7464ef 100644 --- a/files/mygui/openmw_messagebox_layout.xml +++ b/files/mygui/openmw_messagebox_layout.xml @@ -4,7 +4,7 @@ - + From c7010623fb419f928fb369b5e93cbcfe39c0e0c8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 25 May 2012 18:45:17 +0200 Subject: [PATCH 42/76] Issue #294: disallowed inventory prevents Talk, Open and Take actions --- apps/openmw/mwgui/window_manager.hpp | 5 +++++ apps/openmw/mwworld/actionopen.cpp | 3 +++ apps/openmw/mwworld/actiontake.cpp | 4 ++++ apps/openmw/mwworld/actiontalk.cpp | 5 ++++- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index c698047fe..f565c15fa 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -133,6 +133,11 @@ namespace MWGui updateVisible(); } + bool isAllowed(GuiWindow wnd) + { + return allowed & wnd; + } + MWGui::DialogueWindow* getDialogueWindow() {return mDialogueWindow;} MWGui::ContainerWindow* getContainerWindow() {return mContainerWindow;} MWGui::InventoryWindow* getInventoryWindow() {return mInventoryWindow;} diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index e2c8ec5cf..dd36487dc 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -16,6 +16,9 @@ namespace MWWorld void ActionOpen::execute () { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return; + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container); MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(mContainer); } diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp index 384cb3ffe..9cff42812 100644 --- a/apps/openmw/mwworld/actiontake.cpp +++ b/apps/openmw/mwworld/actiontake.cpp @@ -2,6 +2,7 @@ #include "actiontake.hpp" #include "../mwbase/environment.hpp" +#include "../mwgui/window_manager.hpp" #include "class.hpp" #include "world.hpp" @@ -13,6 +14,9 @@ namespace MWWorld void ActionTake::execute() { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return; + // insert into player's inventory MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPtr ("player", true); diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index b33b78832..b3b631653 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -2,7 +2,7 @@ #include "actiontalk.hpp" #include "../mwbase/environment.hpp" - +#include "../mwgui/window_manager.hpp" #include "../mwdialogue/dialoguemanager.hpp" namespace MWWorld @@ -11,6 +11,9 @@ namespace MWWorld void ActionTalk::execute() { + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + return; + MWBase::Environment::get().getDialogueManager()->startDialogue (mActor); } } From 3cba884f59488609172de97e062a175e186a6351 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 May 2012 05:46:46 +0200 Subject: [PATCH 43/76] Issue #294: show/hide HUD elements based on allowed windows --- apps/openmw/mwgui/window_manager.cpp | 10 ++++++++-- apps/openmw/mwgui/window_manager.hpp | 3 --- apps/openmw/mwgui/window_pinnable_base.hpp | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 96469d105..745ef16d4 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -222,6 +222,11 @@ void WindowManager::updateVisible() else mToolTips->enterGuiMode(); + setMinimapVisibility((allowed & GW_Map) && !map->pinned()); + setWeaponVisibility((allowed & GW_Inventory) && !mInventoryWindow->pinned()); + setSpellVisibility((allowed & GW_Magic)); /// \todo add pin state when spells window is implemented + setHMSVisibility((allowed & GW_Stats) && !mStatsWindow->pinned()); + // If in game mode, don't show anything. if (gameMode) return; @@ -560,12 +565,13 @@ bool WindowManager::getFullHelp() const void WindowManager::setWeaponVisibility(bool visible) { - hud->weapBox->setVisible(visible); + hud->setBottomLeftVisibility(hud->health->getVisible(), visible, hud->spellBox->getVisible()); } void WindowManager::setSpellVisibility(bool visible) { - hud->spellBox->setVisible(visible); + hud->setBottomLeftVisibility(hud->health->getVisible(), hud->weapBox->getVisible(), visible); + hud->setBottomRightVisibility(visible, hud->minimapBox->getVisible()); } void WindowManager::setMouseVisible(bool visible) diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index f565c15fa..e2fbd3e1e 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -263,9 +263,6 @@ namespace MWGui the start of the game, when windows are enabled one by one through script commands. You can manipulate this through using allow() and disableAll(). - - The setting should also affect visibility of certain HUD - elements, but this is not done yet. */ GuiWindow allowed; diff --git a/apps/openmw/mwgui/window_pinnable_base.hpp b/apps/openmw/mwgui/window_pinnable_base.hpp index 8ef38c386..86bc3b85c 100644 --- a/apps/openmw/mwgui/window_pinnable_base.hpp +++ b/apps/openmw/mwgui/window_pinnable_base.hpp @@ -12,6 +12,7 @@ namespace MWGui public: WindowPinnableBase(const std::string& parLayout, WindowManager& parWindowManager); void setVisible(bool b); + bool pinned() { return mPinned; } private: void onWindowButtonPressed(MyGUI::Window* sender, const std::string& eventName); From 313a8e55b7cea30dd4061fc507ee8606eff534b1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 May 2012 21:09:21 +0200 Subject: [PATCH 44/76] - Issue #296: Clicking on HUD elements shows/hides the respective window - Slightly redesigned the map window and minimap, the player arrow now isn't cut off at cell borders anymore --- apps/openmw/mwgui/hud.cpp | 64 ++++++------- apps/openmw/mwgui/hud.hpp | 6 +- apps/openmw/mwgui/map_window.cpp | 109 +++++++++++++++-------- apps/openmw/mwgui/map_window.hpp | 12 ++- apps/openmw/mwgui/window_manager.cpp | 6 +- apps/openmw/mwgui/window_manager.hpp | 6 ++ files/mygui/openmw_hud_layout.xml | 76 +++++----------- files/mygui/openmw_map_window_layout.xml | 42 +-------- 8 files changed, 154 insertions(+), 167 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 892bd6c7a..a3036cec4 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -48,25 +48,38 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(health, "Health"); getWidget(magicka, "Magicka"); getWidget(stamina, "Stamina"); + hmsBaseLeft = health->getLeft(); + MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame; + getWidget(healthFrame, "HealthFrame"); + getWidget(magickaFrame, "MagickaFrame"); + getWidget(fatigueFrame, "FatigueFrame"); + healthFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); + magickaFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); + fatigueFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); + // Item and spell images and status bars getWidget(weapBox, "WeapBox"); getWidget(weapImage, "WeapImage"); getWidget(weapStatus, "WeapStatus"); weapBoxBaseLeft = weapBox->getLeft(); + weapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWeaponClicked); getWidget(spellBox, "SpellBox"); getWidget(spellImage, "SpellImage"); getWidget(spellStatus, "SpellStatus"); spellBoxBaseLeft = spellBox->getLeft(); + spellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked); getWidget(effectBox, "EffectBox"); getWidget(effect1, "Effect1"); effectBoxBaseRight = effectBox->getRight(); + effectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked); getWidget(minimapBox, "MiniMapBox"); minimapBoxBaseRight = minimapBox->getRight(); + minimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked); getWidget(minimap, "MiniMap"); getWidget(compass, "Compass"); @@ -85,7 +98,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) setSpellStatus(65, 100); setEffect("icons\\s\\tx_s_chameleon.dds"); - LocalMapBase::init(minimap, this); + LocalMapBase::init(minimap, compass, this); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver); @@ -192,35 +205,6 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& v } } -void HUD::setPlayerDir(const float x, const float y) -{ - if (!minimapBox->getVisible() || (x == mLastPositionX && y == mLastPositionY)) return; - - MyGUI::ISubWidget* main = compass->getSubWidgetMain(); - MyGUI::RotatingSkin* rotatingSubskin = main->castType(); - rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); - float angle = std::atan2(x,y); - rotatingSubskin->setAngle(angle); - mLastPositionX = x; - mLastPositionY = y; -} - -void HUD::setPlayerPos(const float x, const float y) -{ - if (!minimapBox->getVisible() || (x == mLastDirectionX && y == mLastDirectionY)) return; - - MyGUI::IntSize size = minimap->getCanvasSize(); - MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); - MyGUI::IntCoord viewsize = minimap->getCoord(); - MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); - - minimap->setViewOffset(pos); - compass->setPosition(MyGUI::IntPoint(x*512-16, y*512-16)); - - mLastDirectionX = x; - mLastDirectionY = y; -} - void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible) { int weapDx = 0, spellDx = 0; @@ -320,3 +304,23 @@ void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) { MyGUI::PointerManager::getInstance().setPointer("arrow"); } + +void HUD::onHMSClicked(MyGUI::Widget* _sender) +{ + MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats); +} + +void HUD::onMapClicked(MyGUI::Widget* _sender) +{ + MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map); +} + +void HUD::onWeaponClicked(MyGUI::Widget* _sender) +{ + MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory); +} + +void HUD::onMagicClicked(MyGUI::Widget* _sender) +{ + MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 81f64ee50..924893351 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -21,8 +21,6 @@ namespace MWGui void setFPS(float fps); void setTriangleCount(size_t count); void setBatchCount(size_t count); - void setPlayerDir(const float x, const float y); - void setPlayerPos(const float x, const float y); void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible); void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); void setFpsLevel(const int level); @@ -53,5 +51,9 @@ namespace MWGui void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); + void onHMSClicked(MyGUI::Widget* _sender); + void onWeaponClicked(MyGUI::Widget* _sender); + void onMagicClicked(MyGUI::Widget* _sender); + void onMapClicked(MyGUI::Widget* _sender); }; } diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index a44571d0a..a51b66e2b 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -11,6 +11,7 @@ LocalMapBase::LocalMapBase() , mInterior(false) , mFogOfWar(true) , mLocalMap(NULL) + , mMapDragAndDrop(false) , mPrefix() , mChanged(true) , mLayout(NULL) @@ -18,13 +19,41 @@ LocalMapBase::LocalMapBase() , mLastPositionY(0.0f) , mLastDirectionX(0.0f) , mLastDirectionY(0.0f) + , mCompass(NULL) { } -void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout) +void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop) { mLocalMap = widget; mLayout = layout; + mMapDragAndDrop = mapDragAndDrop; + mCompass = compass; + + // create 3x3 map widgets, 512x512 each, holding a 1024x1024 texture each + const int widgetSize = 512; + for (int mx=0; mx<3; ++mx) + { + for (int my=0; my<3; ++my) + { + MyGUI::ImageBox* map = mLocalMap->createWidget("ImageBox", + MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize), + MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my)); + + MyGUI::ImageBox* fog = map->createWidget("ImageBox", + MyGUI::IntCoord(0, 0, widgetSize, widgetSize), + MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my) + "_fog"); + + if (!mMapDragAndDrop) + { + map->setNeedMouseFocus(false); + fog->setNeedMouseFocus(false); + } + + mMapWidgets.push_back(map); + mFogWidgets.push_back(fog); + } + } } void LocalMapBase::setCellPrefix(const std::string& prefix) @@ -47,10 +76,10 @@ void LocalMapBase::applyFogOfWar() { std::string name = "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my); + std::string image = mPrefix+"_"+ boost::lexical_cast(mCurX + (mx-1)) + "_" + boost::lexical_cast(mCurY + (mInterior ? (my-1) : -1*(my-1))); - MyGUI::ImageBox* fog; - mLayout->getWidget(fog, name+"_fog"); + MyGUI::ImageBox* fog = mFogWidgets[my + 3*mx]; fog->setImageTexture(mFogOfWar ? ((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog" : "black.png" ) @@ -66,14 +95,13 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior) { for (int my=0; my<3; ++my) { - std::string name = "Map_" + boost::lexical_cast(mx) + "_" - + boost::lexical_cast(my); - std::string image = mPrefix+"_"+ boost::lexical_cast(x + (mx-1)) + "_" + boost::lexical_cast(y + (interior ? (my-1) : -1*(my-1))); - MyGUI::ImageBox* box; - mLayout->getWidget(box, name); + std::string name = "Map_" + boost::lexical_cast(mx) + "_" + + boost::lexical_cast(my); + + MyGUI::ImageBox* box = mMapWidgets[my + 3*mx]; if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) box->setImageTexture(image); @@ -86,6 +114,42 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior) mCurY = y; mChanged = false; applyFogOfWar(); + + // set the compass texture again, because MyGUI determines sorting of ImageBox widgets + // based on the last setImageTexture call + std::string tex = "textures\\compass.dds"; + mCompass->setImageTexture(""); + mCompass->setImageTexture(tex); +} + + +void LocalMapBase::setPlayerPos(const float x, const float y) +{ + if (x == mLastPositionX && y == mLastPositionY) + return; + MyGUI::IntSize size = mLocalMap->getCanvasSize(); + MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); + MyGUI::IntCoord viewsize = mLocalMap->getCoord(); + MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); + mLocalMap->setViewOffset(pos); + + mCompass->setPosition(MyGUI::IntPoint(512+x*512-16, 512+y*512-16)); + mLastPositionX = x; + mLastPositionY = y; +} + +void LocalMapBase::setPlayerDir(const float x, const float y) +{ + if (x == mLastDirectionX && y == mLastDirectionY) + return; + MyGUI::ISubWidget* main = mCompass->getSubWidgetMain(); + MyGUI::RotatingSkin* rotatingSubskin = main->castType(); + rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); + float angle = std::atan2(x,y); + rotatingSubskin->setAngle(angle); + + mLastDirectionX = x; + mLastDirectionY = y; } // ------------------------------------------------------------------------------------------ @@ -111,7 +175,7 @@ MapWindow::MapWindow(WindowManager& parWindowManager) : eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); - LocalMapBase::init(mLocalMap, this); + LocalMapBase::init(mLocalMap, mPlayerArrow, this); } void MapWindow::setCellName(const std::string& cellName) @@ -119,33 +183,6 @@ void MapWindow::setCellName(const std::string& cellName) setTitle(cellName); } -void MapWindow::setPlayerPos(const float x, const float y) -{ - if (mGlobal || !mVisible || (x == mLastPositionX && y == mLastPositionY)) return; - MyGUI::IntSize size = mLocalMap->getCanvasSize(); - MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); - MyGUI::IntCoord viewsize = mLocalMap->getCoord(); - MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); - mLocalMap->setViewOffset(pos); - - mPlayerArrow->setPosition(MyGUI::IntPoint(x*512-16, y*512-16)); - mLastPositionX = x; - mLastPositionY = y; -} - -void MapWindow::setPlayerDir(const float x, const float y) -{ - if (!mVisible || (x == mLastDirectionX && y == mLastDirectionY)) return; - MyGUI::ISubWidget* main = mPlayerArrow->getSubWidgetMain(); - MyGUI::RotatingSkin* rotatingSubskin = main->castType(); - rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); - float angle = std::atan2(x,y); - rotatingSubskin->setAngle(angle); - - mLastDirectionX = x; - mLastDirectionY = y; -} - void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) { if (_id!=MyGUI::MouseButton::Left) return; diff --git a/apps/openmw/mwgui/map_window.hpp b/apps/openmw/mwgui/map_window.hpp index e7318f4e4..8d3392b82 100644 --- a/apps/openmw/mwgui/map_window.hpp +++ b/apps/openmw/mwgui/map_window.hpp @@ -9,10 +9,12 @@ namespace MWGui { public: LocalMapBase(); - void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout); + void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop=false); void setCellPrefix(const std::string& prefix); void setActiveCell(const int x, const int y, bool interior=false); + void setPlayerDir(const float x, const float y); + void setPlayerPos(const float x, const float y); void toggleFogOfWar(); @@ -20,14 +22,20 @@ namespace MWGui int mCurX, mCurY; bool mInterior; MyGUI::ScrollView* mLocalMap; + MyGUI::ImageBox* mCompass; std::string mPrefix; bool mChanged; bool mFogOfWar; + std::vector mMapWidgets; + std::vector mFogWidgets; + void applyFogOfWar(); OEngine::GUI::Layout* mLayout; + bool mMapDragAndDrop; + float mLastPositionX; float mLastPositionY; float mLastDirectionX; @@ -40,8 +48,6 @@ namespace MWGui MapWindow(WindowManager& parWindowManager); virtual ~MapWindow(){} - void setPlayerPos(const float x, const float y); - void setPlayerDir(const float x, const float y); void setCellName(const std::string& cellName); private: diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 745ef16d4..088e9c61e 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -271,9 +271,9 @@ void WindowManager::updateVisible() int eff = shown & allowed; // Show the windows we want - map -> setVisible( (eff & GW_Map) != 0 ); - mStatsWindow -> setVisible( (eff & GW_Stats) != 0 ); - mInventoryWindow->setVisible(true); + map -> setVisible( (eff & GW_Map) ); + mStatsWindow -> setVisible( (eff & GW_Stats) ); + mInventoryWindow->setVisible( (eff & GW_Inventory)); break; } case GM_Container: diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index e2fbd3e1e..df32547fc 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -119,6 +119,12 @@ namespace MWGui bool isGuiMode() const { return !mGuiModes.empty(); } + void toggleVisible(GuiWindow wnd) + { + shown = (shown & wnd) ? (GuiWindow) (shown & ~wnd) : (GuiWindow) (shown | wnd); + updateVisible(); + } + // Disallow all inventory mode windows void disallowAll() { diff --git a/files/mygui/openmw_hud_layout.xml b/files/mygui/openmw_hud_layout.xml index 0aabc3e3e..26c31793c 100644 --- a/files/mygui/openmw_hud_layout.xml +++ b/files/mygui/openmw_hud_layout.xml @@ -29,79 +29,49 @@ - + - + + + + + + + - - + - + + + + + - - - + + + - - - - - - + + + - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - diff --git a/files/mygui/openmw_map_window_layout.xml b/files/mygui/openmw_map_window_layout.xml index e0ae5bd88..63fd03b14 100644 --- a/files/mygui/openmw_map_window_layout.xml +++ b/files/mygui/openmw_map_window_layout.xml @@ -11,46 +11,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + From 63213b36bfdf162fe9fd3edaec8a2a9716c7c672 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 May 2012 23:06:15 +0200 Subject: [PATCH 45/76] Show a label on the HUD with the cell name when it changes (visible for a few seconds) - like Morrowind --- apps/openmw/mwgui/hud.cpp | 23 +++++++++++++++++++++++ apps/openmw/mwgui/hud.hpp | 8 ++++++++ apps/openmw/mwgui/window_manager.cpp | 4 ++++ files/mygui/openmw_hud_layout.xml | 8 ++++++++ 4 files changed, 43 insertions(+) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index a3036cec4..d3d7696b4 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -41,6 +41,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , effectBoxBaseRight(0) , minimapBoxBaseRight(0) , mDragAndDrop(dragAndDrop) + , mCellNameTimer(0.0f) + , mCellNameBox(NULL) { setCoord(0,0, width, height); @@ -83,6 +85,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(minimap, "MiniMap"); getWidget(compass, "Compass"); + getWidget(mCellNameBox, "CellName"); + getWidget(crosshair, "Crosshair"); setFpsLevel(fpsLevel); @@ -324,3 +328,22 @@ void HUD::onMagicClicked(MyGUI::Widget* _sender) { MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic); } + +void HUD::setCellName(const std::string& cellName) +{ + if (mCellName != cellName) + { + mCellNameTimer = 5.0f; + mCellName = cellName; + + mCellNameBox->setCaption(mCellName); + mCellNameBox->setVisible(true); + } +} + +void HUD::onFrame(float dt) +{ + mCellNameTimer -= dt; + if (mCellNameTimer < 0) + mCellNameBox->setVisible(false); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 924893351..f7131a39c 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -25,6 +25,10 @@ namespace MWGui void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); void setFpsLevel(const int level); + void onFrame(float dt); + + void setCellName(const std::string& cellName); + MyGUI::ProgressPtr health, magicka, stamina; MyGUI::Widget *weapBox, *spellBox; MyGUI::ImageBox *weapImage, *spellImage; @@ -34,6 +38,7 @@ namespace MWGui MyGUI::ScrollView* minimap; MyGUI::ImageBox* compass; MyGUI::ImageBox* crosshair; + MyGUI::TextBox* mCellNameBox; MyGUI::WidgetPtr fpsbox; MyGUI::TextBox* fpscounter; @@ -48,6 +53,9 @@ namespace MWGui DragAndDrop* mDragAndDrop; + std::string mCellName; + float mCellNameTimer; + 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/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 088e9c61e..acd0b089f 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -470,6 +470,8 @@ void WindowManager::onFrame (float frameDuration) mInventoryWindow->onFrame(); mStatsWindow->onFrame(); + + hud->onFrame(frameDuration); } const ESMS::ESMStore& WindowManager::getStore() const @@ -494,6 +496,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) } map->setCellName( name ); + hud->setCellName( name ); map->setCellPrefix("Cell"); hud->setCellPrefix("Cell"); @@ -503,6 +506,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) else { map->setCellName( cell->cell->name ); + hud->setCellName( cell->cell->name ); map->setCellPrefix( cell->cell->name ); hud->setCellPrefix( cell->cell->name ); } diff --git a/files/mygui/openmw_hud_layout.xml b/files/mygui/openmw_hud_layout.xml index 26c31793c..d0026bf25 100644 --- a/files/mygui/openmw_hud_layout.xml +++ b/files/mygui/openmw_hud_layout.xml @@ -59,6 +59,14 @@ name="Effect1"/> + + + + + + + + From a7e6a142f972ad102443f1eb0d4bff9ace4c59b6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 00:39:33 +0200 Subject: [PATCH 46/76] blend fog of war into adjacent cells --- apps/openmw/mwrender/localmap.cpp | 71 +++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index ea8902443..55cb45fdc 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -307,19 +307,19 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni // convert from world coordinates to texture UV coordinates float u,v; - std::string texName; + std::string texBaseName; if (!mInterior) { u = std::abs((pos.x - (sSize*x))/sSize); v = 1-std::abs((pos.y + (sSize*y))/sSize); - texName = "Cell_"+coordStr(x,y); + texBaseName = "Cell_"; } else { u = (pos.x - min.x - sSize*x)/sSize; v = (pos.y - min.y - sSize*y)/sSize; - texName = mInteriorName + "_" + coordStr(x,y); + texBaseName = mInteriorName + "_"; } MWBase::Environment::get().getWindowManager()->setPlayerPos(u, v); @@ -327,30 +327,57 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni // explore radius (squared) const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution; + const float exploreRadius = 0.1 * sFogOfWarResolution; // explore radius from 0 to sFogOfWarResolution + const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space) - // get the appropriate fog of war texture - TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog"); - if (!tex.isNull()) + int intExtMult = mInterior ? 1 : -1; // interior and exterior have reversed Y coordinates (interior: top to bottom) + + // change the affected fog of war textures (in a 3x3 grid around the player) + for (int mx = -1; mx<2; ++mx) { - // get its buffer - if (mBuffers.find(texName) == mBuffers.end()) return; - int i=0; - for (int texV = 0; texV> 24); - alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); - mBuffers[texName][i] = (uint32) (alpha << 24); - ++i; + // is this texture affected at all? + bool affected = false; + if (mx == 0 && my == 0) // the player is always in the center of the 3x3 grid + affected = true; + else + { + bool affectsX = (mx > 0)? (u + exploreRadiusUV > 1) : (u - exploreRadiusUV < 0); + bool affectsY = (my > 0)? (v + exploreRadiusUV > 1) : (v - exploreRadiusUV < 0); + affected = (affectsX && (my == 0)) || (affectsY && mx == 0) || (affectsX && affectsY); + } + + if (!affected) + continue; + + std::string texName = texBaseName + coordStr(x+mx,y+my*intExtMult); + + TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog"); + if (!tex.isNull()) + { + // get its buffer + if (mBuffers.find(texName) == mBuffers.end()) return; + int i=0; + for (int texV = 0; texV> 24); + alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); + mBuffers[texName][i] = (uint32) (alpha << 24); + + ++i; + } + } + + // copy to the texture + memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4); + tex->getBuffer()->unlock(); } } - - // copy to the texture - memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4); - tex->getBuffer()->unlock(); } } From f1d3978897b0e89f6f8f70128494c847d434d09c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 01:14:33 +0200 Subject: [PATCH 47/76] Issue #290: Auto-Close MW-reference related GUI windows --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/alchemywindow.cpp | 4 +-- apps/openmw/mwgui/alchemywindow.hpp | 2 ++ apps/openmw/mwgui/container.cpp | 27 ++++++++++-------- apps/openmw/mwgui/container.hpp | 16 +++++------ apps/openmw/mwgui/dialogue.cpp | 9 ++++-- apps/openmw/mwgui/dialogue.hpp | 7 +++-- apps/openmw/mwgui/inventorywindow.cpp | 8 +++--- apps/openmw/mwgui/inventorywindow.hpp | 2 ++ apps/openmw/mwgui/referenceinterface.cpp | 28 +++++++++++++++++++ apps/openmw/mwgui/referenceinterface.hpp | 29 ++++++++++++++++++++ apps/openmw/mwgui/tradewindow.cpp | 35 ++++++++++++++---------- apps/openmw/mwgui/tradewindow.hpp | 2 ++ apps/openmw/mwgui/window_manager.cpp | 18 ++++++++++++ apps/openmw/mwgui/window_manager.hpp | 1 + 15 files changed, 145 insertions(+), 45 deletions(-) create mode 100644 apps/openmw/mwgui/referenceinterface.cpp create mode 100644 apps/openmw/mwgui/referenceinterface.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index ac3882714..edbeab0a1 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -28,7 +28,7 @@ add_openmw_dir (mwgui dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list formatting inventorywindow container hud countdialog tradewindow settingswindow - confirmationdialog alchemywindow + confirmationdialog alchemywindow referenceinterface ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 4fdd6588f..50d209524 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -171,7 +171,7 @@ namespace MWGui // create a reference and add it to player inventory MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), result.first); - MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); ref.getPtr().getRefData().setCount(1); store.add(ref.getPtr()); @@ -223,7 +223,7 @@ namespace MWGui setFilter(ContainerBase::Filter_Ingredients); // pick the best available apparatus - MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::Ptr bestAlbemic; MWWorld::Ptr bestMortarPestle; diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index e75597bcd..c01a18e41 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -42,6 +42,8 @@ namespace MWGui void removeIngredient(MyGUI::Widget* ingredient); + virtual void onReferenceUnavailable() { ; } + void update(); }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6aabeb2c6..1cfbc1b2b 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -264,16 +264,16 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) if(mDragAndDrop->mIsOnDragAndDrop) //drop item here { MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData(); - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); if (mDragAndDrop->mDraggedFrom != this) { assert(object.getContainerStore() && "Item is not in a container!"); // check the container's Organic flag (if this is a container). container with Organic flag doesn't allow putting items inside - if (mContainer.getTypeName() == typeid(ESM::Container).name()) + if (mPtr.getTypeName() == typeid(ESM::Container).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->flags & ESM::Container::Organic) { // user notification @@ -288,13 +288,13 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) // check that we don't exceed the allowed weight (only for containers, not for inventory) if (!isInventory()) { - float capacity = MWWorld::Class::get(mContainer).getCapacity(mContainer); + float capacity = MWWorld::Class::get(mPtr).getCapacity(mPtr); // try adding the item, and if weight is exceeded, just remove it again. object.getRefData().setCount(mDragAndDrop->mDraggedCount); MWWorld::ContainerStoreIterator it = containerStore.add(object); - float curWeight = MWWorld::Class::get(mContainer).getEncumbrance(mContainer); + float curWeight = MWWorld::Class::get(mPtr).getEncumbrance(mPtr); if (curWeight > capacity) { it->getRefData().setCount(0); @@ -346,7 +346,7 @@ void ContainerBase::setFilter(ContainerBase::Filter filter) void ContainerBase::openContainer(MWWorld::Ptr container) { - mContainer = container; + mPtr = container; drawItems(); } @@ -356,7 +356,7 @@ void ContainerBase::drawItems() { MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0)); } - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); int x = 0; int y = 0; @@ -557,7 +557,7 @@ void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) void ContainerBase::addItem(MWWorld::Ptr item, int count) { - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); int origCount = item.getRefData().getCount(); @@ -569,7 +569,7 @@ void ContainerBase::addItem(MWWorld::Ptr item, int count) void ContainerBase::transferBoughtItems() { - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) { @@ -587,7 +587,7 @@ void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store) MWWorld::ContainerStore& ContainerBase::getContainerStore() { - MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); return store; } @@ -651,7 +651,7 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { // transfer everything into the player's inventory - MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player); @@ -676,3 +676,8 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) MWBase::Environment::get().getWindowManager()->popGuiMode(); } } + +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 26e78149a..5cd8167c2 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -2,15 +2,14 @@ #define MGUI_CONTAINER_H #include -#include "../mwclass/container.hpp" -#include -#include -#include -#include + #include "window_base.hpp" +#include "referenceinterface.hpp" + +#include "../mwclass/container.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/containerstore.hpp" -#include + namespace MWWorld { @@ -43,7 +42,7 @@ namespace MWGui int mDraggedCount; }; - class ContainerBase + class ContainerBase : public ReferenceInterface { public: ContainerBase(DragAndDrop* dragAndDrop); @@ -89,7 +88,6 @@ namespace MWGui MyGUI::Widget* mSelectedItem; DragAndDrop* mDragAndDrop; - MWWorld::Ptr mContainer; Filter mFilter; @@ -140,6 +138,8 @@ namespace MWGui void onWindowResize(MyGUI::Window* window); void onCloseButtonClicked(MyGUI::Widget* _sender); void onTakeAllButtonClicked(MyGUI::Widget* _sender); + + virtual void onReferenceUnavailable(); }; } #endif // CONTAINER_H diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 8a68ff666..ce687424c 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -125,7 +125,7 @@ void DialogueWindow::onSelectTopic(std::string topic) { /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? mWindowManager.pushGuiMode(GM_Barter); - mWindowManager.getTradeWindow()->startTrade(mActor); + mWindowManager.getTradeWindow()->startTrade(mPtr); } else @@ -135,7 +135,7 @@ void DialogueWindow::onSelectTopic(std::string topic) void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) { mEnabled = true; - mActor = actor; + mPtr = actor; topicsList->setEnabled(true); setTitle(npcName); @@ -260,3 +260,8 @@ void DialogueWindow::goodbye() topicsList->setEnabled(false); mEnabled = false; } + +void DialogueWindow::onReferenceUnavailable() +{ + mWindowManager.removeGuiMode(GM_Dialogue); +} diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index d3106ad38..8e9aba003 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -2,6 +2,7 @@ #define MWGUI_DIALOGE_H #include "window_base.hpp" +#include "referenceinterface.hpp" #include #include "../mwworld/ptr.hpp" @@ -25,7 +26,7 @@ namespace MWGui { class DialogueHistory; - class DialogueWindow: public WindowBase + class DialogueWindow: public WindowBase, public ReferenceInterface { public: DialogueWindow(WindowManager& parWindowManager); @@ -58,6 +59,8 @@ namespace MWGui void onMouseWheel(MyGUI::Widget* _sender, int _rel); void onWindowResize(MyGUI::Window* _sender); + virtual void onReferenceUnavailable(); + private: void updateOptions(); /** @@ -70,8 +73,6 @@ namespace MWGui bool mEnabled; - MWWorld::Ptr mActor; // actor being talked to - DialogueHistory* history; Widgets::MWList* topicsList; MyGUI::ProgressPtr pDispositionBar; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 04a30b69b..2b224ab2c 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -155,7 +155,7 @@ namespace MWGui if (mDragAndDrop->mDraggedFrom != this) { // add item to the player's inventory - MWWorld::ContainerStore& invStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::ContainerStoreIterator it = invStore.begin(); int origCount = ptr.getRefData().getCount(); @@ -192,7 +192,7 @@ namespace MWGui std::vector InventoryWindow::getEquippedItems() { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); std::vector items; @@ -210,7 +210,7 @@ namespace MWGui void InventoryWindow::_unequipItem(MWWorld::Ptr item) { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) { @@ -244,7 +244,7 @@ namespace MWGui int InventoryWindow::getPlayerGold() { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 86f7ee3c7..ecff75f10 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -48,6 +48,8 @@ namespace MWGui virtual bool isInventory() { return true; } virtual std::vector getEquippedItems(); virtual void _unequipItem(MWWorld::Ptr item); + + virtual void onReferenceUnavailable() { ; } }; } diff --git a/apps/openmw/mwgui/referenceinterface.cpp b/apps/openmw/mwgui/referenceinterface.cpp new file mode 100644 index 000000000..c6e710952 --- /dev/null +++ b/apps/openmw/mwgui/referenceinterface.cpp @@ -0,0 +1,28 @@ +#include "referenceinterface.hpp" + +#include "../mwworld/player.hpp" +#include "../mwworld/world.hpp" +#include "../mwbase/environment.hpp" + +namespace MWGui +{ + ReferenceInterface::ReferenceInterface() + : mCurrentPlayerCell(NULL) + { + } + + void ReferenceInterface::checkReferenceAvailable() + { + if (mPtr.isEmpty()) + return; + + MWWorld::Ptr::CellStore* playerCell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); + + // check if player has changed cell, or count of the reference has become 0 + if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL) + || mPtr.getRefData().getCount() == 0) + onReferenceUnavailable(); + + mCurrentPlayerCell = playerCell; + } +} diff --git a/apps/openmw/mwgui/referenceinterface.hpp b/apps/openmw/mwgui/referenceinterface.hpp new file mode 100644 index 000000000..40844b238 --- /dev/null +++ b/apps/openmw/mwgui/referenceinterface.hpp @@ -0,0 +1,29 @@ +#ifndef MWGUI_REFERENCEINTERFACE_H +#define MWGUI_REFERENCEINTERFACE_H + +#include "../mwworld/ptr.hpp" + +namespace MWGui +{ + /// \brief this class is intended for GUI interfaces that access an MW-Reference + /// for example dialogue window accesses an NPC, or Container window accesses a Container + /// these classes have to be automatically closed if the reference becomes unavailable + /// make sure that checkReferenceAvailable() is called every frame and that onReferenceUnavailable() has been overridden + class ReferenceInterface + { + public: + ReferenceInterface(); + + void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable + + protected: + virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable + + MWWorld::Ptr mPtr; + + private: + MWWorld::Ptr::CellStore* mCurrentPlayerCell; + }; +} + +#endif diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 311ea6c95..0a12a82a0 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -157,9 +157,9 @@ namespace MWGui // check if the merchant can afford this int merchantgold; - if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->npdt52.gold == -10) merchantgold = ref->base->npdt12.gold; else @@ -167,7 +167,7 @@ namespace MWGui } else // ESM::Creature { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); merchantgold = ref->base->data.gold; } if (mCurrentBalance > 0 && merchantgold < mCurrentBalance) @@ -218,7 +218,7 @@ namespace MWGui // i give you back your stuff! returnBoughtItems(mWindowManager.getInventoryWindow()->getContainerStore()); // now gimme back my stuff! - mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); + mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr)); mWindowManager.popGuiMode(); } @@ -240,9 +240,9 @@ namespace MWGui } int merchantgold; - if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->npdt52.gold == -10) merchantgold = ref->base->npdt12.gold; else @@ -250,7 +250,7 @@ namespace MWGui } else // ESM::Creature { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); merchantgold = ref->base->data.gold; } @@ -262,13 +262,13 @@ namespace MWGui { std::vector items; - if (mContainer.getTypeName() == typeid(ESM::Creature).name()) + if (mPtr.getTypeName() == typeid(ESM::Creature).name()) { // creatures don't have equipment slots. return items; } - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) { @@ -285,15 +285,15 @@ namespace MWGui bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item) { int services = 0; - if (mContainer.getTypeName() == typeid(ESM::NPC).name()) + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->hasAI) services = ref->base->AI.services; } - else if (mContainer.getTypeName() == typeid(ESM::Creature).name()) + else if (mPtr.getTypeName() == typeid(ESM::Creature).name()) { - ESMS::LiveCellRef* ref = mContainer.get(); + ESMS::LiveCellRef* ref = mPtr.get(); if (ref->base->hasAI) services = ref->base->AI.services; } @@ -327,7 +327,7 @@ namespace MWGui std::vector TradeWindow::itemsToIgnore() { std::vector items; - MWWorld::ContainerStore& invStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) @@ -356,4 +356,11 @@ namespace MWGui updateLabels(); } + + void TradeWindow::onReferenceUnavailable() + { + // remove both Trade and Dialogue (since you always trade with the NPC/creature that you have previously talked to) + mWindowManager.removeGuiMode(GM_Barter); + mWindowManager.removeGuiMode(GM_Dialogue); + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 8da96d37e..b391fd8fa 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -69,6 +69,8 @@ namespace MWGui virtual std::vector itemsToIgnore(); void updateLabels(); + + virtual void onReferenceUnavailable(); }; } diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index acd0b089f..a6d236136 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -472,6 +472,10 @@ void WindowManager::onFrame (float frameDuration) mStatsWindow->onFrame(); hud->onFrame(frameDuration); + + mDialogueWindow->checkReferenceAvailable(); + mTradeWindow->checkReferenceAvailable(); + mContainerWindow->checkReferenceAvailable(); } const ESMS::ESMStore& WindowManager::getStore() const @@ -626,3 +630,17 @@ void WindowManager::popGuiMode() updateVisible(); } + +void WindowManager::removeGuiMode(GuiMode mode) +{ + std::vector::iterator it = mGuiModes.begin(); + while (it != mGuiModes.end()) + { + if (*it == mode) + it = mGuiModes.erase(it); + else + ++it; + } + + updateVisible(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index df32547fc..7082cc0bc 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -109,6 +109,7 @@ namespace MWGui void pushGuiMode(GuiMode mode); void popGuiMode(); + void removeGuiMode(GuiMode mode); ///< can be anywhere in the stack GuiMode getMode() const { From 10cfe0f5bc37d08356dccb3a4d08589facda131e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 06:39:10 +0200 Subject: [PATCH 48/76] Issue #295: Class creation dialogs tooltips; plus tons of other improvements --- apps/openmw/mwgui/class.cpp | 129 +++++++++++-- apps/openmw/mwgui/class.hpp | 8 + apps/openmw/mwgui/race.cpp | 15 +- apps/openmw/mwgui/review.cpp | 52 ++++- apps/openmw/mwgui/review.hpp | 2 + apps/openmw/mwgui/stats_window.cpp | 79 +------- apps/openmw/mwgui/tooltips.cpp | 181 ++++++++++++++++++ apps/openmw/mwgui/tooltips.hpp | 9 + apps/openmw/mwgui/widgets.cpp | 4 +- components/esm/attr.cpp | 11 ++ components/esm/attr.hpp | 1 + files/mygui/openmw_chargen_class_layout.xml | 16 +- .../openmw_chargen_create_class_layout.xml | 14 +- ...w_chargen_generate_class_result_layout.xml | 4 +- files/mygui/openmw_chargen_race_layout.xml | 8 +- files/mygui/openmw_chargen_review_layout.xml | 75 +++++++- ...w_chargen_select_specialization_layout.xml | 6 +- files/mygui/openmw_infobox_layout.xml | 2 +- files/mygui/openmw_resources.xml | 29 +++ files/mygui/openmw_text.skin.xml | 41 ++-- files/mygui/openmw_tooltips.xml | 25 +++ 21 files changed, 565 insertions(+), 146 deletions(-) diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 3e41fa6b1..d3d261ab0 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -1,6 +1,4 @@ #include "class.hpp" -#include "window_manager.hpp" -#include "components/esm_store/store.hpp" #include #include @@ -8,6 +6,11 @@ #include #include +#include + +#include "window_manager.hpp" +#include "tooltips.hpp" + #undef min #undef max @@ -79,17 +82,13 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager) // Centre dialog center(); - setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(specializationName, "SpecializationName"); - setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); getWidget(favoriteAttribute[0], "FavoriteAttribute0"); getWidget(favoriteAttribute[1], "FavoriteAttribute1"); favoriteAttribute[0]->setWindowManager(&mWindowManager); favoriteAttribute[1]->setWindowManager(&mWindowManager); - setText("MajorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu3", "Major Skills:")); - setText("MinorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu4", "Minor Skills:")); for(int i = 0; i < 5; i++) { char theIndex = '0'+i; @@ -231,15 +230,21 @@ void PickClassDialog::updateStats() "sSpecializationMagic", "sSpecializationStealth" }; - specializationName->setCaption(mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization])); + std::string specName = mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization]); + specializationName->setCaption(specName); + ToolTips::createSpecializationToolTip(specializationName, specName, specialization); favoriteAttribute[0]->setAttributeId(klass->data.attribute[0]); favoriteAttribute[1]->setAttributeId(klass->data.attribute[1]); + ToolTips::createAttributeToolTip(favoriteAttribute[0], favoriteAttribute[0]->getAttributeId()); + ToolTips::createAttributeToolTip(favoriteAttribute[1], favoriteAttribute[1]->getAttributeId()); for (int i = 0; i < 5; ++i) { majorSkill[i]->setSkillNumber(klass->data.skills[i][0]); minorSkill[i]->setSkillNumber(klass->data.skills[i][1]); + ToolTips::createSkillToolTip(majorSkill[i], klass->data.skills[i][0]); + ToolTips::createSkillToolTip(minorSkill[i], klass->data.skills[i][1]); } classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds"); @@ -387,7 +392,6 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(specializationName, "SpecializationName"); - specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); specializationName->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked); setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); @@ -451,6 +455,9 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager) minorSkill[2]->setSkillId(ESM::Skill::Spear); minorSkill[3]->setSkillId(ESM::Skill::Athletics); minorSkill[4]->setSkillId(ESM::Skill::Enchant); + + setSpecialization(0); + update(); } CreateClassDialog::~CreateClassDialog() @@ -461,6 +468,18 @@ CreateClassDialog::~CreateClassDialog() delete descDialog; } +void CreateClassDialog::update() +{ + for (int i = 0; i < 5; ++i) + { + ToolTips::createSkillToolTip(majorSkill[i], majorSkill[i]->getSkillId()); + ToolTips::createSkillToolTip(minorSkill[i], minorSkill[i]->getSkillId()); + } + + ToolTips::createAttributeToolTip(favoriteAttribute0, favoriteAttribute0->getAttributeId()); + ToolTips::createAttributeToolTip(favoriteAttribute1, favoriteAttribute1->getAttributeId()); +} + std::string CreateClassDialog::getName() const { return editName->getOnlyText(); @@ -539,14 +558,25 @@ void CreateClassDialog::open() void CreateClassDialog::onDialogCancel() { if (specDialog) - specDialog->setVisible(false); + { + mWindowManager.removeDialog(specDialog); + specDialog = 0; + } if (attribDialog) - attribDialog->setVisible(false); + { + mWindowManager.removeDialog(attribDialog); + attribDialog = 0; + } if (skillDialog) - skillDialog->setVisible(false); + { + mWindowManager.removeDialog(skillDialog); + skillDialog = 0; + } if (descDialog) - descDialog->setVisible(false); - // TODO: Delete dialogs here + { + mWindowManager.removeDialog(descDialog); + descDialog = 0; + } } void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) @@ -562,8 +592,23 @@ void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) void CreateClassDialog::onSpecializationSelected() { specializationId = specDialog->getSpecializationId(); - specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[specializationId], "")); - specDialog->setVisible(false); + setSpecialization(specializationId); + + mWindowManager.removeDialog(specDialog); + specDialog = 0; +} + +void CreateClassDialog::setSpecialization(int id) +{ + specializationId = (ESM::Class::Specialization) id; + static const char *specIds[3] = { + "sSpecializationCombat", + "sSpecializationMagic", + "sSpecializationStealth" + }; + std::string specName = mWindowManager.getGameSettingString(specIds[specializationId], specIds[specializationId]); + specializationName->setCaption(specName); + ToolTips::createSpecializationToolTip(specializationName, specName, specializationId); } void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) @@ -592,7 +637,10 @@ void CreateClassDialog::onAttributeSelected() favoriteAttribute0->setAttributeId(favoriteAttribute1->getAttributeId()); } attribute->setAttributeId(id); - attribDialog->setVisible(false); + mWindowManager.removeDialog(attribDialog); + attribDialog = 0; + + update(); } void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) @@ -625,7 +673,9 @@ void CreateClassDialog::onSkillSelected() } skill->setSkillId(skillDialog->getSkillId()); - skillDialog->setVisible(false); + mWindowManager.removeDialog(skillDialog); + skillDialog = 0; + update(); } void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) @@ -640,6 +690,7 @@ void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow) { description = descDialog->getTextInput(); mWindowManager.removeDialog(descDialog); + descDialog = 0; } void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender) @@ -665,20 +716,35 @@ SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowM getWidget(specialization0, "Specialization0"); getWidget(specialization1, "Specialization1"); getWidget(specialization2, "Specialization2"); - specialization0->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); + std::string combat = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], ""); + std::string magic = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], ""); + std::string stealth = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], ""); + + specialization0->setCaption(combat); specialization0->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); - specialization1->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], "")); + specialization1->setCaption(magic); specialization1->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); - specialization2->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], "")); + specialization2->setCaption(stealth); specialization2->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); specializationId = ESM::Class::Combat; + ToolTips::createSpecializationToolTip(specialization0, combat, ESM::Class::Combat); + ToolTips::createSpecializationToolTip(specialization1, magic, ESM::Class::Magic); + ToolTips::createSpecializationToolTip(specialization2, stealth, ESM::Class::Stealth); + MyGUI::ButtonPtr cancelButton; getWidget(cancelButton, "CancelButton"); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(216 - buttonWidth, 90, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectSpecializationDialog::~SelectSpecializationDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -721,6 +787,7 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) attribute->setWindowManager(&parWindowManager); attribute->setAttributeId(ESM::Attribute::attributeIds[i]); attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked); + ToolTips::createAttributeToolTip(attribute, attribute->getAttributeId()); } MyGUI::ButtonPtr cancelButton; @@ -729,6 +796,13 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager) cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(186 - buttonWidth, 180, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectAttributeDialog::~SelectAttributeDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -810,6 +884,7 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) skills[spec][i].widget->setWindowManager(&mWindowManager); skills[spec][i].widget->setSkillId(skills[spec][i].skillId); skills[spec][i].widget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked); + ToolTips::createSkillToolTip(skills[spec][i].widget, skills[spec][i].widget->getSkillId()); } } @@ -819,6 +894,13 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); int buttonWidth = cancelButton->getTextSize().width + 24; cancelButton->setCoord(447 - buttonWidth, 218, buttonWidth, 21); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +SelectSkillDialog::~SelectSkillDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls @@ -853,6 +935,13 @@ DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager) // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit); + + MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget); +} + +DescriptionDialog::~DescriptionDialog() +{ + MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); } // widget controls diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 6f0138aa4..868052800 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -139,6 +139,7 @@ namespace MWGui { public: SelectSpecializationDialog(WindowManager& parWindowManager); + ~SelectSpecializationDialog(); ESM::Class::Specialization getSpecializationId() const { return specializationId; } @@ -169,6 +170,7 @@ namespace MWGui { public: SelectAttributeDialog(WindowManager& parWindowManager); + ~SelectAttributeDialog(); ESM::Attribute::AttributeID getAttributeId() const { return attributeId; } Widgets::MWAttributePtr getAffectedWidget() const { return affectedWidget; } @@ -201,6 +203,7 @@ namespace MWGui { public: SelectSkillDialog(WindowManager& parWindowManager); + ~SelectSkillDialog(); ESM::Skill::SkillEnum getSkillId() const { return skillId; } Widgets::MWSkillPtr getAffectedWidget() const { return affectedWidget; } @@ -236,6 +239,7 @@ namespace MWGui { public: DescriptionDialog(WindowManager& parWindowManager); + ~DescriptionDialog(); std::string getTextInput() const { return textEdit ? textEdit->getOnlyText() : ""; } void setTextInput(const std::string &text) { if (textEdit) textEdit->setOnlyText(text); } @@ -285,6 +289,10 @@ namespace MWGui void onDescriptionEntered(WindowBase* parWindow); void onDialogCancel(); + void setSpecialization(int id); + + void update(); + private: MyGUI::EditPtr editName; MyGUI::TextBox* specializationName; diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index f18bdb41f..dea365ac2 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -1,7 +1,4 @@ #include "race.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" -#include "components/esm_store/store.hpp" #include #include @@ -10,6 +7,12 @@ #include #include +#include + +#include "window_manager.hpp" +#include "widgets.hpp" +#include "tooltips.hpp" + using namespace MWGui; using namespace Widgets; @@ -51,7 +54,7 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager) prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace); nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace); - setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Hair")); + setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu4", "Change Hair")); getWidget(prevButton, "PrevHairButton"); getWidget(nextButton, "NextHairButton"); prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair); @@ -255,6 +258,8 @@ void RaceDialog::updateSkills() skillWidget->setWindowManager(&mWindowManager); skillWidget->setSkillNumber(skillId); skillWidget->setSkillValue(MWSkill::SkillValue(race->data.bonus[i].bonus)); + ToolTips::createSkillToolTip(skillWidget, skillId); + skillItems.push_back(skillWidget); @@ -288,6 +293,8 @@ void RaceDialog::updateSpellPowers() spellPowerWidget = spellPowerList->createWidget("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast(i)); spellPowerWidget->setWindowManager(&mWindowManager); spellPowerWidget->setSpellId(spellpower); + spellPowerWidget->setUserString("ToolTipType", "Spell"); + spellPowerWidget->setUserString("Spell", spellpower); spellPowerItems.push_back(spellPowerWidget); diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 5059efb34..be537e854 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -1,12 +1,15 @@ #include "review.hpp" -#include "window_manager.hpp" -#include "widgets.hpp" -#include "components/esm_store/store.hpp" + +#include #include #include -#include +#include + +#include "window_manager.hpp" +#include "widgets.hpp" +#include "tooltips.hpp" #undef min #undef max @@ -74,7 +77,7 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager) getWidget(skillAreaWidget, "Skills"); getWidget(skillClientWidget, "SkillClient"); getWidget(skillScrollerWidget, "SkillScroller"); - + skillClientWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &ReviewDialog::onScrollChangePosition); updateScroller(); @@ -137,13 +140,17 @@ void ReviewDialog::setRace(const std::string &raceId_) raceId = raceId_; const ESM::Race *race = mWindowManager.getStore().races.search(raceId); if (race) + { + ToolTips::createRaceToolTip(raceWidget, race); raceWidget->setCaption(race->name); + } } void ReviewDialog::setClass(const ESM::Class& class_) { klass = class_; classWidget->setCaption(klass.name); + ToolTips::createClassToolTip(classWidget, klass); } void ReviewDialog::setBirthSign(const std::string& signId) @@ -151,22 +158,31 @@ void ReviewDialog::setBirthSign(const std::string& signId) birthSignId = signId; const ESM::BirthSign *sign = mWindowManager.getStore().birthSigns.search(birthSignId); if (sign) + { birthSignWidget->setCaption(sign->name); + ToolTips::createBirthsignToolTip(birthSignWidget, birthSignId); + } } void ReviewDialog::setHealth(const MWMechanics::DynamicStat& value) { health->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + health->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); } void ReviewDialog::setMagicka(const MWMechanics::DynamicStat& value) { magicka->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + magicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); } void ReviewDialog::setFatigue(const MWMechanics::DynamicStat& value) { fatigue->setValue(value.getCurrent(), value.getModified()); + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + fatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); } void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat& value) @@ -219,6 +235,8 @@ void ReviewDialog::configureSkills(const std::vector& major, const std::vec void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::ImageBox* separator = skillClientWidget->createWidget("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default); + separator->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); + skillWidgets.push_back(separator); coord1.top += separator->getHeight(); @@ -228,6 +246,7 @@ void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2 void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) { MyGUI::TextBox* groupWidget = skillClientWidget->createWidget("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default); + groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); groupWidget->setCaption(label); skillWidgets.push_back(groupWidget); @@ -242,10 +261,12 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::st skillNameWidget = skillClientWidget->createWidget("SandText", coord1, MyGUI::Align::Default); skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillValueWidget = skillClientWidget->createWidget("SandTextRight", coord2, MyGUI::Align::Top | MyGUI::Align::Right); skillValueWidget->setCaption(value); skillValueWidget->_setWidgetState(state); + skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillWidgets.push_back(skillNameWidget); skillWidgets.push_back(skillValueWidget); @@ -262,6 +283,7 @@ void ReviewDialog::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGU skillNameWidget = skillClientWidget->createWidget("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); skillWidgets.push_back(skillNameWidget); @@ -297,6 +319,12 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId else if (modified < base) state = "decreased"; MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), state, coord1, coord2); + + for (int i=0; i<2; ++i) + { + ToolTips::createSkillToolTip(skillWidgets[skillWidgets.size()-1-i], skillId); + } + skillWidgetMap[skillId] = widget; } } @@ -330,6 +358,8 @@ void ReviewDialog::updateScroller() { skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0)); skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0)); + if (clientHeight != 0) + skillScrollerWidget->setTrackSize( (skillAreaWidget->getHeight() / float(clientHeight)) * skillScrollerWidget->getLineSize() ); } // widget controls @@ -363,3 +393,15 @@ void ReviewDialog::onBirthSignClicked(MyGUI::Widget* _sender) { eventActivateDialog(BIRTHSIGN_DIALOG); } + +void ReviewDialog::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (skillScrollerWidget->getScrollPosition() - _rel*0.3 < 0) + skillScrollerWidget->setScrollPosition(0); + else if (skillScrollerWidget->getScrollPosition() - _rel*0.3 > skillScrollerWidget->getScrollRange()-1) + skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollRange()-1); + else + skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollPosition() - _rel*0.3); + + onScrollChangePosition(skillScrollerWidget, skillScrollerWidget->getScrollPosition()); +} diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index 76ca5a2d7..bae4dc459 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -68,6 +68,8 @@ namespace MWGui void onClassClicked(MyGUI::Widget* _sender); void onBirthSignClicked(MyGUI::Widget* _sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + private: void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 54d9d7d4e..061800bf0 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -12,6 +12,7 @@ #include "../mwbase/environment.hpp" #include "window_manager.hpp" +#include "tooltips.hpp" using namespace MWGui; @@ -442,32 +443,17 @@ void StatsWindow::updateSkillArea() const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace()); MyGUI::Widget* raceWidget; getWidget(raceWidget, "RaceText"); - raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); - raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description); + ToolTips::createRaceToolTip(raceWidget, playerRace); getWidget(raceWidget, "Race_str"); - raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); - raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description); + ToolTips::createRaceToolTip(raceWidget, playerRace); // class tooltip MyGUI::Widget* classWidget; const ESM::Class& playerClass = MWBase::Environment::get().getWorld()->getPlayer().getClass(); - int spec = playerClass.data.specialization; - std::string specStr; - if (spec == 0) - specStr = "#{sSpecializationCombat}"; - else if (spec == 1) - specStr = "#{sSpecializationMagic}"; - else if (spec == 2) - specStr = "#{sSpecializationStealth}"; - getWidget(classWidget, "ClassText"); - classWidget->setUserString("Caption_ClassName", playerClass.name); - classWidget->setUserString("Caption_ClassDescription", playerClass.description); - classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + ToolTips::createClassToolTip(classWidget, playerClass); getWidget(classWidget, "Class_str"); - classWidget->setUserString("Caption_ClassName", playerClass.name); - classWidget->setUserString("Caption_ClassDescription", playerClass.description); - classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + ToolTips::createClassToolTip(classWidget, playerClass); if (!mFactions.empty()) { @@ -534,61 +520,8 @@ void StatsWindow::updateSkillArea() addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2); const ESM::BirthSign *sign = store.birthSigns.find(birthSignId); MyGUI::Widget* w = addItem(sign->name, coord1, coord2); - w->setUserString("ToolTipType", "Layout"); - w->setUserString("ToolTipLayout", "BirthSignToolTip"); - std::string image = sign->texture; - image.replace(image.size()-3, 3, "dds"); - w->setUserString("ImageTexture_BirthSignImage", "textures\\" + image); - std::string text; - text += sign->name; - text += "\n#BF9959" + sign->description; - - std::vector abilities, powers, spells; - - std::vector::const_iterator it = sign->powers.list.begin(); - std::vector::const_iterator end = sign->powers.list.end(); - for (; it != end; ++it) - { - const std::string &spellId = *it; - const ESM::Spell *spell = store.spells.search(spellId); - if (!spell) - continue; // Skip spells which cannot be found - ESM::Spell::SpellType type = static_cast(spell->data.type); - if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power) - continue; // We only want spell, ability and powers. - - if (type == ESM::Spell::ST_Ability) - abilities.push_back(spellId); - else if (type == ESM::Spell::ST_Power) - powers.push_back(spellId); - else if (type == ESM::Spell::ST_Spell) - spells.push_back(spellId); - } - - struct{ const std::vector &spells; std::string label; } categories[3] = { - {abilities, "sBirthsignmenu1"}, - {powers, "sPowers"}, - {spells, "sBirthsignmenu2"} - }; - - for (int category = 0; category < 3; ++category) - { - for (std::vector::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it) - { - if (it == categories[category].spells.begin()) - { - text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}"; - } - - const std::string &spellId = *it; - - const ESM::Spell *spell = store.spells.search(spellId); - text += "\n#BF9959" + spell->name; - } - } - - w->setUserString("Caption_BirthSignText", text); + ToolTips::createBirthsignToolTip(w, birthSignId); } // Add a line separator if there are items above diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index e21c88646..c6d8e2c8c 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -65,6 +65,17 @@ void ToolTips::onFrame(float frameDuration) IntSize tooltipSize; + // try to go 1 level up until there is a widget that has tooltip + // this is necessary because some skin elements are actually separate widgets + int i=0; + while (!focus->isUserString("ToolTipType")) + { + focus = focus->getParent(); + if (!focus) + return; + ++i; + } + std::string type = focus->getUserString("ToolTipType"); std::string text = focus->getUserString("ToolTipText"); @@ -78,6 +89,29 @@ void ToolTips::onFrame(float frameDuration) mFocusObject = *focus->getUserData(); tooltipSize = getToolTipViaPtr(false); } + else if (type == "Spell") + { + ToolTipInfo info; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); + info.caption = spell->name; + Widgets::SpellEffectList effects; + std::vector::const_iterator end = spell->effects.list.end(); + for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + { + Widgets::SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); + effects.push_back(params); + } + info.effects = effects; + tooltipSize = createToolTip(info); + } else if (type == "Layout") { // tooltip defined in the layout @@ -440,3 +474,150 @@ void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, mFocusToolTipX = (min_x + max_x) / 2; mFocusToolTipY = min_y; } + +void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId) +{ + if (skillId == -1) + return; + + const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId]; + const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().skills.search(skillId); + assert(skill); + const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(skill->data.attribute); + assert(attr); + std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); + widget->setUserString("Caption_SkillNoProgressName", "#{"+skillNameId+"}"); + widget->setUserString("Caption_SkillNoProgressDescription", skill->description); + widget->setUserString("Caption_SkillNoProgressAttribute", "#{sGoverningAttribute}: #{" + attr->name + "}"); + widget->setUserString("ImageTexture_SkillNoProgressImage", icon); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); + widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip"); +} + +void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId) +{ + if (attributeId == -1) + return; + + const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(attributeId); + assert(attr); + std::string icon = ESM::Attribute::attributeIcons[attributeId]; + std::string name = ESM::Attribute::gmstAttributeIds[attributeId]; + std::string desc = ESM::Attribute::gmstAttributeDescIds[attributeId]; + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "AttributeToolTip"); + widget->setUserString("Caption_AttributeName", "#{"+name+"}"); + widget->setUserString("Caption_AttributeDescription", "#{"+desc+"}"); + widget->setUserString("ImageTexture_AttributeImage", icon); +} + +void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId) +{ + widget->setUserString("Caption_CenteredCaption", name); + std::string specText; + // get all skills of this specialisation + std::map skills = MWBase::Environment::get().getWorld()->getStore().skills.list; + for (std::map::const_iterator it = skills.begin(); + it != skills.end(); ++it) + { + if (it->second.data.specialization == specId) + specText += std::string("\n#{") + ESM::Skill::sSkillNameIds[it->second.index] + "}"; + } + widget->setUserString("Caption_CenteredCaptionText", specText); + widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); + widget->setUserString("ToolTipType", "Layout"); +} + +void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId) +{ + const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.find(birthsignId); + + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "BirthSignToolTip"); + std::string image = sign->texture; + image.replace(image.size()-3, 3, "dds"); + widget->setUserString("ImageTexture_BirthSignImage", "textures\\" + image); + std::string text; + + text += sign->name; + text += "\n#BF9959" + sign->description; + + std::vector abilities, powers, spells; + + std::vector::const_iterator it = sign->powers.list.begin(); + std::vector::const_iterator end = sign->powers.list.end(); + for (; it != end; ++it) + { + const std::string &spellId = *it; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId); + if (!spell) + continue; // Skip spells which cannot be found + ESM::Spell::SpellType type = static_cast(spell->data.type); + if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power) + continue; // We only want spell, ability and powers. + + if (type == ESM::Spell::ST_Ability) + abilities.push_back(spellId); + else if (type == ESM::Spell::ST_Power) + powers.push_back(spellId); + else if (type == ESM::Spell::ST_Spell) + spells.push_back(spellId); + } + + struct{ const std::vector &spells; std::string label; } categories[3] = { + {abilities, "sBirthsignmenu1"}, + {powers, "sPowers"}, + {spells, "sBirthsignmenu2"} + }; + + for (int category = 0; category < 3; ++category) + { + for (std::vector::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it) + { + if (it == categories[category].spells.begin()) + { + text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}"; + } + + const std::string &spellId = *it; + + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId); + text += "\n#BF9959" + spell->name; + } + } + + widget->setUserString("Caption_BirthSignText", text); +} + +void ToolTips::createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace) +{ + widget->setUserString("Caption_CenteredCaption", playerRace->name); + widget->setUserString("Caption_CenteredCaptionText", playerRace->description); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); +} + +void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass) +{ + if (playerClass.name == "") + return; + + int spec = playerClass.data.specialization; + std::string specStr; + if (spec == 0) + specStr = "#{sSpecializationCombat}"; + else if (spec == 1) + specStr = "#{sSpecializationMagic}"; + else if (spec == 2) + specStr = "#{sSpecializationStealth}"; + + widget->setUserString("Caption_ClassName", playerClass.name); + widget->setUserString("Caption_ClassDescription", playerClass.description); + widget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); + widget->setUserString("ToolTipType", "Layout"); + widget->setUserString("ToolTipLayout", "ClassToolTip"); +} diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 6d4a205d1..1925a4f14 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -57,6 +57,15 @@ namespace MWGui static std::string getCountString(const int value); ///< @return blank string if count is 1, or else " (value)" + // these do not create an actual tooltip, but they fill in the data that is required so the tooltip + // system knows what to show in case this widget is hovered + static void createSkillToolTip(MyGUI::Widget* widget, int skillId); + static void createAttributeToolTip(MyGUI::Widget* widget, int attributeId); + static void createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId); + static void createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId); + static void createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace); + static void createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass); + private: MyGUI::Widget* mDynamicToolTipBox; diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 2fd40b7c2..b85074805 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -301,8 +301,8 @@ void MWEffectList::createEffectWidgets(std::vector &effects, M { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); effect->setWindowManager(mWindowManager); - it->mIsConstant = (flags & EF_Constant); - it->mNoTarget = (flags & EF_NoTarget); + it->mIsConstant = (flags & EF_Constant) || it->mIsConstant; + it->mNoTarget = (flags & EF_NoTarget) || it->mNoTarget; effect->setSpellEffect(*it); effects.push_back(effect); if (effect->getRequestedWidth() > maxwidth) diff --git a/components/esm/attr.cpp b/components/esm/attr.cpp index 8c410e57a..b077ef499 100644 --- a/components/esm/attr.cpp +++ b/components/esm/attr.cpp @@ -34,3 +34,14 @@ const std::string Attribute::gmstAttributeDescIds[Attribute::Length] = { "sPerDesc", "sLucDesc" }; + +const std::string Attribute::attributeIcons[Attribute::Length] = { + "icons\\k\\attribute_strength.dds", + "icons\\k\\attribute_int.dds", + "icons\\k\\attribute_wilpower.dds", + "icons\\k\\attribute_agility.dds", + "icons\\k\\attribute_speed.dds", + "icons\\k\\attribute_endurance.dds", + "icons\\k\\attribute_personality.dds", + "icons\\k\\attribute_luck.dds" +}; diff --git a/components/esm/attr.hpp b/components/esm/attr.hpp index 183fb9e0e..620683dbb 100644 --- a/components/esm/attr.hpp +++ b/components/esm/attr.hpp @@ -30,6 +30,7 @@ struct Attribute static const AttributeID attributeIds[Length]; static const std::string gmstAttributeIds[Length]; static const std::string gmstAttributeDescIds[Length]; + static const std::string attributeIcons[Length]; Attribute(AttributeID id, const std::string &name, const std::string &description) : id(id) diff --git a/files/mygui/openmw_chargen_class_layout.xml b/files/mygui/openmw_chargen_class_layout.xml index 38fa606ab..613143d54 100644 --- a/files/mygui/openmw_chargen_class_layout.xml +++ b/files/mygui/openmw_chargen_class_layout.xml @@ -14,8 +14,11 @@ - + + + + @@ -23,16 +26,19 @@ - + + + + - + @@ -42,7 +48,7 @@ - + @@ -58,7 +64,7 @@ - + diff --git a/files/mygui/openmw_chargen_create_class_layout.xml b/files/mygui/openmw_chargen_create_class_layout.xml index be6a10e0c..dde74a6a2 100644 --- a/files/mygui/openmw_chargen_create_class_layout.xml +++ b/files/mygui/openmw_chargen_create_class_layout.xml @@ -12,17 +12,23 @@ - + + + + - + - + + + + @@ -59,7 +65,7 @@ - + diff --git a/files/mygui/openmw_chargen_generate_class_result_layout.xml b/files/mygui/openmw_chargen_generate_class_result_layout.xml index 9a6ed4f2e..1cef9c9ce 100644 --- a/files/mygui/openmw_chargen_generate_class_result_layout.xml +++ b/files/mygui/openmw_chargen_generate_class_result_layout.xml @@ -9,10 +9,10 @@ - + @@ -24,7 +24,7 @@ - + diff --git a/files/mygui/openmw_chargen_race_layout.xml b/files/mygui/openmw_chargen_race_layout.xml index a9b072f5e..df0d29f78 100644 --- a/files/mygui/openmw_chargen_race_layout.xml +++ b/files/mygui/openmw_chargen_race_layout.xml @@ -17,27 +17,23 @@ - - - - @@ -45,15 +41,13 @@ - - + - diff --git a/files/mygui/openmw_chargen_review_layout.xml b/files/mygui/openmw_chargen_review_layout.xml index 57bb3b124..2071cac88 100644 --- a/files/mygui/openmw_chargen_review_layout.xml +++ b/files/mygui/openmw_chargen_review_layout.xml @@ -26,26 +26,83 @@ + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -59,7 +116,7 @@ - + diff --git a/files/mygui/openmw_chargen_select_specialization_layout.xml b/files/mygui/openmw_chargen_select_specialization_layout.xml index 53980b133..1b5295bc9 100644 --- a/files/mygui/openmw_chargen_select_specialization_layout.xml +++ b/files/mygui/openmw_chargen_select_specialization_layout.xml @@ -11,13 +11,13 @@ - + - + - + diff --git a/files/mygui/openmw_infobox_layout.xml b/files/mygui/openmw_infobox_layout.xml index de1030830..89031a616 100644 --- a/files/mygui/openmw_infobox_layout.xml +++ b/files/mygui/openmw_infobox_layout.xml @@ -4,7 +4,7 @@ - + diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index e96aeb918..f1a8b0dfc 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -139,4 +139,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 6b62f618d..bfa970de5 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -65,26 +65,45 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml index 262fd2020..148e98064 100644 --- a/files/mygui/openmw_tooltips.xml +++ b/files/mygui/openmw_tooltips.xml @@ -134,6 +134,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From f6a6684685d033554f01fb1a0187f77be5c6eee3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 21:39:18 +0200 Subject: [PATCH 49/76] when the resolution changes, adjust camera aspect ratio and recreate compositors --- apps/openmw/mwrender/compositors.cpp | 15 +++++++++++ apps/openmw/mwrender/compositors.hpp | 5 ++++ apps/openmw/mwrender/renderingmanager.cpp | 32 +++++++++++++++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 10 ++++++- apps/openmw/mwrender/sky.cpp | 7 +++-- apps/openmw/mwrender/sky.hpp | 2 +- apps/openmw/mwrender/water.cpp | 9 +++++-- apps/openmw/mwrender/water.hpp | 3 ++- libs/openengine/ogre/renderer.cpp | 15 +++++++++++ libs/openengine/ogre/renderer.hpp | 5 ++++ 10 files changed, 94 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/compositors.cpp b/apps/openmw/mwrender/compositors.cpp index 4c9f08b72..d786c263b 100644 --- a/apps/openmw/mwrender/compositors.cpp +++ b/apps/openmw/mwrender/compositors.cpp @@ -26,6 +26,21 @@ void Compositors::setEnabled (const bool enabled) mEnabled = enabled; } +void Compositors::recreate() +{ + Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); + + CompositorMap temp = mCompositors; + mCompositors.clear(); + + for (CompositorMap::iterator it=temp.begin(); + it != temp.end(); ++it) + { + addCompositor(it->first, it->second.second); + setCompositorEnabled(it->first, mEnabled && it->second.first); + } +} + void Compositors::addCompositor (const std::string& name, const int priority) { int id = 0; diff --git a/apps/openmw/mwrender/compositors.hpp b/apps/openmw/mwrender/compositors.hpp index 50b53f84a..f249ece42 100644 --- a/apps/openmw/mwrender/compositors.hpp +++ b/apps/openmw/mwrender/compositors.hpp @@ -25,6 +25,11 @@ namespace MWRender */ void setEnabled (const bool enabled); + void setViewport(Ogre::Viewport* vp) { mViewport = vp; } + + /// recreate compositors (call this after viewport size changes) + void recreate(); + bool toggle() { setEnabled(!mEnabled); return mEnabled; } /** diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 86c1f752c..e5ce6b0dd 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -11,6 +11,7 @@ #include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone #include "../mwworld/ptr.hpp" +#include "../mwworld/player.hpp" #include "../mwbase/environment.hpp" #include #include @@ -30,6 +31,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0) { mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); + mRendering.setWindowEventListener(this); mCompositors = new Compositors(mRendering.getViewport()); @@ -567,6 +569,7 @@ Compositors* RenderingManager::getCompositors() void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) { + bool changeRes = false; for (Settings::CategorySettingVector::const_iterator it=settings.begin(); it != settings.end(); ++it) { @@ -574,6 +577,24 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec { setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } + else if (it->second == "max viewing distance" && it->first == "Viewing distance") + { + if (!MWBase::Environment::get().getWorld()->isCellExterior() && !MWBase::Environment::get().getWorld()->isCellQuasiExterior()) + configureFog(*MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()); + } + else if (it->first == "Video" && ( + it->second == "resolution x" + || it->second == "resolution y" + || it->second == "fullscreen")) + changeRes = true; + } + + if (changeRes) + { + int x = Settings::Manager::getInt("resolution x", "Video"); + int y = Settings::Manager::getInt("resolution y", "Video"); + mRendering.getWindow()->resize(x, y); + mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } } @@ -587,4 +608,15 @@ void RenderingManager::setMenuTransparency(float val) tex->getBuffer()->unlock(); } +void RenderingManager::windowResized(Ogre::RenderWindow* rw) +{ + mCompositors->setViewport(mRendering.recreateViewport()); + mCompositors->recreate(); + mWater->assignTextures(); +} + +void RenderingManager::windowClosed(Ogre::RenderWindow* rw) +{ +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index edee193f3..562184c62 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -8,6 +8,8 @@ #include "../mwworld/class.hpp" +#include + #include #include #include @@ -51,7 +53,7 @@ namespace MWRender class Water; class Compositors; -class RenderingManager: private RenderingInterface { +class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener { private: @@ -161,6 +163,12 @@ class RenderingManager: private RenderingInterface { void processChangedSettings(const Settings::CategorySettingVector& settings); + Ogre::Viewport* getViewport() { return mRendering.getViewport(); } + + protected: + virtual void windowResized(Ogre::RenderWindow* rw); + virtual void windowClosed(Ogre::RenderWindow* rw); + private: void setAmbientMode(); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 72f88c6c5..19e45c189 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -374,7 +374,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mSunGlare(NULL) , mMasser(NULL) , mSecunda(NULL) - , mViewport(NULL) + , mCamera(pCamera) , mRootNode(NULL) , mSceneMgr(NULL) , mAtmosphereDay(NULL) @@ -399,9 +399,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mSecundaEnabled(true) , mCreated(false) { - mViewport = pCamera->getViewport(); mSceneMgr = pMwRoot->getCreator(); - mRootNode = pCamera->getParentSceneNode()->createChildSceneNode(); + mRootNode = mCamera->getParentSceneNode()->createChildSceneNode(); mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates mRootNode->setInheritOrientation(false); } @@ -741,7 +740,7 @@ void SkyManager::update(float duration) // on how directly the player is looking at the sun Vector3 sun = mSunGlare->getPosition(); sun = Vector3(sun.x, sun.z, -sun.y); - Vector3 cam = mViewport->getCamera()->getRealDirection(); + Vector3 cam = mCamera->getRealDirection(); const Degree angle = sun.angleBetween( cam ); float val = 1- (angle.valueDegrees() / 180.f); val = (val*val*val*val)*2; diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index da89d0eb0..e11745e82 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -185,7 +185,7 @@ namespace MWRender Moon* mMasser; Moon* mSecunda; - Ogre::Viewport* mViewport; + Ogre::Camera* mCamera; Ogre::SceneNode* mRootNode; Ogre::SceneManager* mSceneMgr; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index dda215999..981343e91 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -10,7 +10,7 @@ namespace MWRender { Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell) : - mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()), + mCamera (camera), mSceneManager (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), mReflectionTarget(0), mActive(1), mToggled(1), mReflectionRenderActive(false), mRendering(rend) @@ -80,6 +80,8 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mSceneManager->addRenderQueueListener(this); + assignTextures(); + // ---------------------------------------------------------------------------------------------- // ---------------------------------- reflection debug overlay ---------------------------------- @@ -262,10 +264,13 @@ void Water::createMaterial() // use technique without shaders if reflection is disabled if (mReflectionTarget == 0) mMaterial->removeTechnique(0); +} +void Water::assignTextures() +{ if (Settings::Manager::getBool("shader", "Water")) { - CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mViewport)->getCompositor("gbuffer"); + CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer"); TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0); TextureUnitState* tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap"); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 25631b4af..edd217e84 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -17,7 +17,6 @@ namespace MWRender { static const int CELL_SIZE = 8192; Ogre::Camera *mCamera; Ogre::SceneManager *mSceneManager; - Ogre::Viewport *mViewport; Ogre::Plane mWaterPlane; Ogre::SceneNode *mWaterNode; @@ -65,6 +64,8 @@ namespace MWRender { void toggle(); void update(); + void assignTextures(); + void setViewportBackground(const Ogre::ColourValue& bg); void checkUnderwater(float y); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index ab7920ab8..579ba3dd7 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -144,3 +144,18 @@ void OgreRenderer::createScene(const std::string camName, float fov, float nearC mFader = new Fader(); } + +Ogre::Viewport* OgreRenderer::recreateViewport() +{ + mWindow->removeViewport(mView->getZOrder()); + mView = mWindow->addViewport(mCamera); + + // Alter the camera aspect ratio to match the viewport + mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); + return mView; +} + +void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) +{ + Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); +} diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 50fe64015..7a0fd11df 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -25,6 +25,7 @@ #endif #include "OgreTexture.h" +#include namespace Ogre { @@ -104,6 +105,8 @@ namespace OEngine ~OgreRenderer() { cleanup(); } + void setWindowEventListener(Ogre::WindowEventListener* listener); + /** Configure the renderer. This will load configuration files and set up the Root and logging classes. */ void configure( @@ -153,6 +156,8 @@ namespace OEngine /// Viewport Ogre::Viewport *getViewport() { return mView; } + + Ogre::Viewport* recreateViewport(); }; } } From 8f667580bb855ae04857eda9c228888956527d87 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 27 May 2012 23:12:45 +0200 Subject: [PATCH 50/76] ogre 1.8 final release compability fixes --- apps/openmw/mwrender/terrain.cpp | 20 ++++++++++---------- apps/openmw/mwrender/terrain.hpp | 2 +- files/gbuffer/gbuffer.compositor | 17 ++++------------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 56eff4a9a..90345cf30 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -22,30 +22,30 @@ namespace MWRender TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend) : mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend) { - + mTerrainGlobals = OGRE_NEW TerrainGlobalOptions(); TerrainMaterialGeneratorPtr matGen; TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB(); matGen.bind(matGenP); - mTerrainGlobals.setDefaultMaterialGenerator(matGen); + mTerrainGlobals->setDefaultMaterialGenerator(matGen); TerrainMaterialGenerator::Profile* const activeProfile = - mTerrainGlobals.getDefaultMaterialGenerator() + mTerrainGlobals->getDefaultMaterialGenerator() ->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); + mTerrainGlobals->setMaxPixelError(8); - mTerrainGlobals.setLayerBlendMapSize(32); - mTerrainGlobals.setDefaultGlobalColourMapSize(65); + mTerrainGlobals->setLayerBlendMapSize(32); + mTerrainGlobals->setDefaultGlobalColourMapSize(65); //10 (default) didn't seem to be quite enough - mTerrainGlobals.setSkirtSize(128); + mTerrainGlobals->setSkirtSize(128); //due to the sudden flick between composite and non composite textures, //this seemed the distance where it wasn't too noticeable - mTerrainGlobals.setCompositeMapDistance(mWorldSize*2); + mTerrainGlobals->setCompositeMapDistance(mWorldSize*2); mActiveProfile->setLightmapEnabled(false); mActiveProfile->setLayerSpecularMappingEnabled(false); @@ -92,14 +92,14 @@ namespace MWRender void TerrainManager::setDiffuse(const ColourValue& diffuse) { - mTerrainGlobals.setCompositeMapDiffuse(diffuse); + mTerrainGlobals->setCompositeMapDiffuse(diffuse); } //---------------------------------------------------------------------------------------------- void TerrainManager::setAmbient(const ColourValue& ambient) { - mTerrainGlobals.setCompositeMapAmbient(ambient); + mTerrainGlobals->setCompositeMapAmbient(ambient); } //---------------------------------------------------------------------------------------------- diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index c4ff053a6..273ede084 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -33,7 +33,7 @@ namespace MWRender{ void cellAdded(MWWorld::Ptr::CellStore* store); void cellRemoved(MWWorld::Ptr::CellStore* store); private: - Ogre::TerrainGlobalOptions mTerrainGlobals; + Ogre::TerrainGlobalOptions* mTerrainGlobals; Ogre::TerrainGroup mTerrainGroup; RenderingManager* mRendering; diff --git a/files/gbuffer/gbuffer.compositor b/files/gbuffer/gbuffer.compositor index 316003af6..6ca35df87 100644 --- a/files/gbuffer/gbuffer.compositor +++ b/files/gbuffer/gbuffer.compositor @@ -11,11 +11,8 @@ compositor gbuffer input none pass clear { - clear - { - // make sure to set this to the viewport background color from outside - colour_value 0 0 0 1 - } + // make sure to set this to the viewport background color from outside + colour_value 0 0 0 1 } pass render_scene { @@ -59,11 +56,8 @@ compositor gbufferFinalizer shadows off pass clear { - clear - { - buffers colour - colour_value 0 0 0 0 - } + buffers colour + colour_value 0 0 0 0 } pass render_quad { @@ -81,9 +75,6 @@ compositor gbufferFinalizer input none pass clear { - clear - { - } } pass render_quad { From 19c428e86c46ab120379f9dbfb1aceb72ac6d0ff Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 02:04:00 +0200 Subject: [PATCH 51/76] delete fix --- apps/openmw/mwrender/terrain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 90345cf30..4dac750c7 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -86,6 +86,7 @@ namespace MWRender TerrainManager::~TerrainManager() { + OGRE_DELETE mTerrainGlobals; } //---------------------------------------------------------------------------------------------- From 3daf1ebc3fc36dbc565279a1274a110a69963147 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 05:03:50 +0200 Subject: [PATCH 52/76] small map tweak --- apps/openmw/mwrender/localmap.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 55cb45fdc..2442700bb 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -326,8 +326,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, -playerdirection.z); // explore radius (squared) - const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution; - const float exploreRadius = 0.1 * sFogOfWarResolution; // explore radius from 0 to sFogOfWarResolution + const float sqrExploreRadius = (mInterior ? 0.01 : 0.09) * sFogOfWarResolution*sFogOfWarResolution; + const float exploreRadius = (mInterior ? 0.1 : 0.3) * sFogOfWarResolution; // explore radius from 0 to sFogOfWarResolution const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space) int intExtMult = mInterior ? 1 : -1; // interior and exterior have reversed Y coordinates (interior: top to bottom) @@ -364,7 +364,11 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni { for (int texU = 0; texU> 24); alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); From 14f4f09f834b4d5f7c1d840de8b3be18ff66943e Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 09:19:25 +0200 Subject: [PATCH 53/76] proper resolution switching (reposition GUI & adjust mouse clipping region) --- apps/openmw/mwgui/console.cpp | 5 +++++ apps/openmw/mwgui/console.hpp | 2 ++ apps/openmw/mwgui/hud.cpp | 5 +++++ apps/openmw/mwgui/hud.hpp | 1 + apps/openmw/mwgui/settingswindow.cpp | 5 +++++ apps/openmw/mwgui/window_base.cpp | 10 +++++++++- apps/openmw/mwgui/window_manager.cpp | 21 +++++++++++++++++++++ apps/openmw/mwinput/inputmanager.cpp | 23 ++++++++++++++++++++++- apps/openmw/mwinput/inputmanager.hpp | 4 ++++ apps/openmw/mwrender/renderingmanager.cpp | 23 +++++++++++++++++++---- libs/mangle/input/servers/ois_driver.cpp | 7 +++++++ libs/mangle/input/servers/ois_driver.hpp | 2 ++ libs/openengine/gui/events.cpp | 18 +++--------------- libs/openengine/gui/events.hpp | 2 -- libs/openengine/ogre/renderer.cpp | 6 +----- libs/openengine/ogre/renderer.hpp | 2 +- 16 files changed, 107 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 8e15abddd..bf80a77b2 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -370,4 +370,9 @@ namespace MWGui /* All keywords match with the shortest. Append it to the output string and return it. */ return output.append(matches.front()); } + + void Console::onResChange(int width, int height) + { + setCoord(10,10, width-10, height/2); + } } diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 6974d8333..117285847 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -58,6 +58,8 @@ namespace MWGui void setFont(const std::string &fntName); + void onResChange(int width, int height); + void clearHistory(); // Print a message to the console. Messages may contain color diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index d3d7696b4..31952e993 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -347,3 +347,8 @@ void HUD::onFrame(float dt) if (mCellNameTimer < 0) mCellNameBox->setVisible(false); } + +void HUD::onResChange(int width, int height) +{ + setCoord(0, 0, width, height); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index f7131a39c..531dd7020 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -26,6 +26,7 @@ namespace MWGui void setFpsLevel(const int level); void onFrame(float dt); + void onResChange(int width, int height); void setCellName(const std::string& cellName); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 0e0815228..c8337d74c 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -11,6 +11,7 @@ #include "../mwbase/environment.hpp" #include "../mwworld/world.hpp" #include "../mwsound/soundmanager.hpp" +#include "../mwinput/inputmanager.hpp" #include "window_manager.hpp" #include "confirmationdialog.hpp" @@ -144,7 +145,10 @@ namespace MWGui } if (_sender == mFullscreenButton) + { Settings::Manager::setBool("fullscreen", "Video", newState); + apply(); + } else if (_sender == mVSyncButton) { Settings::Manager::setBool("vsync", "Video", newState); @@ -188,5 +192,6 @@ namespace MWGui MWBase::Environment::get().getWorld()->processChangedSettings(changed); MWBase::Environment::get().getSoundManager()->processChangedSettings(changed); MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); + MWBase::Environment::get().getInputManager()->processChangedSettings(changed); } } diff --git a/apps/openmw/mwgui/window_base.cpp b/apps/openmw/mwgui/window_base.cpp index 45206214b..433057931 100644 --- a/apps/openmw/mwgui/window_base.cpp +++ b/apps/openmw/mwgui/window_base.cpp @@ -1,6 +1,8 @@ #include "window_base.hpp" #include "window_manager.hpp" +#include + using namespace MWGui; WindowBase::WindowBase(const std::string& parLayout, WindowManager& parWindowManager) @@ -25,7 +27,13 @@ void WindowBase::setVisible(bool visible) void WindowBase::center() { // Centre dialog - MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); + + // MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); + // Note by scrawl: The following works more reliably in the case when the window was _just_ + // resized and MyGUI RenderManager doesn't know about the new size yet + MyGUI::IntSize gameWindowSize = MyGUI::IntSize(Settings::Manager::getInt("resolution x", "Video"), + Settings::Manager::getInt("resolution y", "Video")); + MyGUI::IntCoord coord = mMainWidget->getCoord(); coord.left = (gameWindowSize.width - coord.width)/2; coord.top = (gameWindowSize.height - coord.height)/2; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index a6d236136..891f85ca2 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -605,6 +605,27 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) { hud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); + + bool changeRes = false; + for (Settings::CategorySettingVector::const_iterator it = changed.begin(); + it != changed.end(); ++it) + { + if (it->first == "Video" && ( + it->second == "resolution x" + || it->second == "resolution y")) + { + changeRes = true; + } + } + + if (changeRes) + { + int x = Settings::Manager::getInt("resolution x", "Video"); + int y = Settings::Manager::getInt("resolution y", "Video"); + hud->onResChange(x, y); + console->onResChange(x, y); + mSettingsWindow->center(); + } } void WindowManager::pushGuiMode(GuiMode mode) diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 9b6a1d39b..a2bafcbf7 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -92,7 +92,12 @@ namespace MWInput /* InputImpl Methods */ - +public: + void adjustMouseRegion(int width, int height) + { + input.adjustMouseClippingSize(width, height); + } +private: void toggleSpell() { if (windows.isGuiMode()) return; @@ -450,4 +455,20 @@ namespace MWInput { impl->changeInputMode(guiMode); } + + void MWInputManager::processChangedSettings(const Settings::CategorySettingVector& changed) + { + bool changeRes = false; + for (Settings::CategorySettingVector::const_iterator it = changed.begin(); + it != changed.end(); ++it) + { + if (it->first == "Video" && ( + it->second == "resolution x" + || it->second == "resolution y")) + changeRes = true; + } + + if (changeRes) + impl->adjustMouseRegion(Settings::Manager::getInt("resolution x", "Video"), Settings::Manager::getInt("resolution y", "Video")); + } } diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index b8d98ed56..4ef3df137 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -3,6 +3,8 @@ #include "../mwgui/mode.hpp" +#include + namespace OEngine { namespace Render @@ -52,6 +54,8 @@ namespace MWInput void changeInputMode(bool guiMode); + void processChangedSettings(const Settings::CategorySettingVector& changed); + void setDragDrop(bool dragDrop); }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index e5ce6b0dd..46e274ff5 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -22,6 +22,9 @@ #include "water.hpp" #include "compositors.hpp" +#include "../mwgui/window_manager.hpp" // FIXME +#include "../mwinput/inputmanager.hpp" // FIXME + using namespace MWRender; using namespace Ogre; @@ -591,9 +594,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec if (changeRes) { - int x = Settings::Manager::getInt("resolution x", "Video"); - int y = Settings::Manager::getInt("resolution y", "Video"); - mRendering.getWindow()->resize(x, y); + unsigned int x = Settings::Manager::getInt("resolution x", "Video"); + unsigned int y = Settings::Manager::getInt("resolution y", "Video"); + + if (x != mRendering.getWindow()->getWidth() || y != mRendering.getWindow()->getHeight()) + { + mRendering.getWindow()->resize(x, y); + } mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } } @@ -610,9 +617,17 @@ void RenderingManager::setMenuTransparency(float val) void RenderingManager::windowResized(Ogre::RenderWindow* rw) { - mCompositors->setViewport(mRendering.recreateViewport()); + Settings::Manager::setInt("resolution x", "Video", rw->getWidth()); + Settings::Manager::setInt("resolution y", "Video", rw->getHeight()); + + + mRendering.adjustViewport(); mCompositors->recreate(); mWater->assignTextures(); + + const Settings::CategorySettingVector& changed = Settings::Manager::apply(); + MWBase::Environment::get().getInputManager()->processChangedSettings(changed); //FIXME + MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); // FIXME } void RenderingManager::windowClosed(Ogre::RenderWindow* rw) diff --git a/libs/mangle/input/servers/ois_driver.cpp b/libs/mangle/input/servers/ois_driver.cpp index 2071b91ea..acca69df4 100644 --- a/libs/mangle/input/servers/ois_driver.cpp +++ b/libs/mangle/input/servers/ois_driver.cpp @@ -146,3 +146,10 @@ bool OISDriver::isDown(int index) // TODO: Extend to mouse buttons as well return keyboard->isKeyDown((OIS::KeyCode)index); } + +void OISDriver::adjustMouseClippingSize(int width, int height) +{ + const OIS::MouseState &ms = mouse->getMouseState(); + ms.width = width; + ms.height = height; +} diff --git a/libs/mangle/input/servers/ois_driver.hpp b/libs/mangle/input/servers/ois_driver.hpp index ba780c39e..81633542f 100644 --- a/libs/mangle/input/servers/ois_driver.hpp +++ b/libs/mangle/input/servers/ois_driver.hpp @@ -31,6 +31,8 @@ namespace Mangle OISDriver(Ogre::RenderWindow *window, bool exclusive=true); ~OISDriver(); + void adjustMouseClippingSize(int width, int height); + void capture(); bool isDown(int index); /// Not currently supported. diff --git a/libs/openengine/gui/events.cpp b/libs/openengine/gui/events.cpp index 3e52c6435..a19c247c2 100644 --- a/libs/openengine/gui/events.cpp +++ b/libs/openengine/gui/events.cpp @@ -8,18 +8,9 @@ using namespace OIS; using namespace OEngine::GUI; EventInjector::EventInjector(MyGUI::Gui *g) - : gui(g), mouseX(0), mouseY(0), enabled(true) + : gui(g), enabled(true) { assert(gui); - maxX = MyGUI::RenderManager::getInstance().getViewSize().width; - maxY = MyGUI::RenderManager::getInstance().getViewSize().height; -} - -template -void setRange(X &x, X min, X max) -{ - if(x < min) x = min; - else if(x > max) x = max; } void EventInjector::event(Type type, int index, const void *p) @@ -64,11 +55,8 @@ void EventInjector::event(Type type, int index, const void *p) MyGUI::MouseButton id = MyGUI::MouseButton::Enum(index); // Update mouse position - mouseX += mouse->state.X.rel; - mouseY += mouse->state.Y.rel; - - setRange(mouseX,0,maxX); - setRange(mouseY,0,maxY); + int mouseX = mouse->state.X.abs; + int mouseY = mouse->state.Y.abs; if(type == EV_MouseDown) MyGUI::InputManager::getInstance().injectMousePress(mouseX, mouseY, id); diff --git a/libs/openengine/gui/events.hpp b/libs/openengine/gui/events.hpp index 6ca83cf75..1f506cffa 100644 --- a/libs/openengine/gui/events.hpp +++ b/libs/openengine/gui/events.hpp @@ -16,8 +16,6 @@ namespace GUI class EventInjector : public Mangle::Input::Event { MyGUI::Gui *gui; - int mouseX, mouseY; - int maxX, maxY; public: bool enabled; diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 579ba3dd7..7a01ffce7 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -145,14 +145,10 @@ void OgreRenderer::createScene(const std::string camName, float fov, float nearC mFader = new Fader(); } -Ogre::Viewport* OgreRenderer::recreateViewport() +void OgreRenderer::adjustViewport() { - mWindow->removeViewport(mView->getZOrder()); - mView = mWindow->addViewport(mCamera); - // Alter the camera aspect ratio to match the viewport mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); - return mView; } void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 7a0fd11df..9d1d0122d 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -157,7 +157,7 @@ namespace OEngine /// Viewport Ogre::Viewport *getViewport() { return mView; } - Ogre::Viewport* recreateViewport(); + void adjustViewport(); }; } } From 6014a900025cd45b13325c0d1f9d896e856defe5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 09:46:05 +0200 Subject: [PATCH 54/76] added tooltip delay option --- apps/openmw/mwgui/settingswindow.cpp | 6 ++++ apps/openmw/mwgui/settingswindow.hpp | 1 + apps/openmw/mwgui/tooltips.cpp | 30 +++++++++++++++++++ apps/openmw/mwgui/tooltips.hpp | 8 +++++ apps/openmw/mwgui/window_manager.cpp | 1 + files/mygui/openmw_settings_window_layout.xml | 15 ++++++++++ files/settings-default.cfg | 3 ++ 7 files changed, 64 insertions(+) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index c8337d74c..428e0e862 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -37,6 +37,7 @@ namespace MWGui getWidget(mOkButton, "OkButton"); getWidget(mResolutionList, "ResolutionList"); getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); + getWidget(mToolTipDelaySlider, "ToolTipDelaySlider"); getWidget(mViewDistanceSlider, "ViewDistanceSlider"); getWidget(mFullscreenButton, "FullscreenButton"); getWidget(mVSyncButton, "VSyncButton"); @@ -52,6 +53,7 @@ namespace MWGui mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mToolTipDelaySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); @@ -79,6 +81,8 @@ namespace MWGui // read settings int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI"); mMenuTransparencySlider->setScrollPosition(menu_transparency); + int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI"); + mToolTipDelaySlider->setScrollPosition(tooltip_delay); float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-2000)/(5600-2000); int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; @@ -170,6 +174,8 @@ namespace MWGui float val = pos / float(scroller->getScrollRange()-1); if (scroller == mMenuTransparencySlider) Settings::Manager::setFloat("menu transparency", "GUI", val); + else if (scroller == mToolTipDelaySlider) + Settings::Manager::setFloat("tooltip delay", "GUI", val); else if (scroller == mViewDistanceSlider) Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); else if (scroller == mMasterVolumeSlider) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 79af03994..09a93264d 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -19,6 +19,7 @@ namespace MWGui MyGUI::Button* mOkButton; MyGUI::ScrollBar* mMenuTransparencySlider; + MyGUI::ScrollBar* mToolTipDelaySlider; // graphics MyGUI::ListBox* mResolutionList; diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index c6d8e2c8c..bdce61a44 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -8,6 +8,8 @@ #include +#include + using namespace MWGui; using namespace MyGUI; @@ -19,6 +21,10 @@ ToolTips::ToolTips(WindowManager* windowManager) : , mEnabled(true) , mFocusToolTipX(0.0) , mFocusToolTipY(0.0) + , mDelay(0.0) + , mRemainingDelay(0.0) + , mLastMouseX(0) + , mLastMouseY(0) { getWidget(mDynamicToolTipBox, "DynamicToolTipBox"); @@ -28,6 +34,9 @@ ToolTips::ToolTips(WindowManager* windowManager) : // even if the mouse is over the tooltip mDynamicToolTipBox->setNeedMouseFocus(false); mMainWidget->setNeedMouseFocus(false); + + mDelay = Settings::Manager::getFloat("tooltip delay", "GUI"); + mRemainingDelay = mDelay; } void ToolTips::setEnabled(bool enabled) @@ -57,6 +66,21 @@ void ToolTips::onFrame(float frameDuration) if (!mGameMode) { + const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); + if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) + { + mRemainingDelay -= frameDuration; + } + else + { + mRemainingDelay = mDelay; + } + mLastMouseX = mousePos.left; + mLastMouseY = mousePos.top; + + if (mRemainingDelay > 0) + return; + Widget* focus = InputManager::getInstance().getMouseFocusWidget(); if (focus == 0) { @@ -621,3 +645,9 @@ void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playe widget->setUserString("ToolTipType", "Layout"); widget->setUserString("ToolTipLayout", "ClassToolTip"); } + +void ToolTips::setDelay(float delay) +{ + mDelay = delay; + mRemainingDelay = mDelay; +} diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 1925a4f14..036bdfaa3 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -41,6 +41,8 @@ namespace MWGui void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) bool getFullHelp() const; + void setDelay(float delay); + void setFocusObject(const MWWorld::Ptr& focus); void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); ///< set the screen-space position of the tooltip for focused object @@ -84,6 +86,12 @@ namespace MWGui float mFocusToolTipX; float mFocusToolTipY; + float mDelay; + float mRemainingDelay; // remaining time until tooltip will show + + int mLastMouseX; + int mLastMouseY; + bool mGameMode; bool mEnabled; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 891f85ca2..c3dc5d801 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -605,6 +605,7 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) { hud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); + mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); bool changeRes = false; for (Settings::CategorySettingVector::const_iterator it = changed.begin(); diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 9b5826765..2e53c2a4a 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -23,6 +23,21 @@ + + + + + + + + + + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index a6623656c..883f32ae0 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -28,6 +28,9 @@ vsync = false # 1 is fully opaque menu transparency = 0.84 +# 0 - instantly, 1 - max. delay +tooltip delay = 0.2 + [General] # Camera field of view field of view = 55 From e1ee45a6d66f1eacfa7192d386ccfde42ef53761 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 10:50:00 +0200 Subject: [PATCH 55/76] Issue #297: Make the stats review dialog show correct values for attributes/skills/health/magicka/fatigue --- apps/openmw/mwgui/charactercreation.cpp | 62 +++++++++++++++++++++++-- apps/openmw/mwgui/charactercreation.hpp | 8 ++-- apps/openmw/mwgui/class.cpp | 10 ++-- apps/openmw/mwgui/review.cpp | 3 ++ apps/openmw/mwgui/stats_window.cpp | 2 + apps/openmw/mwgui/window_manager.cpp | 4 ++ apps/openmw/mwgui/window_manager.hpp | 5 ++ 7 files changed, 81 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 691fd4a91..cc7448646 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -122,6 +122,56 @@ CharacterCreation::CharacterCreation(WindowManager* _wm) mCreationStage = CSE_NotStarted; } +void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat& value) +{ + if (mReviewDialog) + { + static const char *ids[] = + { + "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", + "AttribVal6", "AttribVal7", "AttribVal8", + 0 + }; + + for (int i=0; ids[i]; ++i) + { + if (ids[i]==id) + mReviewDialog->setAttribute(ESM::Attribute::AttributeID(i), value); + } + } +} + +void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat& value) +{ + if (mReviewDialog) + { + if (id == "HBar") + { + mReviewDialog->setHealth (value); + } + else if (id == "MBar") + { + mReviewDialog->setMagicka (value); + } + else if (id == "FBar") + { + mReviewDialog->setFatigue (value); + } + } +} + +void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value) +{ + if (mReviewDialog) + mReviewDialog->setSkillValue(parSkill, value); +} + +void CharacterCreation::configureSkills (const SkillList& major, const SkillList& minor) +{ + if (mReviewDialog) + mReviewDialog->configureSkills(major, minor); +} + void CharacterCreation::spawnDialog(const char id) { switch (id) @@ -208,20 +258,22 @@ void CharacterCreation::spawnDialog(const char id) mReviewDialog->setFatigue(mPlayerFatigue); { - std::map >::iterator end = mPlayerAttributes.end(); - for (std::map >::iterator it = mPlayerAttributes.begin(); it != end; ++it) + std::map > attributes = mWM->getPlayerAttributeValues(); + for (std::map >::iterator it = attributes.begin(); + it != attributes.end(); ++it) { mReviewDialog->setAttribute(it->first, it->second); } } { - std::map >::iterator end = mPlayerSkillValues.end(); - for (std::map >::iterator it = mPlayerSkillValues.begin(); it != end; ++it) + std::map > skills = mWM->getPlayerSkillValues(); + for (std::map >::iterator it = skills.begin(); + it != skills.end(); ++it) { mReviewDialog->setSkillValue(it->first, it->second); } - mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills); + mReviewDialog->configureSkills(mWM->getPlayerMajorSkills(), mWM->getPlayerMinorSkills()); } mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone); diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index dfb07853e..02b48ffe2 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -42,6 +42,11 @@ namespace MWGui void setPlayerFatigue (const MWMechanics::DynamicStat& value); + void setValue (const std::string& id, const MWMechanics::Stat& value); + void setValue (const std::string& id, const MWMechanics::DynamicStat& value); + void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); + void configureSkills (const SkillList& major, const SkillList& minor); + private: //Dialogs TextInputDialog* mNameDialog; @@ -61,9 +66,6 @@ namespace MWGui std::string mPlayerRaceId; std::string mPlayerBirthSignId; ESM::Class mPlayerClass; - std::map > mPlayerAttributes; - SkillList mPlayerMajorSkills, mPlayerMinorSkills; - std::map > mPlayerSkillValues; MWMechanics::DynamicStat mPlayerHealth; MWMechanics::DynamicStat mPlayerMagicka; MWMechanics::DynamicStat mPlayerFatigue; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index d3d261ab0..a7e5b8674 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -241,10 +241,10 @@ void PickClassDialog::updateStats() for (int i = 0; i < 5; ++i) { - majorSkill[i]->setSkillNumber(klass->data.skills[i][0]); - minorSkill[i]->setSkillNumber(klass->data.skills[i][1]); - ToolTips::createSkillToolTip(majorSkill[i], klass->data.skills[i][0]); - ToolTips::createSkillToolTip(minorSkill[i], klass->data.skills[i][1]); + minorSkill[i]->setSkillNumber(klass->data.skills[i][0]); + majorSkill[i]->setSkillNumber(klass->data.skills[i][1]); + ToolTips::createSkillToolTip(minorSkill[i], klass->data.skills[i][0]); + ToolTips::createSkillToolTip(majorSkill[i], klass->data.skills[i][1]); } classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds"); @@ -518,7 +518,7 @@ std::vector CreateClassDialog::getMinorSkills() const std::vector v; for(int i=0; i < 5; i++) { - v.push_back(majorSkill[i]->getSkillId()); + v.push_back(minorSkill[i]->getSkillId()); } return v; } diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index be537e854..67b6cc24a 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -211,6 +211,7 @@ void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanic widget->setCaption(text); widget->_setWidgetState(state); } + } void ReviewDialog::configureSkills(const std::vector& major, const std::vector& minor) @@ -230,6 +231,8 @@ void ReviewDialog::configureSkills(const std::vector& major, const std::vec if (skillSet.find(skill) == skillSet.end()) miscSkills.push_back(skill); } + + updateSkillArea(); } void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 061800bf0..75159f4db 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -255,6 +255,8 @@ void StatsWindow::configureSkills (const std::vector& major, const std::vec if (skillSet.find(skill) == skillSet.end()) miscSkills.push_back(skill); } + + updateSkillArea(); } void StatsWindow::onFrame () diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index c3dc5d801..4e786978f 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -302,6 +302,7 @@ void WindowManager::updateVisible() void WindowManager::setValue (const std::string& id, const MWMechanics::Stat& value) { mStatsWindow->setValue (id, value); + mCharGen->setValue(id, value); static const char *ids[] = { @@ -332,6 +333,7 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::Stat& value) { mStatsWindow->setValue(parSkill, value); + mCharGen->setValue(parSkill, value); playerSkillValues[parSkill] = value; } @@ -339,6 +341,7 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicS { mStatsWindow->setValue (id, value); hud->setValue (id, value); + mCharGen->setValue(id, value); if (id == "HBar") { playerHealth = value; @@ -391,6 +394,7 @@ void WindowManager::setPlayerClass (const ESM::Class &class_) void WindowManager::configureSkills (const SkillList& major, const SkillList& minor) { mStatsWindow->configureSkills (major, minor); + mCharGen->configureSkills(major, minor); playerMajorSkills = major; playerMinorSkills = minor; } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 7082cc0bc..f3e6a436e 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -211,6 +211,11 @@ namespace MWGui void onFrame (float frameDuration); + std::map > getPlayerSkillValues() { return playerSkillValues; } + std::map > getPlayerAttributeValues() { return playerAttributes; } + SkillList getPlayerMinorSkills() { return playerMinorSkills; } + SkillList getPlayerMajorSkills() { return playerMajorSkills; } + /** * Fetches a GMST string from the store, if there is no setting with the given * ID or it is not a string the default string is returned. From a54623bcd2a764e7622d282ea3a7117ab24cdfe2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 11:37:56 +0200 Subject: [PATCH 56/76] reset attributes when building player --- apps/openmw/mwmechanics/mechanicsmanager.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanager.cpp index 0c48d8894..331074ef7 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.cpp @@ -30,6 +30,15 @@ namespace MWMechanics for (int i=0; i<27; ++i) npcStats.mSkill[i].setBase (player->npdt52.skills[i]); + creatureStats.mAttributes[0].setBase (player->npdt52.strength); + creatureStats.mAttributes[1].setBase (player->npdt52.intelligence); + creatureStats.mAttributes[2].setBase (player->npdt52.willpower); + creatureStats.mAttributes[3].setBase (player->npdt52.agility); + creatureStats.mAttributes[4].setBase (player->npdt52.speed); + creatureStats.mAttributes[5].setBase (player->npdt52.endurance); + creatureStats.mAttributes[6].setBase (player->npdt52.personality); + creatureStats.mAttributes[7].setBase (player->npdt52.luck); + // race if (mRaceSelected) { From 0a17d6d710731152d543f866d805a1eb7e58e609 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 28 May 2012 12:34:29 +0200 Subject: [PATCH 57/76] more resolution switching fixes --- apps/openmw/mwgui/confirmationdialog.cpp | 2 ++ apps/openmw/mwgui/confirmationdialog.hpp | 1 + apps/openmw/mwgui/hud.cpp | 4 ++- apps/openmw/mwgui/hud.hpp | 2 ++ apps/openmw/mwgui/settingswindow.cpp | 40 ++++++++++++++++++++++-- apps/openmw/mwgui/settingswindow.hpp | 1 + 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/confirmationdialog.cpp b/apps/openmw/mwgui/confirmationdialog.cpp index a54bdb1d8..5e12c3296 100644 --- a/apps/openmw/mwgui/confirmationdialog.cpp +++ b/apps/openmw/mwgui/confirmationdialog.cpp @@ -50,6 +50,8 @@ namespace MWGui void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender) { + eventCancelClicked(); + close(); } diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp index a20034171..d278274a0 100644 --- a/apps/openmw/mwgui/confirmationdialog.hpp +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -17,6 +17,7 @@ namespace MWGui signature : void method()\n */ EventHandle_Void eventOkClicked; + EventHandle_Void eventCancelClicked; private: MyGUI::EditBox* mMessage; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 31952e993..7276218d6 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -43,6 +43,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mDragAndDrop(dragAndDrop) , mCellNameTimer(0.0f) , mCellNameBox(NULL) + , mMapVisible(true) { setCoord(0,0, width, height); @@ -234,6 +235,7 @@ void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible if (!minimapBoxVisible) effectsDx = minimapBoxBaseRight - effectBoxBaseRight; + mMapVisible = minimapBoxVisible; minimapBox->setVisible(minimapBoxVisible); effectBox->setPosition(effectBoxBaseRight - effectBox->getWidth() + effectsDx, effectBox->getTop()); effectBox->setVisible(effectBoxVisible); @@ -337,7 +339,7 @@ void HUD::setCellName(const std::string& cellName) mCellName = cellName; mCellNameBox->setCaption(mCellName); - mCellNameBox->setVisible(true); + mCellNameBox->setVisible(mMapVisible); } } diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 531dd7020..16749114c 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -57,6 +57,8 @@ namespace MWGui std::string mCellName; float mCellNameTimer; + bool mMapVisible; + 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/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 428e0e862..3f30516d9 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -113,6 +113,8 @@ namespace MWGui dialog->open("#{sNotifyMessage67}"); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); + dialog->eventCancelClicked.clear(); + dialog->eventCancelClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); } void SettingsWindow::onResolutionAccept() @@ -130,6 +132,12 @@ namespace MWGui Settings::Manager::setInt("resolution y", "Video", resY); apply(); + mResolutionList->setIndexSelected(MyGUI::ITEM_NONE); + } + + void SettingsWindow::onResolutionCancel() + { + mResolutionList->setIndexSelected(MyGUI::ITEM_NONE); } void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) @@ -150,8 +158,36 @@ namespace MWGui if (_sender == mFullscreenButton) { - Settings::Manager::setBool("fullscreen", "Video", newState); - apply(); + // check if this resolution is supported in fullscreen + bool supported = false; + for (unsigned int i=0; igetItemCount(); ++i) + { + std::string resStr = mResolutionList->getItemNameAt(i); + size_t xPos = resStr.find("x"); + std::string resXStr = resStr.substr(0, xPos-1); + Ogre::StringUtil::trim(resXStr); + std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2)); + Ogre::StringUtil::trim(resYStr); + int resX = boost::lexical_cast(resXStr); + int resY = boost::lexical_cast(resYStr); + + if (resX == Settings::Manager::getInt("resolution x", "Video") + && resY == Settings::Manager::getInt("resolution y", "Video")) + supported = true; + } + + if (!supported) + { + std::string msg = "This resolution is not supported in Fullscreen mode. Please select a resolution from the list."; + MWBase::Environment::get().getWindowManager()-> + messageBox(msg, std::vector()); + _sender->castType()->setCaption(off); + } + else + { + Settings::Manager::setBool("fullscreen", "Video", newState); + apply(); + } } else if (_sender == mVSyncButton) { diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 09a93264d..9079cff54 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -41,6 +41,7 @@ namespace MWGui void onButtonToggled(MyGUI::Widget* _sender); void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); void onResolutionAccept(); + void onResolutionCancel(); void apply(); }; From f75266e4bae64ab53515614934a569aedb918e2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 01:47:49 +0200 Subject: [PATCH 58/76] fixed race dialog bug --- apps/openmw/mwgui/charactercreation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index cc7448646..31696230c 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -471,14 +471,14 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) mWM->popGuiMode(); mWM->pushGuiMode(GM_Review); } - else if (mCreationStage >= CSE_NameChosen) + else if (mCreationStage >= CSE_RaceChosen) { mWM->popGuiMode(); mWM->pushGuiMode(GM_Class); } else { - mCreationStage = CSE_NameChosen; + mCreationStage = CSE_RaceChosen; mWM->popGuiMode(); } } From 8c7cb6909d937563247048e652946e3035a7fa8c Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 01:59:16 +0200 Subject: [PATCH 59/76] addition to c7010623fb419f928fb369b5e93cbcfe39c0e0c8 : apparently talking _is_ allowed during the starting sequence, it is only disabled via scripts for certain actors --- apps/openmw/mwworld/actiontalk.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index b3b631653..a0f9d8c4c 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -11,9 +11,6 @@ namespace MWWorld void ActionTalk::execute() { - if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) - return; - MWBase::Environment::get().getDialogueManager()->startDialogue (mActor); } } From 6945afe95b8073b71719905fb3d7b4647c79052b Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 02:57:19 +0200 Subject: [PATCH 60/76] alchemy window layout --- apps/openmw/mwgui/alchemywindow.cpp | 46 +++++++++++++++++++- files/mygui/openmw_alchemy_window_layout.xml | 40 ++++++++--------- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 50d209524..9c26bfabe 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -128,6 +128,7 @@ namespace MWGui { ESM::ENAMstruct effect; effect.effectID = mEffects[i].mEffectID; + effect.area = 0; effect.range = ESM::RT_Self; effect.skill = mEffects[i].mSkill; effect.attribute = mEffects[i].mAttribute; @@ -167,10 +168,51 @@ namespace MWGui int random = rand() % names.size(); newPotion.model = "m\\misc_potion_" + names[random ] + "_01.nif"; newPotion.icon = "m\\tx_potion_" + names[random ] + "_01.dds"; - std::pair result = MWBase::Environment::get().getWorld()->createRecord(newPotion); + + // check if a similiar potion record exists already + bool found = false; + std::string objectId; + typedef std::map PotionMap; + PotionMap potions = MWBase::Environment::get().getWorld()->getStore().potions.list; + for (PotionMap::const_iterator it = potions.begin(); it != potions.end(); ++it) + { + if (found) break; + + if (it->second.data.value == newPotion.data.value + && it->second.data.weight == newPotion.data.weight + && it->second.name == newPotion.name + && it->second.effects.list.size() == newPotion.effects.list.size()) + { + // check effects + for (unsigned int i=0; i < it->second.effects.list.size(); ++i) + { + const ESM::ENAMstruct& a = it->second.effects.list[i]; + const ESM::ENAMstruct& b = newPotion.effects.list[i]; + if (a.effectID == b.effectID + && a.area == b.area + && a.range == b.range + && a.skill == b.skill + && a.attribute == b.attribute + && a.magnMin == b.magnMin + && a.magnMax == b.magnMax + && a.duration == b.duration) + { + found = true; + objectId = it->first; + break; + } + } + } + } + + if (!found) + { + std::pair result = MWBase::Environment::get().getWorld()->createRecord(newPotion); + objectId = result.first; + } // create a reference and add it to player inventory - MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), result.first); + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), objectId); MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); ref.getPtr().getRefData().setCount(1); store.add(ref.getPtr()); diff --git a/files/mygui/openmw_alchemy_window_layout.xml b/files/mygui/openmw_alchemy_window_layout.xml index 8eb5e1265..2590f9db2 100644 --- a/files/mygui/openmw_alchemy_window_layout.xml +++ b/files/mygui/openmw_alchemy_window_layout.xml @@ -1,7 +1,7 @@ - + @@ -10,73 +10,73 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + From 5d03e866131372be578e5898b6b1d3bf63d2c7ea Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 04:54:54 +0200 Subject: [PATCH 61/76] added field of view and texture filtering to settings window --- apps/openmw/mwgui/settingswindow.cpp | 69 ++++++++++++++++++- apps/openmw/mwgui/settingswindow.hpp | 12 ++++ apps/openmw/mwrender/renderingmanager.cpp | 15 ++++ files/mygui/openmw_alchemy_window_layout.xml | 4 +- files/mygui/openmw_settings_window_layout.xml | 33 ++++++++- libs/openengine/gui/events.cpp | 19 +++-- libs/openengine/gui/events.hpp | 3 + libs/openengine/ogre/renderer.cpp | 5 ++ libs/openengine/ogre/renderer.hpp | 2 + 9 files changed, 151 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 3f30516d9..82c8b554f 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -27,6 +27,18 @@ namespace else return "Detailed"; } + + std::string textureFilteringToStr(const std::string& val) + { + if (val == "none") + return "None"; + else if (val == "anisotropic") + return "Anisotropic"; + else if (val == "bilinear") + return "Bilinear"; + else + return "Trilinear"; + } } namespace MWGui @@ -42,20 +54,28 @@ namespace MWGui getWidget(mFullscreenButton, "FullscreenButton"); getWidget(mVSyncButton, "VSyncButton"); getWidget(mFPSButton, "FPSButton"); + getWidget(mFOVSlider, "FOVSlider"); getWidget(mMasterVolumeSlider, "MasterVolume"); getWidget(mVoiceVolumeSlider, "VoiceVolume"); getWidget(mEffectsVolumeSlider, "EffectsVolume"); getWidget(mFootstepsVolumeSlider, "FootstepsVolume"); getWidget(mMusicVolumeSlider, "MusicVolume"); + getWidget(mAnisotropySlider, "AnisotropySlider"); + getWidget(mTextureFilteringButton, "TextureFilteringButton"); + getWidget(mAnisotropyLabel, "AnisotropyLabel"); + getWidget(mAnisotropyBox, "AnisotropyBox"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mTextureFilteringButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringToggled); mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mFOVSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mToolTipDelaySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); + mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); @@ -84,7 +104,20 @@ namespace MWGui int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI"); mToolTipDelaySlider->setScrollPosition(tooltip_delay); - float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-2000)/(5600-2000); + float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin); + mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1)); + MyGUI::TextBox* fovText; + getWidget(fovText, "FovText"); + fovText->setCaption("Field of View (" + boost::lexical_cast(int(Settings::Manager::getFloat("field of view", "General"))) + ")"); + + float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0; + mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1)); + std::string tf = Settings::Manager::getString("texture filtering", "General"); + mTextureFilteringButton->setCaption(textureFilteringToStr(tf)); + mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(Settings::Manager::getInt("anisotropy", "General")) + ")"); + mAnisotropyBox->setVisible(tf == "anisotropic"); + + float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin); int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; mViewDistanceSlider->setScrollPosition(viewdist); @@ -205,6 +238,26 @@ namespace MWGui apply(); } + void SettingsWindow::onTextureFilteringToggled(MyGUI::Widget* _sender) + { + std::string current = Settings::Manager::getString("texture filtering", "General"); + std::string next; + if (current == "none") + next = "bilinear"; + else if (current == "bilinear") + next = "trilinear"; + else if (current == "trilinear") + next = "anisotropic"; + else + next = "none"; + + mTextureFilteringButton->setCaption(textureFilteringToStr(next)); + mAnisotropyBox->setVisible(next == "anisotropic"); + + Settings::Manager::setString("texture filtering", "General", next); + apply(); + } + void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) { float val = pos / float(scroller->getScrollRange()-1); @@ -213,7 +266,19 @@ namespace MWGui else if (scroller == mToolTipDelaySlider) Settings::Manager::setFloat("tooltip delay", "GUI", val); else if (scroller == mViewDistanceSlider) - Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * 2000 + val * 5600); + Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * sViewDistMin + val * sViewDistMax); + else if (scroller == mFOVSlider) + { + MyGUI::TextBox* fovText; + getWidget(fovText, "FovText"); + 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 == mAnisotropySlider) + { + mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(int(val*16)) + ")"); + Settings::Manager::setInt("anisotropy", "General", val * 16); + } else if (scroller == mMasterVolumeSlider) Settings::Manager::setFloat("master volume", "Sound", val); else if (scroller == mVoiceVolumeSlider) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 9079cff54..8924375d9 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -15,6 +15,12 @@ namespace MWGui public: SettingsWindow(WindowManager& parWindowManager); + private: + static const float sFovMin = 30; + static const float sFovMax = 140; + static const float sViewDistMin = 2000; + static const float sViewDistMax = 5600; + protected: MyGUI::Button* mOkButton; @@ -27,6 +33,11 @@ namespace MWGui MyGUI::Button* mVSyncButton; MyGUI::Button* mFPSButton; MyGUI::ScrollBar* mViewDistanceSlider; + MyGUI::ScrollBar* mFOVSlider; + MyGUI::ScrollBar* mAnisotropySlider; + MyGUI::Button* mTextureFilteringButton; + MyGUI::TextBox* mAnisotropyLabel; + MyGUI::Widget* mAnisotropyBox; // audio MyGUI::ScrollBar* mMasterVolumeSlider; @@ -37,6 +48,7 @@ namespace MWGui void onOkButtonClicked(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender); + void onTextureFilteringToggled(MyGUI::Widget* _sender); void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos); void onButtonToggled(MyGUI::Widget* _sender); void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 46e274ff5..89f42a5f1 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -590,6 +590,21 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec || it->second == "resolution y" || it->second == "fullscreen")) changeRes = 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") + || (it->second == "anisotropy" && it->first == "General")) + { + TextureFilterOptions tfo; + std::string filter = Settings::Manager::getString("texture filtering", "General"); + if (filter == "anisotropic") tfo = TFO_ANISOTROPIC; + else if (filter == "trilinear") tfo = TFO_TRILINEAR; + else if (filter == "bilinear") tfo = TFO_BILINEAR; + else if (filter == "none") tfo = TFO_NONE; + + MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); + MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); + } } if (changeRes) diff --git a/files/mygui/openmw_alchemy_window_layout.xml b/files/mygui/openmw_alchemy_window_layout.xml index 2590f9db2..68df748b1 100644 --- a/files/mygui/openmw_alchemy_window_layout.xml +++ b/files/mygui/openmw_alchemy_window_layout.xml @@ -60,9 +60,9 @@ - + - + diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 2e53c2a4a..107e883c4 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -100,15 +100,44 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/openengine/gui/events.cpp b/libs/openengine/gui/events.cpp index a19c247c2..bce70704b 100644 --- a/libs/openengine/gui/events.cpp +++ b/libs/openengine/gui/events.cpp @@ -9,8 +9,13 @@ using namespace OEngine::GUI; EventInjector::EventInjector(MyGUI::Gui *g) : gui(g), enabled(true) + , mMouseX(0) + , mMouseY(0) { assert(gui); + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + mMouseX = viewSize.width/2; + mMouseY = viewSize.height/2; } void EventInjector::event(Type type, int index, const void *p) @@ -54,15 +59,19 @@ void EventInjector::event(Type type, int index, const void *p) MouseEvent *mouse = (MouseEvent*)p; MyGUI::MouseButton id = MyGUI::MouseButton::Enum(index); + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + // Update mouse position - int mouseX = mouse->state.X.abs; - int mouseY = mouse->state.Y.abs; + mMouseX += mouse->state.X.rel; + mMouseY += mouse->state.Y.rel; + mMouseX = std::max(0, std::min(mMouseX, viewSize.width)); + mMouseY = std::max(0, std::min(mMouseY, viewSize.height)); if(type == EV_MouseDown) - MyGUI::InputManager::getInstance().injectMousePress(mouseX, mouseY, id); + MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, id); else if(type == EV_MouseUp) - MyGUI::InputManager::getInstance().injectMouseRelease(mouseX, mouseY, id); + MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, id); else - MyGUI::InputManager::getInstance().injectMouseMove(mouseX, mouseY, mouse->state.Z.abs); + MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, mouse->state.Z.abs); } } diff --git a/libs/openengine/gui/events.hpp b/libs/openengine/gui/events.hpp index 1f506cffa..10c5309bc 100644 --- a/libs/openengine/gui/events.hpp +++ b/libs/openengine/gui/events.hpp @@ -17,6 +17,9 @@ namespace GUI { MyGUI::Gui *gui; + int mMouseX; + int mMouseY; + public: bool enabled; diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 7a01ffce7..b525e76e3 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -155,3 +155,8 @@ void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) { Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); } + +void OgreRenderer::setFov(float fov) +{ + mCamera->setFOVy(Degree(fov)); +} diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 9d1d0122d..f4ea8fbc8 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -124,6 +124,8 @@ namespace OEngine float nearClip=5 // Near clip distance ); + void setFov(float fov); + /// Kill the renderer. void cleanup(); From 69e6bc6588256be514f9dbc054fd8795a20583c7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 06:45:44 +0200 Subject: [PATCH 62/76] add water settings to settings window --- apps/openmw/mwgui/settingswindow.cpp | 38 +++++ apps/openmw/mwgui/settingswindow.hpp | 4 + apps/openmw/mwrender/compositors.cpp | 7 + apps/openmw/mwrender/compositors.hpp | 2 + apps/openmw/mwrender/renderingmanager.cpp | 52 +++++-- apps/openmw/mwrender/renderingmanager.hpp | 4 + apps/openmw/mwrender/water.cpp | 134 +++++++++++++----- apps/openmw/mwrender/water.hpp | 8 ++ files/mygui/openmw_settings_window_layout.xml | 28 ++++ files/water/water.material | 25 ++++ 10 files changed, 252 insertions(+), 50 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 82c8b554f..67ccf9d53 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -64,9 +64,17 @@ namespace MWGui getWidget(mTextureFilteringButton, "TextureFilteringButton"); getWidget(mAnisotropyLabel, "AnisotropyLabel"); getWidget(mAnisotropyBox, "AnisotropyBox"); + getWidget(mWaterShaderButton, "WaterShaderButton"); + getWidget(mReflectObjectsButton, "ReflectObjectsButton"); + getWidget(mReflectActorsButton, "ReflectActorsButton"); + getWidget(mReflectTerrainButton, "ReflectTerrainButton"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mWaterShaderButton->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); mTextureFilteringButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringToggled); mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); @@ -127,6 +135,19 @@ namespace MWGui mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1)); mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); + mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect objects", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}"); + + if (!MWRender::RenderingManager::waterShaderSupported()) + { + mWaterShaderButton->setEnabled(false); + mReflectObjectsButton->setEnabled(false); + mReflectActorsButton->setEnabled(false); + mReflectTerrainButton->setEnabled(false); + } + mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}"); mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}"); mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD"))); @@ -228,6 +249,23 @@ namespace MWGui MWBase::Environment::get().getWindowManager()-> messageBox("VSync will be applied after a restart", std::vector()); } + else + { + if (_sender == mWaterShaderButton) + Settings::Manager::setBool("shader", "Water", newState); + else if (_sender == mReflectObjectsButton) + { + Settings::Manager::setBool("reflect misc", "Water", newState); + Settings::Manager::setBool("reflect statics", "Water", newState); + Settings::Manager::setBool("reflect statics small", "Water", newState); + } + else if (_sender == mReflectActorsButton) + Settings::Manager::setBool("reflect actors", "Water", newState); + else if (_sender == mReflectTerrainButton) + Settings::Manager::setBool("reflect terrain", "Water", newState); + + apply(); + } } void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 8924375d9..ce95edbd2 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -38,6 +38,10 @@ namespace MWGui MyGUI::Button* mTextureFilteringButton; MyGUI::TextBox* mAnisotropyLabel; MyGUI::Widget* mAnisotropyBox; + MyGUI::Button* mWaterShaderButton; + MyGUI::Button* mReflectObjectsButton; + MyGUI::Button* mReflectActorsButton; + MyGUI::Button* mReflectTerrainButton; // audio MyGUI::ScrollBar* mMasterVolumeSlider; diff --git a/apps/openmw/mwrender/compositors.cpp b/apps/openmw/mwrender/compositors.cpp index d786c263b..6f97269ab 100644 --- a/apps/openmw/mwrender/compositors.cpp +++ b/apps/openmw/mwrender/compositors.cpp @@ -62,3 +62,10 @@ void Compositors::setCompositorEnabled (const std::string& name, const bool enab mCompositors[name].first = enabled; Ogre::CompositorManager::getSingleton().setCompositorEnabled (mViewport, name, enabled && mEnabled); } + +void Compositors::removeAll() +{ + Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); + + mCompositors.clear(); +} diff --git a/apps/openmw/mwrender/compositors.hpp b/apps/openmw/mwrender/compositors.hpp index f249ece42..bbd838b8e 100644 --- a/apps/openmw/mwrender/compositors.hpp +++ b/apps/openmw/mwrender/compositors.hpp @@ -44,6 +44,8 @@ namespace MWRender */ void addCompositor (const std::string& name, const int priority); + void removeAll (); + protected: /// maps compositor name to its "enabled" state CompositorMap mCompositors; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 89f42a5f1..a6f10fcd2 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -67,25 +67,13 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // disable unsupported effects const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); - if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) + if (!waterShaderSupported()) Settings::Manager::setBool("shader", "Water", false); if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0")) || !Settings::Manager::getBool("shaders", "Objects")) Settings::Manager::setBool("enabled", "Shadows", false); - // note that the order is important here - if (useMRT()) - { - mCompositors->addCompositor("gbuffer", 0); - mCompositors->setCompositorEnabled("gbuffer", true); - mCompositors->addCompositor("Underwater", 1); - mCompositors->addCompositor("gbufferFinalizer", 2); - mCompositors->setCompositorEnabled("gbufferFinalizer", true); - } - else - { - mCompositors->addCompositor("UnderwaterNoMRT", 0); - } + applyCompositors(); // Turn the entire scene (represented by the 'root' node) -90 // degrees around the x axis. This makes Z go upwards, and Y go into @@ -605,6 +593,11 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); } + else if (it->second == "shader" && it->first == "Water") + { + applyCompositors(); + mShaderHelper->applyShaders(); + } } if (changeRes) @@ -618,6 +611,9 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec } mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } + + if (mWater) + mWater->processChangedSettings(settings); } void RenderingManager::setMenuTransparency(float val) @@ -649,4 +645,32 @@ 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; + return true; +} + +void RenderingManager::applyCompositors() +{ + mCompositors->removeAll(); + if (useMRT()) + { + mCompositors->addCompositor("gbuffer", 0); + mCompositors->setCompositorEnabled("gbuffer", true); + mCompositors->addCompositor("Underwater", 1); + mCompositors->addCompositor("gbufferFinalizer", 2); + mCompositors->setCompositorEnabled("gbufferFinalizer", true); + } + else + { + mCompositors->addCompositor("UnderwaterNoMRT", 0); + } + + if (mWater) + mWater->assignTextures(); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 562184c62..642c42930 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -165,6 +165,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList Ogre::Viewport* getViewport() { return mRendering.getViewport(); } + static bool waterShaderSupported(); + protected: virtual void windowResized(Ogre::RenderWindow* rw); virtual void windowClosed(Ogre::RenderWindow* rw); @@ -175,6 +177,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void setMenuTransparency(float val); + void applyCompositors(); + bool mSunEnabled; SkyManager* mSkyManager; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 981343e91..b4486a0ca 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -1,5 +1,5 @@ #include "water.hpp" -#include + #include "sky.hpp" #include "renderingmanager.hpp" #include "compositors.hpp" @@ -30,13 +30,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mWater->setRenderQueueGroup(RQG_Water); mWater->setCastShadows(false); - mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water") - + RV_Statics * Settings::Manager::getBool("reflect statics", "Water") - + RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water") - + RV_Actors * Settings::Manager::getBool("reflect actors", "Water") - + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") - + RV_Sky; - mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); mWaterNode->setPosition(0, mTop, 0); @@ -48,30 +41,9 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel } mWaterNode->attachObject(mWater); - // Create rendertarget for reflection - int rttsize = Settings::Manager::getInt("rtt size", "Water"); + applyRTT(); + applyVisibilityMask(); - TexturePtr tex; - if (Settings::Manager::getBool("shader", "Water")) - { - tex = TextureManager::getSingleton().createManual("WaterReflection", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET); - - RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); - Viewport* vp = rtt->addViewport(mReflectionCamera); - vp->setOverlaysEnabled(false); - vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); - vp->setShadowsEnabled(false); - vp->setVisibilityMask( mVisibilityFlags ); - // use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain) - //vp->setMaterialScheme("Fallback"); - rtt->addListener(this); - rtt->setActive(true); - - mReflectionTarget = rtt; - } - - mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; createMaterial(); mWater->setMaterial(mMaterial); @@ -251,7 +223,15 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) void Water::createMaterial() { - mMaterial = MaterialManager::getSingleton().getByName("Water"); + if (mReflectionTarget == 0) + { + mMaterial = MaterialManager::getSingleton().getByName("Water_Fallback"); + } + else + { + mMaterial = MaterialManager::getSingleton().getByName("Water"); + mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(mReflectionTexture); + } // these have to be set in code std::string textureNames[32]; @@ -259,11 +239,13 @@ void Water::createMaterial() { textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds"; } - mMaterial->getTechnique(1)->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); - - // use technique without shaders if reflection is disabled + Ogre::Technique* tech; if (mReflectionTarget == 0) - mMaterial->removeTechnique(0); + tech = mMaterial->getTechnique(0); + else + tech = mMaterial->getTechnique(1); + + tech->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); } void Water::assignTextures() @@ -320,4 +302,84 @@ void Water::update() { } +void Water::applyRTT() +{ + if (mReflectionTarget) + { + TextureManager::getSingleton().remove("WaterReflection"); + mReflectionTarget = 0; + } + + // Create rendertarget for reflection + int rttsize = Settings::Manager::getInt("rtt size", "Water"); + + if (Settings::Manager::getBool("shader", "Water")) + { + mReflectionTexture = TextureManager::getSingleton().createManual("WaterReflection", + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, 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 (currently not implemented for sky and terrain) + //vp->setMaterialScheme("Fallback"); + rtt->addListener(this); + rtt->setActive(true); + + mReflectionTarget = rtt; + } + + mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; +} + +void Water::applyVisibilityMask() +{ + mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water") + + RV_Statics * Settings::Manager::getBool("reflect statics", "Water") + + RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water") + + RV_Actors * Settings::Manager::getBool("reflect actors", "Water") + + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") + + RV_Sky; + + if (mReflectionTarget) + { + mReflectionTexture->getBuffer()->getRenderTarget()->getViewport(0)->setVisibilityMask(mVisibilityFlags); + } +} + +void Water::processChangedSettings(const Settings::CategorySettingVector& settings) +{ + bool applyRT = false; + bool applyVisMask = false; + for (Settings::CategorySettingVector::const_iterator it=settings.begin(); + it != settings.end(); ++it) + { + if ( it->first == "Water" && ( + it->second == "shader" + || it->second == "rtt size")) + applyRT = true; + + if ( it->first == "Water" && ( + it->second == "reflect actors" + || it->second == "reflect terrain" + || it->second == "reflect misc" + || it->second == "reflect small statics" + || it->second == "reflect statics")) + applyVisMask = true; + } + + if(applyRT) + { + applyRTT(); + applyVisibilityMask(); + createMaterial(); + mWater->setMaterial(mMaterial); + assignTextures(); + } + if (applyVisMask) + applyVisibilityMask(); +} + } // namespace diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index edd217e84..4d617ea47 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -3,9 +3,11 @@ #include #include +#include #include "renderconst.hpp" + namespace MWRender { class SkyManager; @@ -38,6 +40,9 @@ namespace MWRender { 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(); + void updateVisible(); RenderingManager* mRendering; @@ -50,6 +55,7 @@ namespace MWRender { Ogre::Camera* mReflectionCamera; + Ogre::TexturePtr mReflectionTexture; Ogre::RenderTarget* mReflectionTarget; bool mUnderwaterEffect; @@ -68,6 +74,8 @@ namespace MWRender { void setViewportBackground(const Ogre::ColourValue& bg); + void processChangedSettings(const Settings::CategorySettingVector& settings); + void checkUnderwater(float y); void changeCell(const ESM::Cell* cell); void setHeight(const float height); diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 107e883c4..7c508b1e9 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -153,6 +153,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/water/water.material b/files/water/water.material index 8b4ff96f5..a2a6b3e2d 100644 --- a/files/water/water.material +++ b/files/water/water.material @@ -90,6 +90,31 @@ material Water } } } + + technique + { + scheme Fallback + pass + { + cull_hardware none + scene_blend alpha_blend + depth_write off + diffuse 0 0 0 1 + emissive 0.6 0.7 1.0 + ambient 0 0 0 + texture_unit + { + // texture names set via code + scale 0.1 0.1 + alpha_op_ex source1 src_manual src_current 0.7 + } + } + } + +} + +material Water_Fallback +{ technique { scheme Fallback From c7268233df07351dc7c06251bac1158c64fce23d Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 09:02:22 +0200 Subject: [PATCH 63/76] spell window layout & opening/closing/pinning logic --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/spellwindow.cpp | 20 ++++++++++++++++++++ apps/openmw/mwgui/spellwindow.hpp | 21 +++++++++++++++++++++ apps/openmw/mwgui/window_manager.cpp | 14 ++++++++++---- apps/openmw/mwgui/window_manager.hpp | 2 ++ files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_spell_window_layout.xml | 19 +++++++++++++++++++ 8 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 apps/openmw/mwgui/spellwindow.cpp create mode 100644 apps/openmw/mwgui/spellwindow.hpp create mode 100644 files/mygui/openmw_spell_window_layout.xml diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index edbeab0a1..045f504a7 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -28,7 +28,7 @@ add_openmw_dir (mwgui dialogue_history window_base stats_window messagebox journalwindow charactercreation map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list formatting inventorywindow container hud countdialog tradewindow settingswindow - confirmationdialog alchemywindow referenceinterface + confirmationdialog alchemywindow referenceinterface spellwindow ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 2b224ab2c..1a715657a 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -91,7 +91,7 @@ namespace MWGui mFilterAll->setStateSelected(true); - setCoord(0, 342, 600, 258); + setCoord(0, 342, 498, 258); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); openContainer(player); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp new file mode 100644 index 000000000..9c903134d --- /dev/null +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -0,0 +1,20 @@ +#include "spellwindow.hpp" + +#include "window_manager.hpp" + +namespace MWGui +{ + SpellWindow::SpellWindow(WindowManager& parWindowManager) + : WindowPinnableBase("openmw_spell_window_layout.xml", parWindowManager) + { + getWidget(mSpellView, "SpellView"); + getWidget(mEffectBox, "EffectsBox"); + + setCoord(498, 300, 302, 300); + } + + void SpellWindow::onPinToggled() + { + mWindowManager.setSpellVisibility(!mPinned); + } +} diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp new file mode 100644 index 000000000..0450be473 --- /dev/null +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -0,0 +1,21 @@ +#ifndef MWGUI_SPELLWINDOW_H +#define MWGUI_SPELLWINDOW_H + +#include "window_pinnable_base.hpp" + +namespace MWGui +{ + class SpellWindow : public WindowPinnableBase + { + public: + SpellWindow(WindowManager& parWindowManager); + + protected: + MyGUI::ScrollView* mSpellView; + MyGUI::Widget* mEffectBox; + + virtual void onPinToggled(); + }; +} + +#endif diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 4e786978f..2db71438a 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -19,6 +19,7 @@ #include "settingswindow.hpp" #include "confirmationdialog.hpp" #include "alchemywindow.hpp" +#include "spellwindow.hpp" #include "../mwmechanics/mechanicsmanager.hpp" #include "../mwinput/inputmanager.hpp" @@ -56,6 +57,7 @@ WindowManager::WindowManager( , mSettingsWindow(NULL) , mConfirmationDialog(NULL) , mAlchemyWindow(NULL) + , mSpellWindow(NULL) , mCharGen(NULL) , playerClass() , playerName() @@ -124,6 +126,7 @@ WindowManager::WindowManager( mSettingsWindow = new SettingsWindow(*this); mConfirmationDialog = new ConfirmationDialog(*this); mAlchemyWindow = new AlchemyWindow(*this); + mSpellWindow = new SpellWindow(*this); // The HUD is always on hud->setVisible(true); @@ -167,6 +170,7 @@ WindowManager::~WindowManager() delete mSettingsWindow; delete mConfirmationDialog; delete mAlchemyWindow; + delete mSpellWindow; cleanupGarbage(); } @@ -211,6 +215,7 @@ void WindowManager::updateVisible() mTradeWindow->setVisible(false); mSettingsWindow->setVisible(false); mAlchemyWindow->setVisible(false); + mSpellWindow->setVisible(false); // Mouse is visible whenever we're not in game mode MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); @@ -224,7 +229,7 @@ void WindowManager::updateVisible() setMinimapVisibility((allowed & GW_Map) && !map->pinned()); setWeaponVisibility((allowed & GW_Inventory) && !mInventoryWindow->pinned()); - setSpellVisibility((allowed & GW_Magic)); /// \todo add pin state when spells window is implemented + setSpellVisibility((allowed & GW_Magic) && !mSpellWindow->pinned()); setHMSVisibility((allowed & GW_Stats) && !mStatsWindow->pinned()); // If in game mode, don't show anything. @@ -271,9 +276,10 @@ void WindowManager::updateVisible() int eff = shown & allowed; // Show the windows we want - map -> setVisible( (eff & GW_Map) ); - mStatsWindow -> setVisible( (eff & GW_Stats) ); - mInventoryWindow->setVisible( (eff & GW_Inventory)); + map -> setVisible(eff & GW_Map); + mStatsWindow -> setVisible(eff & GW_Stats); + mInventoryWindow->setVisible(eff & GW_Inventory); + mSpellWindow->setVisible(eff & GW_Magic); break; } case GM_Container: diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index f3e6a436e..872f46f3d 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -81,6 +81,7 @@ namespace MWGui class SettingsWindow; class ConfirmationDialog; class AlchemyWindow; + class SpellWindow; struct ClassPoint { @@ -250,6 +251,7 @@ namespace MWGui SettingsWindow* mSettingsWindow; ConfirmationDialog* mConfirmationDialog; AlchemyWindow* mAlchemyWindow; + SpellWindow* mSpellWindow; CharacterCreation* mCharGen; diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 6b16e5f59..dad4afb46 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -60,6 +60,7 @@ configure_file("${SDIR}/openmw_trade_window_layout.xml" "${DDIR}/openmw_trade_wi configure_file("${SDIR}/openmw_settings_window_layout.xml" "${DDIR}/openmw_settings_window_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_confirmation_dialog_layout.xml" "${DDIR}/openmw_confirmation_dialog_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_alchemy_window_layout.xml" "${DDIR}/openmw_alchemy_window_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_spell_window_layout.xml" "${DDIR}/openmw_spell_window_layout.xml" COPYONLY) configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) diff --git a/files/mygui/openmw_spell_window_layout.xml b/files/mygui/openmw_spell_window_layout.xml new file mode 100644 index 000000000..66a685c38 --- /dev/null +++ b/files/mygui/openmw_spell_window_layout.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + From 5412d6ed9effdc16ad3814a79c77f2a2665b9034 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 10:47:48 +0200 Subject: [PATCH 64/76] fixed a typo that prevented spells from getting added --- apps/openmw/mwmechanics/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index af43cdfb5..70eb78639 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -28,7 +28,7 @@ namespace MWMechanics void Spells::add (const std::string& spellId) { - if (std::find (mSpells.begin(), mSpells.end(), spellId)!=mSpells.end()) + if (std::find (mSpells.begin(), mSpells.end(), spellId)==mSpells.end()) mSpells.push_back (spellId); } From 30461438f62a45abea53100687f148a4c6d53286 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 12:35:03 +0200 Subject: [PATCH 65/76] still left: spell success formula --- apps/openmw/mwgui/container.cpp | 2 + apps/openmw/mwgui/container.hpp | 2 + apps/openmw/mwgui/hud.cpp | 5 +- apps/openmw/mwgui/inventorywindow.cpp | 8 + apps/openmw/mwgui/inventorywindow.hpp | 2 + apps/openmw/mwgui/spellwindow.cpp | 358 +++++++++++++++++++++ apps/openmw/mwgui/spellwindow.hpp | 13 + apps/openmw/mwgui/tooltips.cpp | 5 + apps/openmw/mwgui/window_manager.cpp | 10 +- apps/openmw/mwgui/window_manager.hpp | 1 + apps/openmw/mwworld/containerstore.cpp | 1 + apps/openmw/mwworld/inventorystore.cpp | 13 + apps/openmw/mwworld/inventorystore.hpp | 13 +- files/mygui/openmw_spell_window_layout.xml | 1 + files/mygui/openmw_text.skin.xml | 30 ++ 15 files changed, 456 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 1cfbc1b2b..33ee8bf49 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -535,6 +535,8 @@ void ContainerBase::drawItems() MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x+42), mItemView->getSize().height); mItemView->setCanvasSize(size); mContainerWidget->setSize(size); + + notifyContentChanged(); } std::string ContainerBase::getCountString(const int count) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 5cd8167c2..88e445a7b 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -120,6 +120,8 @@ namespace MWGui virtual bool ignoreEquippedItems() { return false; } virtual std::vector itemsToIgnore() { return std::vector(); } + + virtual void notifyContentChanged() { ; } }; class ContainerWindow : public ContainerBase, public WindowBase diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 7276218d6..fdd1c8821 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -112,6 +112,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) void HUD::setFpsLevel(int level) { + fpscounter = 0; + MyGUI::Widget* fps; getWidget(fps, "FPSBoxAdv"); fps->setVisible(false); @@ -134,7 +136,8 @@ void HUD::setFpsLevel(int level) void HUD::setFPS(float fps) { - fpscounter->setCaption(boost::lexical_cast((int)fps)); + if (fpscounter) + fpscounter->setCaption(boost::lexical_cast((int)fps)); } void HUD::setTriangleCount(size_t count) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 1a715657a..e1d4cc998 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -20,6 +20,7 @@ #include "widgets.hpp" #include "bookwindow.hpp" #include "scrollwindow.hpp" +#include "spellwindow.hpp" namespace { @@ -259,4 +260,11 @@ namespace MWGui { mTrading = true; } + + void InventoryWindow::notifyContentChanged() + { + // update the spell window just in case new enchanted items were added to inventory + if (mWindowManager.getSpellWindow()) + mWindowManager.getSpellWindow()->updateSpells(); + } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index ecff75f10..bc4cb08ef 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -50,6 +50,8 @@ namespace MWGui virtual void _unequipItem(MWWorld::Ptr item); virtual void onReferenceUnavailable() { ; } + + virtual void notifyContentChanged(); }; } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 9c903134d..f761e00db 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -1,20 +1,378 @@ #include "spellwindow.hpp" +#include +#include + +#include "../mwworld/world.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/inventorystore.hpp" +#include "../mwbase/environment.hpp" +#include "../mwmechanics/spells.hpp" +#include "../mwmechanics/creaturestats.hpp" +#include "../mwsound/soundmanager.hpp" + #include "window_manager.hpp" +#include "inventorywindow.hpp" + +namespace +{ + bool sortSpells(const std::string& left, const std::string& right) + { + const ESM::Spell* a = MWBase::Environment::get().getWorld()->getStore().spells.find(left); + const ESM::Spell* b = MWBase::Environment::get().getWorld()->getStore().spells.find(right); + + int cmp = a->name.compare(b->name); + return cmp < 0; + } + + bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right) + { + int cmp = MWWorld::Class::get(left).getName(left).compare( + MWWorld::Class::get(right).getName(right)); + return cmp < 0; + } +} namespace MWGui { SpellWindow::SpellWindow(WindowManager& parWindowManager) : WindowPinnableBase("openmw_spell_window_layout.xml", parWindowManager) + , mHeight(0) + , mWidth(0) { getWidget(mSpellView, "SpellView"); getWidget(mEffectBox, "EffectsBox"); setCoord(498, 300, 302, 300); + updateSpells(); + + mMainWidget->castType()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize); } void SpellWindow::onPinToggled() { mWindowManager.setSpellVisibility(!mPinned); } + + void SpellWindow::open() + { + updateSpells(); + } + + void SpellWindow::updateSpells() + { + const int spellHeight = 18; + + mHeight = 0; + while (mSpellView->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(mSpellView->getChildAt(0)); + + // retrieve all player spells, divide them into Powers and Spells and sort them + std::vector spellList; + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::Spells& spells = stats.mSpells; + + // the following code switches between selected enchanted item and selected spell (only one of these + // can be active at a time) + std::string selectedSpell = spells.getSelectedSpell(); + MWWorld::Ptr selectedItem; + if (store.getSelectedEnchantItem() != store.end()) + { + selectedSpell = ""; + selectedItem = *store.getSelectedEnchantItem(); + + bool allowSelectedItem = true; + + // if the selected item can be equipped, make sure that it actually is equipped + std::pair, bool> slots; + slots = MWWorld::Class::get(selectedItem).getEquipmentSlots(selectedItem); + if (!slots.first.empty()) + { + bool equipped = false; + for (int i=0; i < MWWorld::InventoryStore::Slots; ++i) + { + if (store.getSlot(i) != store.end() && *store.getSlot(i) == selectedItem) + { + equipped = true; + break; + } + } + + if (!equipped) + allowSelectedItem = false; + } + + if (!allowSelectedItem) + { + store.setSelectedEnchantItem(store.end()); + selectedItem = MWWorld::Ptr(); + } + } + + + + for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) + { + spellList.push_back(*it); + } + + std::vector powers; + std::vector::iterator it = spellList.begin(); + while (it != spellList.end()) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + if (spell->data.type == ESM::Spell::ST_Power) + { + powers.push_back(*it); + it = spellList.erase(it); + } + else if (spell->data.type == ESM::Spell::ST_Ability) + { + // abilities are always active and don't show in the spell window. + it = spellList.erase(it); + } + else + ++it; + } + std::sort(powers.begin(), powers.end(), sortSpells); + std::sort(spellList.begin(), spellList.end(), sortSpells); + + // retrieve player's enchanted items + std::vector items; + for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it) + { + std::string enchantId = MWWorld::Class::get(*it).getEnchantment(*it); + if (enchantId != "") + { + // only add items with "Cast once" or "Cast on use" + const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(enchantId); + int type = enchant->data.type; + if (type != ESM::Enchantment::CastOnce + && type != ESM::Enchantment::WhenUsed) + continue; + + items.push_back(*it); + } + } + std::sort(items.begin(), items.end(), sortItems); + + + int height = estimateHeight(items.size() + powers.size() + spellList.size()); + bool scrollVisible = height > mSpellView->getHeight(); + mWidth = mSpellView->getWidth() - (scrollVisible ? 18 : 0); + + // powers + addGroup("#{sPowers}", ""); + + for (std::vector::const_iterator it = powers.begin(); it != powers.end(); ++it) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + MyGUI::Button* t = mSpellView->createWidget("SpellText", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(spell->name); + t->setTextAlign(MyGUI::Align::Left); + t->setUserString("ToolTipType", "Spell"); + t->setUserString("Spell", *it); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected); + + if (*it == selectedSpell) + t->setStateSelected(true); + + mHeight += spellHeight; + } + + // other spells + addGroup("#{sSpells}", "#{sCostChance}"); + for (std::vector::const_iterator it = spellList.begin(); it != spellList.end(); ++it) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it); + MyGUI::Button* t = mSpellView->createWidget("SpellText", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(spell->name); + t->setTextAlign(MyGUI::Align::Left); + t->setUserString("ToolTipType", "Spell"); + t->setUserString("Spell", *it); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected); + + if (*it == selectedSpell) + t->setStateSelected(true); + + // cost / success chance + MyGUI::TextBox* costChance = mSpellView->createWidget("SpellText", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + std::string cost = boost::lexical_cast(spell->data.cost); + costChance->setCaption(cost + "/" + "100"); /// \todo + costChance->setTextAlign(MyGUI::Align::Right); + costChance->setNeedMouseFocus(false); + + + mHeight += spellHeight; + } + + + // enchanted items + addGroup("#{sMagicItem}", "#{sCostCharge}"); + + for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) + { + MWWorld::Ptr item = *it; + + // check if the item is currently equipped (will display in a different color) + bool equipped = false; + for (int i=0; i < MWWorld::InventoryStore::Slots; ++i) + { + if (store.getSlot(i) != store.end() && *store.getSlot(i) == item) + { + equipped = true; + break; + } + } + + MyGUI::Button* t = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + t->setCaption(MWWorld::Class::get(item).getName(item)); + t->setTextAlign(MyGUI::Align::Left); + t->setUserData(item); + t->setUserString("ToolTipType", "ItemPtr"); + t->setUserString("Equipped", equipped ? "true" : "false"); + t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onEnchantedItemSelected); + t->setStateSelected(item == selectedItem); + + // cost / charge + MyGUI::TextBox* costCharge = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", + MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); + + const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item)); + std::string cost = boost::lexical_cast(enchant->data.cost); + std::string charge = boost::lexical_cast(enchant->data.charge); /// \todo track current charge + costCharge->setCaption(cost + "/" + charge); + costCharge->setTextAlign(MyGUI::Align::Right); + costCharge->setNeedMouseFocus(false); + + mHeight += spellHeight; + } + + mSpellView->setCanvasSize(mSpellView->getWidth(), std::max(mSpellView->getHeight(), mHeight)); + } + + void SpellWindow::addGroup(const std::string &label, const std::string& label2) + { + if (mSpellView->getChildCount() > 0) + { + MyGUI::ImageBox* separator = mSpellView->createWidget("MW_HLine", + MyGUI::IntCoord(4, mHeight, mWidth-8, 18), + MyGUI::Align::Left | MyGUI::Align::Top); + separator->setNeedMouseFocus(false); + mHeight += 18; + } + + MyGUI::TextBox* groupWidget = mSpellView->createWidget("SandBrightText", + MyGUI::IntCoord(0, mHeight, mWidth, 24), + MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); + groupWidget->setCaptionWithReplacing(label); + groupWidget->setTextAlign(MyGUI::Align::Left); + groupWidget->setNeedMouseFocus(false); + + if (label2 != "") + { + MyGUI::TextBox* groupWidget2 = mSpellView->createWidget("SandBrightText", + MyGUI::IntCoord(0, mHeight, mWidth-4, 24), + MyGUI::Align::Left | MyGUI::Align::Top); + groupWidget2->setCaptionWithReplacing(label2); + groupWidget2->setTextAlign(MyGUI::Align::Right); + groupWidget2->setNeedMouseFocus(false); + } + + mHeight += 24; + } + + void SpellWindow::onWindowResize(MyGUI::Window* _sender) + { + updateSpells(); + } + + void SpellWindow::onEnchantedItemSelected(MyGUI::Widget* _sender) + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWMechanics::Spells& spells = stats.mSpells; + MWWorld::Ptr item = *_sender->getUserData(); + + // retrieve ContainerStoreIterator to the item + MWWorld::ContainerStoreIterator it = store.begin(); + for (; it != store.end(); ++it) + { + if (*it == item) + { + break; + } + } + assert(it != store.end()); + + // equip, if it is not already equipped + if (_sender->getUserString("Equipped") == "false") + { + // sound + MWBase::Environment::get().getSoundManager()->playSound(MWWorld::Class::get(item).getUpSoundId(item), 1.0, 1.0); + + // Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping + + /// \todo the following code is pretty much copy&paste from ActionEquip, put it in a function? + // slots that this item can be equipped in + std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); + + + // equip the item in the first free slot + for (std::vector::const_iterator slot=slots.first.begin(); + slot!=slots.first.end(); ++slot) + { + // if all slots are occupied, replace the last slot + if (slot == --slots.first.end()) + { + store.equip(*slot, it); + break; + } + + if (store.getSlot(*slot) == store.end()) + { + // slot is not occupied + store.equip(*slot, it); + break; + } + } + /// \todo scripts? + + // since we changed equipping status, update the inventory window + mWindowManager.getInventoryWindow()->drawItems(); + } + + store.setSelectedEnchantItem(it); + spells.setSelectedSpell(""); + + updateSpells(); + } + + void SpellWindow::onSpellSelected(MyGUI::Widget* _sender) + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); + MWMechanics::Spells& spells = stats.mSpells; + + spells.setSelectedSpell(_sender->getUserString("Spell")); + store.setSelectedEnchantItem(store.end()); + + updateSpells(); + } + + int SpellWindow::estimateHeight(int numSpells) const + { + int height = 0; + height += 24 * 3 + 18 * 2; // group headings + height += numSpells * 18; + return height; + } } diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 0450be473..16a1c7ff8 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -10,11 +10,24 @@ namespace MWGui public: SpellWindow(WindowManager& parWindowManager); + void updateSpells(); + protected: MyGUI::ScrollView* mSpellView; MyGUI::Widget* mEffectBox; + int mHeight; + int mWidth; + + void addGroup(const std::string& label, const std::string& label2); + + int estimateHeight(int numSpells) const; + virtual void onPinToggled(); + void onWindowResize(MyGUI::Window* _sender); + void onEnchantedItemSelected(MyGUI::Widget* _sender); + void onSpellSelected(MyGUI::Widget* _sender); + virtual void open(); }; } diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index bdce61a44..dc34ee86c 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -67,6 +67,11 @@ void ToolTips::onFrame(float frameDuration) if (!mGameMode) { const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); + const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); + + if (mousePos == lastPressed) // mouseclick makes tooltip disappear + return; + if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) { mRemainingDelay -= frameDuration; diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 2db71438a..4eaaf72a4 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -191,12 +191,10 @@ void WindowManager::cleanupGarbage() void WindowManager::update() { cleanupGarbage(); - if (showFPSLevel > 0) - { - hud->setFPS(mFPS); - hud->setTriangleCount(mTriangleCount); - hud->setBatchCount(mBatchCount); - } + + hud->setFPS(mFPS); + hud->setTriangleCount(mTriangleCount); + hud->setBatchCount(mBatchCount); } void WindowManager::updateVisible() diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 872f46f3d..2a7794f70 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -154,6 +154,7 @@ namespace MWGui MWGui::CountDialog* getCountDialog() {return mCountDialog;} MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;} MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} + MWGui::SpellWindow* getSpellWindow() {return mSpellWindow;} MyGUI::Gui* getGui() const { return gui; } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index b669508b2..3304d0e6d 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -61,6 +61,7 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) /// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented if ( ptr1.mCellRef->refID == ptr2.mCellRef->refID && MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks + && MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier) && ptr1.mCellRef->owner == ptr2.mCellRef->owner && ptr1.mCellRef->soul == ptr2.mCellRef->soul && ptr1.mCellRef->charge == ptr2.mCellRef->charge) diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 98ab1665b..6df73004b 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -39,15 +39,18 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots) } MWWorld::InventoryStore::InventoryStore() : mMagicEffectsUpToDate (false) + , mSelectedEnchantItem(end()) { initSlots (mSlots); } MWWorld::InventoryStore::InventoryStore (const InventoryStore& store) : ContainerStore (store) + , mSelectedEnchantItem(end()) { mMagicEffects = store.mMagicEffects; mMagicEffectsUpToDate = store.mMagicEffectsUpToDate; + mSelectedEnchantItem = store.mSelectedEnchantItem; copySlots (store); } @@ -260,3 +263,13 @@ bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) return true; } + +void MWWorld::InventoryStore::setSelectedEnchantItem(const ContainerStoreIterator& iterator) +{ + mSelectedEnchantItem = iterator; +} + +MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSelectedEnchantItem() +{ + return mSelectedEnchantItem; +} diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index dcfb21f30..45b3cab26 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -50,6 +50,9 @@ namespace MWWorld mutable TSlots mSlots; + // selected magic item (for using enchantments of type "Cast once" or "Cast when used") + ContainerStoreIterator mSelectedEnchantItem; + void copySlots (const InventoryStore& store); void initSlots (TSlots& slots); @@ -63,7 +66,15 @@ namespace MWWorld InventoryStore& operator= (const InventoryStore& store); void equip (int slot, const ContainerStoreIterator& iterator); - ///< \note \a iteartor can be an end-iterator + ///< \note \a iterator can be an end-iterator + + void setSelectedEnchantItem(const ContainerStoreIterator& iterator); + ///< set the selected magic item (for using enchantments of type "Cast once" or "Cast when used") + /// \note to unset the selected item, call this method with end() iterator + + ContainerStoreIterator getSelectedEnchantItem(); + ///< @return selected magic item (for using enchantments of type "Cast once" or "Cast when used") + /// \note if no item selected, return end() iterator ContainerStoreIterator getSlot (int slot); diff --git a/files/mygui/openmw_spell_window_layout.xml b/files/mygui/openmw_spell_window_layout.xml index 66a685c38..d489f41b8 100644 --- a/files/mygui/openmw_spell_window_layout.xml +++ b/files/mygui/openmw_spell_window_layout.xml @@ -12,6 +12,7 @@ + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index bfa970de5..e29483e35 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -99,6 +99,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 48ba293e88febaed2d0efaca9fac7c5f5eeaac83 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 15:13:44 +0200 Subject: [PATCH 66/76] added the success formula, and spell deleting (shift+click) --- apps/openmw/mwgui/spellwindow.cpp | 83 ++++++++++++++++++++---- apps/openmw/mwgui/spellwindow.hpp | 7 +- apps/openmw/mwmechanics/spellsuccess.hpp | 83 ++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 13 deletions(-) create mode 100644 apps/openmw/mwmechanics/spellsuccess.hpp diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index f761e00db..168578831 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" @@ -9,10 +10,12 @@ #include "../mwbase/environment.hpp" #include "../mwmechanics/spells.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/spellsuccess.hpp" #include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" #include "inventorywindow.hpp" +#include "confirmationdialog.hpp" namespace { @@ -175,6 +178,7 @@ namespace MWGui t->setTextAlign(MyGUI::Align::Left); t->setUserString("ToolTipType", "Spell"); t->setUserString("Spell", *it); + t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel); t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected); if (*it == selectedSpell) @@ -194,18 +198,19 @@ namespace MWGui t->setTextAlign(MyGUI::Align::Left); t->setUserString("ToolTipType", "Spell"); t->setUserString("Spell", *it); + t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel); t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected); - - if (*it == selectedSpell) - t->setStateSelected(true); + t->setStateSelected(*it == selectedSpell); // cost / success chance - MyGUI::TextBox* costChance = mSpellView->createWidget("SpellText", + MyGUI::Button* costChance = mSpellView->createWidget("SpellText", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); std::string cost = boost::lexical_cast(spell->data.cost); - costChance->setCaption(cost + "/" + "100"); /// \todo + std::string chance = boost::lexical_cast(int(MWMechanics::getSpellSuccessChance(*it, player))); + costChance->setCaption(cost + "/" + chance); costChance->setTextAlign(MyGUI::Align::Right); costChance->setNeedMouseFocus(false); + costChance->setStateSelected(*it == selectedSpell); mHeight += spellHeight; @@ -219,6 +224,8 @@ namespace MWGui { MWWorld::Ptr item = *it; + const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item)); + // check if the item is currently equipped (will display in a different color) bool equipped = false; for (int i=0; i < MWWorld::InventoryStore::Slots; ++i) @@ -238,18 +245,26 @@ namespace MWGui t->setUserString("ToolTipType", "ItemPtr"); t->setUserString("Equipped", equipped ? "true" : "false"); t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onEnchantedItemSelected); + t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel); t->setStateSelected(item == selectedItem); // cost / charge - MyGUI::TextBox* costCharge = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", + MyGUI::Button* costCharge = mSpellView->createWidget(equipped ? "SpellText" : "SpellTextUnequipped", MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top); - const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item)); std::string cost = boost::lexical_cast(enchant->data.cost); std::string charge = boost::lexical_cast(enchant->data.charge); /// \todo track current charge + if (enchant->data.type != ESM::Enchantment::CastOnce) + { + // this is Morrowind behaviour + cost = "100"; + charge = "100"; + } + costCharge->setCaption(cost + "/" + charge); costCharge->setTextAlign(MyGUI::Align::Right); costCharge->setNeedMouseFocus(false); + costCharge->setStateSelected(item == selectedItem); mHeight += spellHeight; } @@ -312,8 +327,9 @@ namespace MWGui } assert(it != store.end()); - // equip, if it is not already equipped - if (_sender->getUserString("Equipped") == "false") + // equip, if it can be equipped and is not already equipped + if (_sender->getUserString("Equipped") == "false" + && !MWWorld::Class::get(item).getEquipmentSlots(item).first.empty()) { // sound MWBase::Environment::get().getSoundManager()->playSound(MWWorld::Class::get(item).getUpSoundId(item), 1.0, 1.0); @@ -324,7 +340,6 @@ namespace MWGui // slots that this item can be equipped in std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); - // equip the item in the first free slot for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) @@ -362,8 +377,33 @@ namespace MWGui MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); MWMechanics::Spells& spells = stats.mSpells; - spells.setSelectedSpell(_sender->getUserString("Spell")); - store.setSelectedEnchantItem(store.end()); + if (MyGUI::InputManager::getInstance().isShiftPressed()) + { + // delete spell, if allowed + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(_sender->getUserString("Spell")); + if (spell->data.flags & ESM::Spell::F_Always + || spell->data.type == ESM::Spell::ST_Power) + { + mWindowManager.messageBox("#{sDeleteSpellError}", std::vector()); + } + else + { + // ask for confirmation + mSpellToDelete = _sender->getUserString("Spell"); + ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); + std::string question = mWindowManager.getGameSettingString("sQuestionDeleteSpell", "Delete %s?"); + question = boost::str(boost::format(question) % spell->name); + dialog->open(question); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept); + dialog->eventCancelClicked.clear(); + } + } + else + { + spells.setSelectedSpell(_sender->getUserString("Spell")); + store.setSelectedEnchantItem(store.end()); + } updateSpells(); } @@ -375,4 +415,23 @@ namespace MWGui height += numSpells * 18; return height; } + + void SpellWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) + { + if (mSpellView->getViewOffset().top + _rel*0.3 > 0) + mSpellView->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mSpellView->setViewOffset(MyGUI::IntPoint(0, mSpellView->getViewOffset().top + _rel*0.3)); + } + + void SpellWindow::onDeleteSpellAccept() + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::Spells& spells = stats.mSpells; + + spells.remove(mSpellToDelete); + + updateSpells(); + } } diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 16a1c7ff8..87e4783ba 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -19,14 +19,19 @@ namespace MWGui int mHeight; int mWidth; + std::string mSpellToDelete; + void addGroup(const std::string& label, const std::string& label2); int estimateHeight(int numSpells) const; - virtual void onPinToggled(); void onWindowResize(MyGUI::Window* _sender); void onEnchantedItemSelected(MyGUI::Widget* _sender); void onSpellSelected(MyGUI::Widget* _sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + void onDeleteSpellAccept(); + + virtual void onPinToggled(); virtual void open(); }; } diff --git a/apps/openmw/mwmechanics/spellsuccess.hpp b/apps/openmw/mwmechanics/spellsuccess.hpp new file mode 100644 index 000000000..532f9eb4e --- /dev/null +++ b/apps/openmw/mwmechanics/spellsuccess.hpp @@ -0,0 +1,83 @@ +#ifndef MWMECHANICS_SPELLSUCCESS_H +#define MWMECHANICS_SPELLSUCCESS_H + +#include "../mwworld/ptr.hpp" +#include "../mwworld/world.hpp" +#include "../mwbase/environment.hpp" + +#include "npcstats.hpp" + +namespace MWMechanics +{ + // UESP wiki / Morrowind/Spells: + // Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2 + + /** + * @param spellId ID of spell + * @param actor calculate spell success chance for this actor (depends on actor's skills) + * @attention actor has to be an NPC and not a creature! + * @return success chance from 0 to 100 (in percent) + */ + float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + + if (spell->data.flags & ESM::Spell::F_Always) // spells with this flag always succeed (usually birthsign spells) + return 100.0; + + NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); + CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); + + std::map schoolSkillMap; // maps spell school to skill id + schoolSkillMap[0] = 11; // alteration + schoolSkillMap[1] = 13; // conjuration + schoolSkillMap[3] = 12; // illusion + schoolSkillMap[2] = 10; // destruction + schoolSkillMap[4] = 14; // mysticism + schoolSkillMap[5] = 15; // restoration + + // determine the spell's school + // this is always the school where the player's respective skill is the least advanced + // out of all the magic effects' schools + const std::vector& effects = spell->effects.list; + int skill = -1; + int skillLevel = -1; + for (std::vector::const_iterator it = effects.begin(); + it != effects.end(); ++it) + { + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(it->effectID); + int school = effect->data.school; + assert(schoolSkillMap.find(school) != schoolSkillMap.end()); + int _skillLevel = stats.mSkill[schoolSkillMap[school]].getModified(); + + if (skill == -1) + { + skill = schoolSkillMap[school]; + skillLevel = _skillLevel; + } + else if (_skillLevel < skillLevel) + { + skill = schoolSkillMap[school]; + skillLevel = _skillLevel; + } + } + + // Sound magic effect (reduces spell casting chance) + int soundMagnitude = creatureStats.mMagicEffects.get (MWMechanics::EffectKey (48)).mMagnitude; + + int willpower = creatureStats.mAttributes[ESM::Attribute::Willpower].getModified(); + int luck = creatureStats.mAttributes[ESM::Attribute::Luck].getModified(); + int currentFatigue = creatureStats.mDynamic[2].getCurrent(); + int maxFatigue = creatureStats.mDynamic[2].getModified(); + int spellCost = spell->data.cost; + + // There we go, all needed variables are there, lets go + float chance = (float(skillLevel * 2) + float(willpower)/5.0 + float(luck)/ 10.0 - spellCost - soundMagnitude) * (float(currentFatigue + maxFatigue * 1.5)) / float(maxFatigue * 2.0); + + chance = std::max(0.0f, std::min(100.0f, chance)); // clamp to 0 .. 100 + + return chance; + } +} + +#endif From 8b7baa808e719663f65e4ba08c80f416ac0e45bc Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 15:36:48 +0200 Subject: [PATCH 67/76] fixed the hud icon positioning issues --- apps/openmw/mwgui/hud.cpp | 17 +++++++++++------ apps/openmw/mwgui/hud.hpp | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index fdd1c8821..6b0cdbd5c 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -48,11 +48,12 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) setCoord(0,0, width, height); // Energy bars + getWidget(mHealthFrame, "HealthFrame"); getWidget(health, "Health"); getWidget(magicka, "Magicka"); getWidget(stamina, "Stamina"); - hmsBaseLeft = health->getLeft(); + hmsBaseLeft = mHealthFrame->getLeft(); MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame; getWidget(healthFrame, "HealthFrame"); @@ -62,6 +63,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) magickaFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); fatigueFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked); + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + // Item and spell images and status bars getWidget(weapBox, "WeapBox"); getWidget(weapImage, "WeapImage"); @@ -77,11 +80,11 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(effectBox, "EffectBox"); getWidget(effect1, "Effect1"); - effectBoxBaseRight = effectBox->getRight(); + effectBoxBaseRight = viewSize.width - effectBox->getRight(); effectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked); getWidget(minimapBox, "MiniMapBox"); - minimapBoxBaseRight = minimapBox->getRight(); + minimapBoxBaseRight = viewSize.width - minimapBox->getRight(); minimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked); getWidget(minimap, "MiniMap"); getWidget(compass, "Compass"); @@ -220,7 +223,7 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft; if (!weapVisible) - spellDx -= spellBoxBaseLeft - weapBoxBaseLeft; + spellDx += spellBoxBaseLeft - weapBoxBaseLeft; health->setVisible(hmsVisible); stamina->setVisible(hmsVisible); @@ -233,14 +236,16 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible) { + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + // effect box can have variable width -> variable left coordinate int effectsDx = 0; if (!minimapBoxVisible) - effectsDx = minimapBoxBaseRight - effectBoxBaseRight; + effectsDx = (viewSize.width - minimapBoxBaseRight) - (viewSize.width - effectBoxBaseRight); mMapVisible = minimapBoxVisible; minimapBox->setVisible(minimapBoxVisible); - effectBox->setPosition(effectBoxBaseRight - effectBox->getWidth() + effectsDx, effectBox->getTop()); + effectBox->setPosition((viewSize.width - effectBoxBaseRight) - effectBox->getWidth() + effectsDx, effectBox->getTop()); effectBox->setVisible(effectBoxVisible); } diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 16749114c..6d4bf0559 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -31,6 +31,7 @@ namespace MWGui void setCellName(const std::string& cellName); MyGUI::ProgressPtr health, magicka, stamina; + MyGUI::Widget* mHealthFrame; MyGUI::Widget *weapBox, *spellBox; MyGUI::ImageBox *weapImage, *spellImage; MyGUI::ProgressPtr weapStatus, spellStatus; From 298ae4f7f8c8cde5d689c3b5013854f95a183493 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 18:33:01 +0200 Subject: [PATCH 68/76] HUD icons for selected weapon / selected spell / selected enchanted item --- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/hud.cpp | 171 +++++++++++++++++++---- apps/openmw/mwgui/hud.hpp | 16 ++- apps/openmw/mwgui/inventorywindow.cpp | 18 +++ apps/openmw/mwgui/spellwindow.cpp | 17 ++- apps/openmw/mwgui/tooltips.cpp | 1 - apps/openmw/mwgui/tradewindow.cpp | 2 + apps/openmw/mwgui/window_manager.cpp | 25 ++++ apps/openmw/mwgui/window_manager.hpp | 6 + apps/openmw/mwmechanics/spellsuccess.hpp | 66 +++++---- files/mygui/openmw_hud_layout.xml | 8 ++ 11 files changed, 270 insertions(+), 62 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 33ee8bf49..bf6b4add0 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -347,7 +347,6 @@ void ContainerBase::setFilter(ContainerBase::Filter filter) void ContainerBase::openContainer(MWWorld::Ptr container) { mPtr = container; - drawItems(); } void ContainerBase::drawItems() @@ -638,6 +637,7 @@ void ContainerWindow::open(MWWorld::Ptr container) { openContainer(container); setTitle(MWWorld::Class::get(container).getName(container)); + drawItems(); } void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 6b0cdbd5c..95017579b 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -90,6 +90,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(compass, "Compass"); getWidget(mCellNameBox, "CellName"); + getWidget(mWeaponSpellBox, "WeaponSpellName"); getWidget(crosshair, "Crosshair"); @@ -98,14 +99,11 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) getWidget(trianglecounter, "TriangleCounter"); getWidget(batchcounter, "BatchCounter"); - // These are just demo values, you should replace these with - // real calls from outside the class later. - setWeapIcon("icons\\w\\tx_knife_iron.dds"); - setWeapStatus(90, 100); - setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds"); - setSpellStatus(65, 100); setEffect("icons\\s\\tx_s_chameleon.dds"); + unsetSelectedSpell(); + unsetSelectedWeapon(); + LocalMapBase::init(minimap, compass, this); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); @@ -153,28 +151,6 @@ void HUD::setBatchCount(size_t count) batchcounter->setCaption(boost::lexical_cast(count)); } -void HUD::setWeapIcon(const char *str) -{ - weapImage->setImageTexture(str); -} - -void HUD::setSpellIcon(const char *str) -{ - spellImage->setImageTexture(str); -} - -void HUD::setWeapStatus(int s, int smax) -{ - weapStatus->setProgressRange(smax); - weapStatus->setProgressPosition(s); -} - -void HUD::setSpellStatus(int s, int smax) -{ - spellStatus->setProgressRange(smax); - spellStatus->setProgressPosition(s); -} - void HUD::setEffect(const char *img) { effect1->setImageTexture(img); @@ -354,11 +330,150 @@ void HUD::setCellName(const std::string& cellName) void HUD::onFrame(float dt) { mCellNameTimer -= dt; + mWeaponSpellTimer -= dt; if (mCellNameTimer < 0) mCellNameBox->setVisible(false); + if (mWeaponSpellTimer < 0) + mWeaponSpellBox->setVisible(false); } void HUD::onResChange(int width, int height) { setCoord(0, 0, width, height); } + +void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) +{ + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + std::string spellName = spell->name; + if (spellName != mSpellName) + { + mWeaponSpellTimer = 5.0f; + mSpellName = spellName; + mWeaponSpellBox->setCaption(mSpellName); + mWeaponSpellBox->setVisible(true); + } + + spellStatus->setProgressRange(100); + spellStatus->setProgressPosition(successChancePercent); + + if (spellImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0)); + + spellBox->setUserString("ToolTipType", "Spell"); + spellBox->setUserString("Spell", spellId); + + // use the icon of the first effect + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(spell->effects.list.front().effectID); + std::string icon = effect->icon; + int slashPos = icon.find("\\"); + icon.insert(slashPos+1, "b_"); + icon = std::string("icons\\") + icon; + Widgets::fixTexturePath(icon); + spellImage->setImageTexture(icon); +} + +void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) +{ + std::string itemName = MWWorld::Class::get(item).getName(item); + if (itemName != mSpellName) + { + mWeaponSpellTimer = 5.0f; + mSpellName = itemName; + mWeaponSpellBox->setCaption(mSpellName); + mWeaponSpellBox->setVisible(true); + } + + spellStatus->setProgressRange(100); + spellStatus->setProgressPosition(chargePercent); + + if (spellImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0)); + + spellBox->setUserString("ToolTipType", "ItemPtr"); + spellBox->setUserData(item); + + spellImage->setImageTexture("textures\\menu_icon_magic_mini.dds"); + MyGUI::ImageBox* itemBox = spellImage->createWidgetReal("ImageBox", MyGUI::FloatCoord(0,0,1,1) + , MyGUI::Align::Stretch); + + std::string path = std::string("icons\\"); + path+=MWWorld::Class::get(item).getInventoryIcon(item); + Widgets::fixTexturePath(path); + itemBox->setImageTexture(path); + itemBox->setNeedMouseFocus(false); +} + +void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) +{ + std::string itemName = MWWorld::Class::get(item).getName(item); + if (itemName != mWeaponName) + { + mWeaponSpellTimer = 5.0f; + mWeaponName = itemName; + mWeaponSpellBox->setCaption(mWeaponName); + mWeaponSpellBox->setVisible(true); + } + + weapBox->setUserString("ToolTipType", "ItemPtr"); + weapBox->setUserData(item); + + weapStatus->setProgressRange(100); + weapStatus->setProgressPosition(durabilityPercent); + + if (weapImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(weapImage->getChildAt(0)); + + std::string path = std::string("icons\\"); + path+=MWWorld::Class::get(item).getInventoryIcon(item); + Widgets::fixTexturePath(path); + + if (MWWorld::Class::get(item).getEnchantment(item) != "") + { + weapImage->setImageTexture("textures\\menu_icon_magic_mini.dds"); + MyGUI::ImageBox* itemBox = weapImage->createWidgetReal("ImageBox", MyGUI::FloatCoord(0,0,1,1) + , MyGUI::Align::Stretch); + itemBox->setImageTexture(path); + itemBox->setNeedMouseFocus(false); + } + else + weapImage->setImageTexture(path); +} + +void HUD::unsetSelectedSpell() +{ + std::string spellName = "#{sNone}"; + if (spellName != mSpellName) + { + mWeaponSpellTimer = 5.0f; + mSpellName = spellName; + mWeaponSpellBox->setCaptionWithReplacing(mSpellName); + mWeaponSpellBox->setVisible(true); + } + + if (spellImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0)); + spellStatus->setProgressRange(100); + spellStatus->setProgressPosition(0); + spellImage->setImageTexture(""); + spellBox->clearUserStrings(); +} + +void HUD::unsetSelectedWeapon() +{ + std::string itemName = "#{sSkillHandtohand}"; + if (itemName != mWeaponName) + { + mWeaponSpellTimer = 5.0f; + mWeaponName = itemName; + mWeaponSpellBox->setCaptionWithReplacing(mWeaponName); + mWeaponSpellBox->setVisible(true); + } + + if (weapImage->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(weapImage->getChildAt(0)); + weapStatus->setProgressRange(100); + weapStatus->setProgressPosition(0); + weapImage->setImageTexture("icons\\k\\stealth_handtohand.dds"); + weapBox->clearUserStrings(); +} diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 6d4bf0559..f51110637 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -3,6 +3,7 @@ #include #include "../mwmechanics/stat.hpp" +#include "../mwworld/ptr.hpp" namespace MWGui { @@ -12,10 +13,6 @@ namespace MWGui { public: HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); - void setWeapIcon(const char *str); - void setSpellIcon(const char *str); - void setWeapStatus(int s, int smax); - void setSpellStatus(int s, int smax); void setEffect(const char *img); void setValue (const std::string& id, const MWMechanics::DynamicStat& value); void setFPS(float fps); @@ -25,6 +22,12 @@ namespace MWGui void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); void setFpsLevel(const int level); + void setSelectedSpell(const std::string& spellId, int successChancePercent); + void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent); + void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent); + void unsetSelectedSpell(); + void unsetSelectedWeapon(); + void onFrame(float dt); void onResChange(int width, int height); @@ -41,6 +44,7 @@ namespace MWGui MyGUI::ImageBox* compass; MyGUI::ImageBox* crosshair; MyGUI::TextBox* mCellNameBox; + MyGUI::TextBox* mWeaponSpellBox; MyGUI::WidgetPtr fpsbox; MyGUI::TextBox* fpscounter; @@ -58,6 +62,10 @@ namespace MWGui std::string mCellName; float mCellNameTimer; + std::string mWeaponName; + std::string mSpellName; + float mWeaponSpellTimer; + bool mMapVisible; void onWorldClicked(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e1d4cc998..103f5ebf3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -188,6 +188,15 @@ namespace MWGui mWindowManager.setDragDrop(false); drawItems(); + + // update selected weapon icon + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weaponSlot == invStore.end()) + mWindowManager.unsetSelectedWeapon(); + else + mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + } } @@ -266,5 +275,14 @@ namespace MWGui // update the spell window just in case new enchanted items were added to inventory if (mWindowManager.getSpellWindow()) mWindowManager.getSpellWindow()->updateSpells(); + + // update selected weapon icon + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weaponSlot == invStore.end()) + mWindowManager.unsetSelectedWeapon(); + else + mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + } } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 168578831..aae3d878d 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -110,6 +110,8 @@ namespace MWGui if (!allowSelectedItem) { store.setSelectedEnchantItem(store.end()); + spells.setSelectedSpell(""); + mWindowManager.unsetSelectedSpell(); selectedItem = MWWorld::Ptr(); } } @@ -366,12 +368,14 @@ namespace MWGui store.setSelectedEnchantItem(it); spells.setSelectedSpell(""); + mWindowManager.setSelectedEnchantItem(item, 100); /// \todo track charge % updateSpells(); } void SpellWindow::onSpellSelected(MyGUI::Widget* _sender) { + std::string spellId = _sender->getUserString("Spell"); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player); @@ -380,7 +384,7 @@ namespace MWGui if (MyGUI::InputManager::getInstance().isShiftPressed()) { // delete spell, if allowed - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(_sender->getUserString("Spell")); + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); if (spell->data.flags & ESM::Spell::F_Always || spell->data.type == ESM::Spell::ST_Power) { @@ -389,7 +393,7 @@ namespace MWGui else { // ask for confirmation - mSpellToDelete = _sender->getUserString("Spell"); + mSpellToDelete = spellId; ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); std::string question = mWindowManager.getGameSettingString("sQuestionDeleteSpell", "Delete %s?"); question = boost::str(boost::format(question) % spell->name); @@ -401,8 +405,9 @@ namespace MWGui } else { - spells.setSelectedSpell(_sender->getUserString("Spell")); + spells.setSelectedSpell(spellId); store.setSelectedEnchantItem(store.end()); + mWindowManager.setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); } updateSpells(); @@ -430,6 +435,12 @@ namespace MWGui MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); MWMechanics::Spells& spells = stats.mSpells; + if (spells.getSelectedSpell() == mSpellToDelete) + { + spells.setSelectedSpell(""); + mWindowManager.unsetSelectedSpell(); + } + spells.remove(mSpellToDelete); updateSpells(); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index dc34ee86c..0f6892190 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -402,7 +402,6 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) TextBox* chargeText = enchantArea->createWidget("SandText", IntCoord(0, 0, 10, 18), Align::Default, "ToolTipEnchantChargeText"); chargeText->setCaption(store.gameSettings.search("sCharges")->str); - chargeText->setProperty("Static", "true"); const int chargeTextWidth = chargeText->getTextSize().width + 5; const int chargeAndTextWidth = chargeWidth + chargeTextWidth; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 0a12a82a0..2089ed4af 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -104,6 +104,8 @@ namespace MWGui ContainerBase::openContainer(actor); updateLabels(); + + drawItems(); } void TradeWindow::onFilterChanged(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 4eaaf72a4..bd1ad46b6 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -674,3 +674,28 @@ void WindowManager::removeGuiMode(GuiMode mode) updateVisible(); } + +void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent) +{ + hud->setSelectedSpell(spellId, successChancePercent); +} + +void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) +{ + hud->setSelectedEnchantItem(item, chargePercent); +} + +void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) +{ + hud->setSelectedWeapon(item, durabilityPercent); +} + +void WindowManager::unsetSelectedSpell() +{ + hud->unsetSelectedSpell(); +} + +void WindowManager::unsetSelectedWeapon() +{ + hud->unsetSelectedWeapon(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 2a7794f70..037022b42 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -204,6 +204,12 @@ namespace MWGui void setWeaponVisibility(bool visible); void setSpellVisibility(bool visible); + void setSelectedSpell(const std::string& spellId, int successChancePercent); + void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent); + void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent); + void unsetSelectedSpell(); + void unsetSelectedWeapon(); + template void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr. void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. diff --git a/apps/openmw/mwmechanics/spellsuccess.hpp b/apps/openmw/mwmechanics/spellsuccess.hpp index 532f9eb4e..11ac7cda7 100644 --- a/apps/openmw/mwmechanics/spellsuccess.hpp +++ b/apps/openmw/mwmechanics/spellsuccess.hpp @@ -4,30 +4,14 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/world.hpp" #include "../mwbase/environment.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "npcstats.hpp" namespace MWMechanics { - // UESP wiki / Morrowind/Spells: - // Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2 - - /** - * @param spellId ID of spell - * @param actor calculate spell success chance for this actor (depends on actor's skills) - * @attention actor has to be an NPC and not a creature! - * @return success chance from 0 to 100 (in percent) - */ - float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + inline int spellSchoolToSkill(int school) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); - - if (spell->data.flags & ESM::Spell::F_Always) // spells with this flag always succeed (usually birthsign spells) - return 100.0; - - NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); - CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); - std::map schoolSkillMap; // maps spell school to skill id schoolSkillMap[0] = 11; // alteration schoolSkillMap[1] = 13; // conjuration @@ -35,33 +19,65 @@ namespace MWMechanics schoolSkillMap[2] = 10; // destruction schoolSkillMap[4] = 14; // mysticism schoolSkillMap[5] = 15; // restoration + assert(schoolSkillMap.find(school) != schoolSkillMap.end()); + return schoolSkillMap[school]; + } + + inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); // determine the spell's school // this is always the school where the player's respective skill is the least advanced // out of all the magic effects' schools const std::vector& effects = spell->effects.list; - int skill = -1; + int school = -1; int skillLevel = -1; for (std::vector::const_iterator it = effects.begin(); it != effects.end(); ++it) { const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(it->effectID); - int school = effect->data.school; - assert(schoolSkillMap.find(school) != schoolSkillMap.end()); - int _skillLevel = stats.mSkill[schoolSkillMap[school]].getModified(); + int _school = effect->data.school; + int _skillLevel = stats.mSkill[spellSchoolToSkill(_school)].getModified(); - if (skill == -1) + if (school == -1) { - skill = schoolSkillMap[school]; + school = _school; skillLevel = _skillLevel; } else if (_skillLevel < skillLevel) { - skill = schoolSkillMap[school]; + school = _school; skillLevel = _skillLevel; } } + return school; + } + + + // UESP wiki / Morrowind/Spells: + // Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2 + /** + * @param spellId ID of spell + * @param actor calculate spell success chance for this actor (depends on actor's skills) + * @attention actor has to be an NPC and not a creature! + * @return success chance from 0 to 100 (in percent) + */ + inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + + if (spell->data.flags & ESM::Spell::F_Always // spells with this flag always succeed (usually birthsign spells) + || spell->data.type == ESM::Spell::ST_Power) // powers always succeed, but can be cast only once per day + return 100.0; + + NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); + CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); + + int skillLevel = stats.mSkill[getSpellSchool(spellId, actor)].getModified(); + // Sound magic effect (reduces spell casting chance) int soundMagnitude = creatureStats.mMagicEffects.get (MWMechanics::EffectKey (48)).mMagnitude; diff --git a/files/mygui/openmw_hud_layout.xml b/files/mygui/openmw_hud_layout.xml index d0026bf25..cf353a205 100644 --- a/files/mygui/openmw_hud_layout.xml +++ b/files/mygui/openmw_hud_layout.xml @@ -28,6 +28,14 @@ + + + + + + + + From c5a685d11fead58106c62c30acb18f74c5f84f3e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 May 2012 18:59:11 +0200 Subject: [PATCH 69/76] addition to last commit: show the selected weapon/spell names as inventory/spell window caption --- apps/openmw/mwgui/hud.cpp | 20 ++++++++++++-------- apps/openmw/mwgui/hud.hpp | 2 ++ apps/openmw/mwgui/spellwindow.cpp | 1 + apps/openmw/mwgui/window_manager.cpp | 9 +++++++++ libs/openengine/gui/layout.hpp | 2 +- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 95017579b..14212c2f9 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -44,6 +44,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mCellNameTimer(0.0f) , mCellNameBox(NULL) , mMapVisible(true) + , mWeaponVisible(true) + , mSpellVisible(true) { setCoord(0,0, width, height); @@ -101,9 +103,6 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) setEffect("icons\\s\\tx_s_chameleon.dds"); - unsetSelectedSpell(); - unsetSelectedWeapon(); - LocalMapBase::init(minimap, compass, this); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); @@ -201,6 +200,11 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV if (!weapVisible) spellDx += spellBoxBaseLeft - weapBoxBaseLeft; + mWeaponVisible = weapVisible; + mSpellVisible = spellVisible; + if (!mWeaponVisible && !mSpellVisible) + mWeaponSpellBox->setVisible(false); + health->setVisible(hmsVisible); stamina->setVisible(hmsVisible); magicka->setVisible(hmsVisible); @@ -346,7 +350,7 @@ void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) { const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); std::string spellName = spell->name; - if (spellName != mSpellName) + if (spellName != mSpellName && mSpellVisible) { mWeaponSpellTimer = 5.0f; mSpellName = spellName; @@ -376,7 +380,7 @@ void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) { std::string itemName = MWWorld::Class::get(item).getName(item); - if (itemName != mSpellName) + if (itemName != mSpellName && mSpellVisible) { mWeaponSpellTimer = 5.0f; mSpellName = itemName; @@ -407,7 +411,7 @@ void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) { std::string itemName = MWWorld::Class::get(item).getName(item); - if (itemName != mWeaponName) + if (itemName != mWeaponName && mWeaponVisible) { mWeaponSpellTimer = 5.0f; mWeaponName = itemName; @@ -443,7 +447,7 @@ void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) void HUD::unsetSelectedSpell() { std::string spellName = "#{sNone}"; - if (spellName != mSpellName) + if (spellName != mSpellName && mSpellVisible) { mWeaponSpellTimer = 5.0f; mSpellName = spellName; @@ -462,7 +466,7 @@ void HUD::unsetSelectedSpell() void HUD::unsetSelectedWeapon() { std::string itemName = "#{sSkillHandtohand}"; - if (itemName != mWeaponName) + if (itemName != mWeaponName && mWeaponVisible) { mWeaponSpellTimer = 5.0f; mWeaponName = itemName; diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index f51110637..47bd93eef 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -67,6 +67,8 @@ namespace MWGui float mWeaponSpellTimer; bool mMapVisible; + bool mWeaponVisible; + bool mSpellVisible; void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index aae3d878d..04338aa11 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -47,6 +47,7 @@ namespace MWGui getWidget(mEffectBox, "EffectsBox"); setCoord(498, 300, 302, 300); + updateSpells(); mMainWidget->castType()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index bd1ad46b6..8ddbfe929 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -144,6 +144,9 @@ WindowManager::WindowManager( playerSkillValues.insert(std::make_pair(ESM::Skill::skillIds[i], MWMechanics::Stat())); } + unsetSelectedSpell(); + unsetSelectedWeapon(); + // Set up visibility updateVisible(); } @@ -678,24 +681,30 @@ void WindowManager::removeGuiMode(GuiMode mode) void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent) { hud->setSelectedSpell(spellId, successChancePercent); + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + mSpellWindow->setTitle(spell->name); } void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) { hud->setSelectedEnchantItem(item, chargePercent); + mSpellWindow->setTitle(MWWorld::Class::get(item).getName(item)); } void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) { hud->setSelectedWeapon(item, durabilityPercent); + mInventoryWindow->setTitle(MWWorld::Class::get(item).getName(item)); } void WindowManager::unsetSelectedSpell() { hud->unsetSelectedSpell(); + mSpellWindow->setTitle("#{sNone}"); } void WindowManager::unsetSelectedWeapon() { hud->unsetSelectedWeapon(); + mInventoryWindow->setTitle("#{sSkillHandtohand}"); } diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp index d9eefe051..e6feb3d0e 100644 --- a/libs/openengine/gui/layout.hpp +++ b/libs/openengine/gui/layout.hpp @@ -118,7 +118,7 @@ namespace GUI void setTitle(const std::string& title) { // NOTE: this assume that mMainWidget is of type Window. - static_cast(mMainWidget)->setCaption(title); + static_cast(mMainWidget)->setCaptionWithReplacing(title); adjustWindowCaption(); } From 72bb7a2d2c987e97c65e11d8f79b89e0b546bf2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 May 2012 08:04:07 +0200 Subject: [PATCH 70/76] fix a typo --- apps/openmw/mwgui/spellwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 04338aa11..502754feb 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -257,7 +257,7 @@ namespace MWGui std::string cost = boost::lexical_cast(enchant->data.cost); std::string charge = boost::lexical_cast(enchant->data.charge); /// \todo track current charge - if (enchant->data.type != ESM::Enchantment::CastOnce) + if (enchant->data.type == ESM::Enchantment::CastOnce) { // this is Morrowind behaviour cost = "100"; From 2c90654401aff4de56c057130fb9e917c2721b86 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 May 2012 09:21:41 +0200 Subject: [PATCH 71/76] fix a typo that caused a crash when trying to disable an already disabled object --- apps/openmw/mwworld/refdata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index 528f49c33..e1c14b907 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -123,7 +123,7 @@ namespace MWWorld void RefData::disable() { - mEnabled = true; + mEnabled = false; } ESM::Position& RefData::getPosition() From 36d26e0681260005843ae7bdd63c366157aef310 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 May 2012 15:52:39 +0200 Subject: [PATCH 72/76] set the camera orientation after using teleport doors --- apps/openmw/mwrender/player.cpp | 18 ++++++++++++++++++ apps/openmw/mwrender/player.hpp | 3 +++ apps/openmw/mwworld/player.cpp | 5 +++++ apps/openmw/mwworld/player.hpp | 3 +++ apps/openmw/mwworld/scene.cpp | 5 ++++- 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 7ed921218..d6baac4b5 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -6,4 +6,22 @@ namespace MWRender Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node) : mCamera (camera), mNode (node) {} + + void Player::setRot(float x, float y, float z) + { + Ogre::SceneNode *sceneNode = mNode; + Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); + Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); + + // we are only interested in X and Y rotation + + // Rotate around X axis + Ogre::Quaternion xr(Ogre::Radian(x), Ogre::Vector3::UNIT_X); + + // Rotate around Y axis + Ogre::Quaternion yr(Ogre::Radian(-z), Ogre::Vector3::UNIT_Y); + + pitchNode->setOrientation(xr); + yawNode->setOrientation(yr); + } } diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index 4306b8a95..406bedb0a 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -23,6 +23,9 @@ namespace MWRender Ogre::Camera *getCamera() { return mCamera; } + /// Set where the player is looking at. Uses Morrowind (euler) angles + void setRot(float x, float y, float z); + std::string getHandle() const { return mNode->getName(); } Ogre::SceneNode* getNode() {return mNode;} }; diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 0b1483ff8..91b030d1c 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -40,6 +40,11 @@ namespace MWWorld mWorld.moveObject (getPlayer(), x, y, z); } + void Player::setRot(float x, float y, float z) + { + mRenderer->setRot(x, y, z); + } + void Player::setClass (const ESM::Class& class_) { ESM::Class *new_class = new ESM::Class (class_); diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index e199f17e9..166d4cfee 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -42,6 +42,9 @@ namespace MWWorld /// Set the player position. Uses Morrowind coordinates. void setPos(float x, float y, float z); + /// Set where the player is looking at. Uses Morrowind (euler) angles + void setRot(float x, float y, float z); + void setCell (MWWorld::Ptr::CellStore *cellStore) { mCellStore = cellStore; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 47238ee71..a47137d25 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -145,10 +145,13 @@ namespace MWWorld bool hasWater = cell->cell->data.flags & cell->cell->HasWater; mPhysics->setCurrentWater(hasWater, cell->cell->water); if (adjustPlayerPos) + { mWorld->getPlayer().setPos (position.pos[0], position.pos[1], position.pos[2]); + mWorld->getPlayer().setRot (position.rot[0], position.rot[1], position.rot[2]); + } mWorld->getPlayer().setCell (cell); - // TODO orientation + MWBase::Environment::get().getMechanicsManager()->addActor (mWorld->getPlayer().getPlayer()); MWBase::Environment::get().getMechanicsManager()->watchActor (mWorld->getPlayer().getPlayer()); From a9a582f858ef272f048bcdcb96934ea1e1a53573 Mon Sep 17 00:00:00 2001 From: Edmondo Tommasina Date: Wed, 30 May 2012 23:18:59 +0200 Subject: [PATCH 73/76] renderer.cpp: fix std::runtime_error compile error --- libs/openengine/ogre/renderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index b525e76e3..a5eca76ed 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -10,6 +10,7 @@ #include "OgreHardwarePixelBuffer.h" #include +#include using namespace Ogre; using namespace OEngine::Render; From 0ba0b2122e3ac3505d2b90a82784cd13fd3d48aa Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 2 Jun 2012 12:25:24 +0200 Subject: [PATCH 74/76] set the implicit object for script excution by clicking on it --- apps/openmw/mwgui/console.cpp | 12 +- apps/openmw/mwgui/console.hpp | 16 +- apps/openmw/mwgui/hud.cpp | 32 ++- apps/openmw/mwgui/hud.hpp | 4 + apps/openmw/mwgui/tooltips.cpp | 297 ++++++++++++++------------ apps/openmw/mwgui/window_manager.cpp | 23 ++ apps/openmw/mwgui/window_manager.hpp | 4 + apps/openmw/mwworld/physicssystem.cpp | 26 ++- apps/openmw/mwworld/physicssystem.hpp | 3 + apps/openmw/mwworld/world.cpp | 30 ++- 10 files changed, 308 insertions(+), 139 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index bf80a77b2..c9ba752e9 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -240,7 +240,7 @@ namespace MWGui { try { - ConsoleInterpreterContext interpreterContext (*this, MWWorld::Ptr()); + ConsoleInterpreterContext interpreterContext (*this, mPtr); Interpreter::Interpreter interpreter; MWScript::installOpcodes (interpreter); std::vector code; @@ -375,4 +375,14 @@ namespace MWGui { setCoord(10,10, width-10, height/2); } + + void Console::setSelectedObject(const MWWorld::Ptr& object) + { + mPtr = object; + } + + void Console::onReferenceUnavailable() + { + mPtr = MWWorld::Ptr(); + } } diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 117285847..eadf4aa4e 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -16,9 +16,11 @@ #include "../mwscript/compilercontext.hpp" #include "../mwscript/interpretercontext.hpp" +#include "referenceinterface.hpp" + namespace MWGui { - class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler + class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler, public ReferenceInterface { private: @@ -39,7 +41,17 @@ namespace MWGui /// \note The list may contain duplicates (if a name is a keyword and an identifier at the same /// time). - public: + public: + + void setSelectedObject(const MWWorld::Ptr& object); + ///< Set the implicit object for script execution + + protected: + + virtual void onReferenceUnavailable(); + + + public: MyGUI::EditPtr command; MyGUI::EditPtr history; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 14212c2f9..2f275cd33 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -14,6 +14,7 @@ #include "window_manager.hpp" #include "container.hpp" +#include "console.hpp" using namespace MWGui; @@ -46,6 +47,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mMapVisible(true) , mWeaponVisible(true) , mSpellVisible(true) + , mWorldMouseOver(false) { setCoord(0,0, width, height); @@ -265,12 +267,39 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) MWBase::Environment::get().getWindowManager()->setDragDrop(false); } + else + { + GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode(); + + if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) ) + return; + + std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); + MWWorld::Ptr object; + try + { + object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); + } + catch (std::exception& e) + { + return; + } + + if (mode == GM_Console) + MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object); + else if (mode == GM_Console || GM_Inventory) + { + // pick up object + } + } } void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) { if (mDragAndDrop->mIsOnDragAndDrop) { + mWorldMouseOver = false; + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition(); float mouseX = cursorPosition.left / float(viewSize.width); @@ -290,13 +319,14 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) else { MyGUI::PointerManager::getInstance().setPointer("arrow"); - /// \todo make it possible to pick up objects with the mouse, if inventory or container window is open + mWorldMouseOver = true; } } void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) { MyGUI::PointerManager::getInstance().setPointer("arrow"); + mWorldMouseOver = false; } void HUD::onHMSClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 47bd93eef..0bfe5c20f 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -33,6 +33,8 @@ namespace MWGui void setCellName(const std::string& cellName); + bool getWorldMouseOver() { return mWorldMouseOver; } + MyGUI::ProgressPtr health, magicka, stamina; MyGUI::Widget* mHealthFrame; MyGUI::Widget *weapBox, *spellBox; @@ -70,6 +72,8 @@ namespace MWGui bool mWeaponVisible; bool mSpellVisible; + bool mWorldMouseOver; + 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/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 0f6892190..1f614d56b 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -67,158 +67,193 @@ void ToolTips::onFrame(float frameDuration) if (!mGameMode) { const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); - const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); - if (mousePos == lastPressed) // mouseclick makes tooltip disappear - return; - - if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) + if (mWindowManager->getWorldMouseOver() && ((mWindowManager->getMode() == GM_Console) + || (mWindowManager->getMode() == GM_Container) + || (mWindowManager->getMode() == GM_Inventory))) { - mRemainingDelay -= frameDuration; + std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); + try + { + mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); + } + catch (std::exception& e) + { + return; + } + + MyGUI::IntSize tooltipSize = getToolTipViaPtr(true); + + IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + + // make the tooltip stay completely in the viewport + if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) + { + tooltipPosition.left = viewSize.width - tooltipSize.width; + } + if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) + { + tooltipPosition.top = viewSize.height - tooltipSize.height; + } + + setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); } + else { - mRemainingDelay = mDelay; - } - mLastMouseX = mousePos.left; - mLastMouseY = mousePos.top; + const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); - if (mRemainingDelay > 0) - return; - - Widget* focus = InputManager::getInstance().getMouseFocusWidget(); - if (focus == 0) - { - return; - } - - IntSize tooltipSize; - - // try to go 1 level up until there is a widget that has tooltip - // this is necessary because some skin elements are actually separate widgets - int i=0; - while (!focus->isUserString("ToolTipType")) - { - focus = focus->getParent(); - if (!focus) + if (mousePos == lastPressed) // mouseclick makes tooltip disappear return; - ++i; - } - std::string type = focus->getUserString("ToolTipType"); - std::string text = focus->getUserString("ToolTipText"); - - ToolTipInfo info; - if (type == "") - { - return; - } - else if (type == "ItemPtr") - { - mFocusObject = *focus->getUserData(); - tooltipSize = getToolTipViaPtr(false); - } - else if (type == "Spell") - { - ToolTipInfo info; - const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); - info.caption = spell->name; - Widgets::SpellEffectList effects; - std::vector::const_iterator end = spell->effects.list.end(); - for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) { - Widgets::SpellEffectParams params; - params.mEffectID = it->effectID; - params.mSkill = it->skill; - params.mAttribute = it->attribute; - params.mDuration = it->duration; - params.mMagnMin = it->magnMin; - params.mMagnMax = it->magnMax; - params.mRange = it->range; - params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); - effects.push_back(params); - } - info.effects = effects; - tooltipSize = createToolTip(info); - } - else if (type == "Layout") - { - // tooltip defined in the layout - MyGUI::Widget* tooltip; - getWidget(tooltip, focus->getUserString("ToolTipLayout")); - - tooltip->setVisible(true); - if (!tooltip->isUserString("DontResize")) - { - tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping - - tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); + mRemainingDelay -= frameDuration; } else - tooltipSize = tooltip->getSize(); - - std::map userStrings = focus->getUserStrings(); - for (std::map::iterator it = userStrings.begin(); - it != userStrings.end(); ++it) { - if (it->first == "ToolTipType" - || it->first == "ToolTipLayout") - continue; + mRemainingDelay = mDelay; + } + mLastMouseX = mousePos.left; + mLastMouseY = mousePos.top; + if (mRemainingDelay > 0) + return; - size_t underscorePos = it->first.find("_"); - std::string propertyKey = it->first.substr(0, underscorePos); - std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1)); - - MyGUI::Widget* w; - getWidget(w, widgetName); - w->setProperty(propertyKey, it->second); + Widget* focus = InputManager::getInstance().getMouseFocusWidget(); + if (focus == 0) + { + return; } - for (unsigned int i=0; igetChildCount(); ++i) + IntSize tooltipSize; + + // try to go 1 level up until there is a widget that has tooltip + // this is necessary because some skin elements are actually separate widgets + int i=0; + while (!focus->isUserString("ToolTipType")) { - MyGUI::Widget* w = tooltip->getChildAt(i); - - if (w->isUserString("AutoResizeHorizontal")) - { - MyGUI::TextBox* text = w->castType(); - tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); - } - else if (!tooltip->isUserString("DontResize")) - tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8); - - if (w->isUserString("AutoResizeVertical")) - { - MyGUI::TextBox* text = w->castType(); - int height = text->getTextSize().height; - if (height > w->getHeight()) - { - tooltipSize += MyGUI::IntSize(0, height - w->getHeight()); - } - if (height < w->getHeight()) - { - tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height); - } - } + focus = focus->getParent(); + if (!focus) + return; + ++i; } - tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); - } - else - throw std::runtime_error ("unknown tooltip type"); - IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + std::string type = focus->getUserString("ToolTipType"); + std::string text = focus->getUserString("ToolTipText"); - // make the tooltip stay completely in the viewport - if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) - { - tooltipPosition.left = viewSize.width - tooltipSize.width; - } - if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) - { - tooltipPosition.top = viewSize.height - tooltipSize.height; - } + ToolTipInfo info; + if (type == "") + { + return; + } + else if (type == "ItemPtr") + { + mFocusObject = *focus->getUserData(); + tooltipSize = getToolTipViaPtr(false); + } + else if (type == "Spell") + { + ToolTipInfo info; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); + info.caption = spell->name; + Widgets::SpellEffectList effects; + std::vector::const_iterator end = spell->effects.list.end(); + for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + { + Widgets::SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); + effects.push_back(params); + } + info.effects = effects; + tooltipSize = createToolTip(info); + } + else if (type == "Layout") + { + // tooltip defined in the layout + MyGUI::Widget* tooltip; + getWidget(tooltip, focus->getUserString("ToolTipLayout")); - setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); + tooltip->setVisible(true); + if (!tooltip->isUserString("DontResize")) + { + tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping + + tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); + } + else + tooltipSize = tooltip->getSize(); + + std::map userStrings = focus->getUserStrings(); + for (std::map::iterator it = userStrings.begin(); + it != userStrings.end(); ++it) + { + if (it->first == "ToolTipType" + || it->first == "ToolTipLayout") + continue; + + + size_t underscorePos = it->first.find("_"); + std::string propertyKey = it->first.substr(0, underscorePos); + std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1)); + + MyGUI::Widget* w; + getWidget(w, widgetName); + w->setProperty(propertyKey, it->second); + } + + for (unsigned int i=0; igetChildCount(); ++i) + { + MyGUI::Widget* w = tooltip->getChildAt(i); + + if (w->isUserString("AutoResizeHorizontal")) + { + MyGUI::TextBox* text = w->castType(); + tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); + } + else if (!tooltip->isUserString("DontResize")) + tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8); + + if (w->isUserString("AutoResizeVertical")) + { + MyGUI::TextBox* text = w->castType(); + int height = text->getTextSize().height; + if (height > w->getHeight()) + { + tooltipSize += MyGUI::IntSize(0, height - w->getHeight()); + } + if (height < w->getHeight()) + { + tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height); + } + } + } + tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); + } + else + throw std::runtime_error ("unknown tooltip type"); + + IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + + // make the tooltip stay completely in the viewport + if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) + { + tooltipPosition.left = viewSize.width - tooltipSize.width; + } + if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) + { + tooltipPosition.top = viewSize.height - tooltipSize.height; + } + + setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); + } } else { diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 8ddbfe929..5275ae19d 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -487,6 +487,7 @@ void WindowManager::onFrame (float frameDuration) mDialogueWindow->checkReferenceAvailable(); mTradeWindow->checkReferenceAvailable(); mContainerWindow->checkReferenceAvailable(); + console->checkReferenceAvailable(); } const ESMS::ESMStore& WindowManager::getStore() const @@ -708,3 +709,25 @@ void WindowManager::unsetSelectedWeapon() hud->unsetSelectedWeapon(); mInventoryWindow->setTitle("#{sSkillHandtohand}"); } + +void WindowManager::getMousePosition(int &x, int &y) +{ + const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); + x = pos.left; + y = pos.top; +} + +void WindowManager::getMousePosition(float &x, float &y) +{ + const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); + x = pos.left; + y = pos.top; + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + x /= viewSize.width; + y /= viewSize.height; +} + +bool WindowManager::getWorldMouseOver() +{ + return hud->getWorldMouseOver(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 037022b42..19ad7702a 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -155,6 +155,7 @@ namespace MWGui MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;} MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} MWGui::SpellWindow* getSpellWindow() {return mSpellWindow;} + MWGui::Console* getConsole() {return console;} MyGUI::Gui* getGui() const { return gui; } @@ -188,7 +189,10 @@ namespace MWGui void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); void setMouseVisible(bool visible); + void getMousePosition(int &x, int &y); + void getMousePosition(float &x, float &y); void setDragDrop(bool dragDrop); + bool getWorldMouseOver(); void toggleFogOfWar(); void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 808c712a0..5598ff3c0 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -66,7 +66,23 @@ namespace MWWorld return mEngine->rayTest2(from,to); } - void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight){ + + std::vector < std::pair > PhysicsSystem::getFacedObjects (float mouseX, float mouseY) + { + Ray ray = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); + Ogre::Vector3 from = ray.getOrigin(); + Ogre::Vector3 to = ray.getPoint(500); /// \todo make this distance (ray length) configurable + + btVector3 _from, _to; + // OGRE to MW coordinates + _from = btVector3(from.x, -from.z, from.y); + _to = btVector3(to.x, -to.z, to.y); + + return mEngine->rayTest2(_from,_to); + } + + void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight) + { playerphysics->hasWater = hasWater; if(hasWater){ playerphysics->waterHeight = waterHeight; @@ -84,6 +100,14 @@ namespace MWWorld return result; } + btVector3 PhysicsSystem::getRayPoint(float extent, float mouseX, float mouseY) + { + //get a ray pointing to the center of the viewport + Ray centerRay = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); + btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable + return result; + } + bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) { btVector3 _from, _to; diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 9b03d2124..1a8bd87ae 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -47,9 +47,12 @@ namespace MWWorld std::pair getFacedHandle (MWWorld::World& world); btVector3 getRayPoint(float extent); + btVector3 getRayPoint(float extent, float mouseX, float mouseY); std::vector < std::pair > getFacedObjects (); + std::vector < std::pair > getFacedObjects (float mouseX, float mouseY); + // cast ray, return true if it hit something bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 6802d5cc1..e8d555689 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -818,7 +818,15 @@ namespace MWWorld // send new query // figure out which object we want to test against - std::vector < std::pair < float, std::string > > results = mPhysics->getFacedObjects(); + std::vector < std::pair < float, std::string > > results; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + results = mPhysics->getFacedObjects(x, y); + } + else + results = mPhysics->getFacedObjects(); // ignore the player and other things we're not interested in std::vector < std::pair < float, std::string > >::iterator it = results.begin(); @@ -843,7 +851,15 @@ namespace MWWorld mFaced1Name = results.front().second; mNumFacing = 1; - btVector3 p = mPhysics->getRayPoint(results.front().first); + btVector3 p; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + p = mPhysics->getRayPoint(results.front().first, x, y); + } + else + p = mPhysics->getRayPoint(results.front().first); Ogre::Vector3 pos(p.x(), p.z(), -p.y()); Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode(); @@ -860,7 +876,15 @@ namespace MWWorld mFaced2 = getPtrViaHandle(results[1].second); mNumFacing = 2; - btVector3 p = mPhysics->getRayPoint(results[1].first); + btVector3 p; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + p = mPhysics->getRayPoint(results[1].first, x, y); + } + else + p = mPhysics->getRayPoint(results[1].first); Ogre::Vector3 pos(p.x(), p.z(), -p.y()); Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode(); Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode(); From b886aea2989e0a5276bf637c4328372a43117377 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 2 Jun 2012 12:31:23 +0200 Subject: [PATCH 75/76] change console skin to MW_Window and set the selected object refID as window title --- apps/openmw/mwgui/console.cpp | 2 ++ files/mygui/openmw_console.skin.xml | 35 --------------------------- files/mygui/openmw_console_layout.xml | 8 +++--- 3 files changed, 6 insertions(+), 39 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index c9ba752e9..25cd90eae 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -379,10 +379,12 @@ namespace MWGui void Console::setSelectedObject(const MWWorld::Ptr& object) { mPtr = object; + setTitle("#{sConsoleTitle} (" + mPtr.getCellRef().refID + ")"); } void Console::onReferenceUnavailable() { mPtr = MWWorld::Ptr(); + setTitle("#{sConsoleTitle}"); } } diff --git a/files/mygui/openmw_console.skin.xml b/files/mygui/openmw_console.skin.xml index 598252734..1758c728d 100644 --- a/files/mygui/openmw_console.skin.xml +++ b/files/mygui/openmw_console.skin.xml @@ -1,41 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/files/mygui/openmw_console_layout.xml b/files/mygui/openmw_console_layout.xml index a2b883cdb..732684ad1 100644 --- a/files/mygui/openmw_console_layout.xml +++ b/files/mygui/openmw_console_layout.xml @@ -1,17 +1,17 @@  - - + + - + - + From b8464d4ce50c4852a9b2375cf684582baa5f7331 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 2 Jun 2012 14:19:02 +0200 Subject: [PATCH 76/76] allow picking up objects from the gameworld with the mouse in inventory mode --- apps/openmw/mwgui/console.cpp | 9 ++-- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/hud.cpp | 5 +- apps/openmw/mwgui/inventorywindow.cpp | 68 ++++++++++++++++++++++++--- apps/openmw/mwgui/inventorywindow.hpp | 2 + apps/openmw/mwgui/spellwindow.cpp | 10 ++++ apps/openmw/mwgui/tradewindow.cpp | 2 + apps/openmw/mwgui/window_manager.cpp | 1 + 8 files changed, 87 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 25cd90eae..2f8a95306 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -138,6 +138,7 @@ namespace MWGui void Console::disable() { setVisible(false); + setSelectedObject(MWWorld::Ptr()); // Remove keyboard focus from the console input whenever the // console is turned off MyGUI::InputManager::getInstance().setKeyFocusWidget(NULL); @@ -379,12 +380,14 @@ namespace MWGui void Console::setSelectedObject(const MWWorld::Ptr& object) { mPtr = object; - setTitle("#{sConsoleTitle} (" + mPtr.getCellRef().refID + ")"); + if (!mPtr.isEmpty()) + setTitle("#{sConsoleTitle} (" + mPtr.getCellRef().refID + ")"); + else + setTitle("#{sConsoleTitle}"); } void Console::onReferenceUnavailable() { - mPtr = MWWorld::Ptr(); - setTitle("#{sConsoleTitle}"); + setSelectedObject(MWWorld::Ptr()); } } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index bf6b4add0..eb5cbc92b 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -470,7 +470,7 @@ void ContainerBase::drawItems() if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) { std::string path = std::string("icons\\"); - path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); + path += MWWorld::Class::get(*iter).getInventoryIcon(*iter); // background widget (for the "equipped" frame and magic item background image) bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != ""); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 2f275cd33..95d66eb81 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -12,6 +12,7 @@ #include "../mwworld/world.hpp" #include "../mwworld/player.hpp" +#include "inventorywindow.hpp" #include "window_manager.hpp" #include "container.hpp" #include "console.hpp" @@ -266,6 +267,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) mDragAndDrop->mDraggedWidget = 0; MWBase::Environment::get().getWindowManager()->setDragDrop(false); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } else { @@ -287,9 +289,10 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) if (mode == GM_Console) MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object); - else if (mode == GM_Console || GM_Inventory) + else if ((mode == GM_Container) || (mode == GM_Inventory)) { // pick up object + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->pickUpObject(object); } } } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 103f5ebf3..f75c9afdc 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -15,6 +15,8 @@ #include "../mwworld/player.hpp" #include "../mwbase/environment.hpp" #include "../mwworld/manualref.hpp" +#include "../mwworld/actiontake.hpp" +#include "../mwsound/soundmanager.hpp" #include "window_manager.hpp" #include "widgets.hpp" @@ -276,13 +278,65 @@ namespace MWGui if (mWindowManager.getSpellWindow()) mWindowManager.getSpellWindow()->updateSpells(); - // update selected weapon icon - MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); - MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if (weaponSlot == invStore.end()) - mWindowManager.unsetSelectedWeapon(); - else - mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + // update selected weapon icon + MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weaponSlot == invStore.end()) + mWindowManager.unsetSelectedWeapon(); + else + mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + } + void InventoryWindow::pickUpObject (MWWorld::Ptr object) + { + /// \todo scripts + + // make sure the object is of a type that can be picked up + std::string type = object.getTypeName(); + if ( (type != typeid(ESM::Apparatus).name()) + && (type != typeid(ESM::Armor).name()) + && (type != typeid(ESM::Book).name()) + && (type != typeid(ESM::Clothing).name()) + && (type != typeid(ESM::Ingredient).name()) + && (type != typeid(ESM::Light).name()) + && (type != typeid(ESM::Miscellaneous).name()) + && (type != typeid(ESM::Tool).name()) + && (type != typeid(ESM::Probe).name()) + && (type != typeid(ESM::Repair).name()) + && (type != typeid(ESM::Potion).name())) + return; + + // sound + std::string sound = MWWorld::Class::get(object).getUpSoundId(object); + MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1); + + int count = object.getRefData().getCount(); + MWWorld::ActionTake action(object); + action.execute(); + mDragAndDrop->mIsOnDragAndDrop = true; + mDragAndDrop->mDraggedCount = count; + + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(object).getInventoryIcon(object); + MyGUI::ImageBox* baseWidget = mContainerWidget->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); + baseWidget->detachFromWidget(); + baseWidget->attachToWidget(mDragAndDrop->mDragAndDropWidget); + baseWidget->setUserData(object); + mDragAndDrop->mDraggedWidget = baseWidget; + ImageBox* image = baseWidget->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + image->setImageTexture(path); + image->setNeedMouseFocus(false); + + // text widget that shows item count + MyGUI::TextBox* text = image->createWidget("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); + text->setTextAlign(MyGUI::Align::Right); + text->setNeedMouseFocus(false); + text->setTextShadow(true); + text->setTextShadowColour(MyGUI::Colour(0,0,0)); + text->setCaption(getCountString(count)); + mDragAndDrop->mDraggedFrom = this; } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index bc4cb08ef..82da3efea 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -18,6 +18,8 @@ namespace MWGui void onFrame(); + void pickUpObject (MWWorld::Ptr object); + int getPlayerGold(); protected: diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 502754feb..d34ce68d9 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -89,6 +89,16 @@ namespace MWGui bool allowSelectedItem = true; + // make sure that the item is still in the player inventory, otherwise it can't be selected + bool found = false; + for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it) + { + if (*it == selectedItem) + found = true; + } + if (!found) + allowSelectedItem = false; + // if the selected item can be equipped, make sure that it actually is equipped std::pair, bool> slots; slots = MWWorld::Class::get(selectedItem).getEquipmentSlots(selectedItem); diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 2089ed4af..47d299fdc 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -300,6 +300,8 @@ namespace MWGui services = ref->base->AI.services; } + /// \todo what about potions, there doesn't seem to be a flag for them?? + if (item.getTypeName() == typeid(ESM::Weapon).name()) return services & ESM::NPC::Weapon; else if (item.getTypeName() == typeid(ESM::Armor).name()) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 5275ae19d..800125f27 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -638,6 +638,7 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector hud->onResChange(x, y); console->onResChange(x, y); mSettingsWindow->center(); + mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y)); } }