From cac662ca981dc0cdb19872f4c40e46b97bf7b365 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sat, 14 Apr 2012 17:47:44 +0200
Subject: [PATCH 01/44] basic tooltips

---
 apps/openmw/CMakeLists.txt           |  2 +-
 apps/openmw/engine.cpp               | 16 +++----
 apps/openmw/mwgui/tooltips.cpp       | 63 ++++++++++++++++++++++++++++
 apps/openmw/mwgui/tooltips.hpp       | 30 +++++++++++++
 apps/openmw/mwgui/window_manager.cpp | 10 +++++
 apps/openmw/mwgui/window_manager.hpp |  2 +
 files/mygui/CMakeLists.txt           |  1 +
 files/mygui/openmw_tooltips.xml      | 21 ++++++++++
 8 files changed, 136 insertions(+), 9 deletions(-)
 create mode 100644 apps/openmw/mwgui/tooltips.cpp
 create mode 100644 apps/openmw/mwgui/tooltips.hpp
 create mode 100644 files/mygui/openmw_tooltips.xml

diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt
index c4b3776ed..a37dbf7af 100644
--- a/apps/openmw/CMakeLists.txt
+++ b/apps/openmw/CMakeLists.txt
@@ -25,7 +25,7 @@ add_openmw_dir (mwinput
 add_openmw_dir (mwgui
     layouts 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
+    map_window window_pinnable_base cursorreplace tooltips
     )
 
 add_openmw_dir (mwdialogue
diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp
index 2d3c872dd..36a2cb645 100644
--- a/apps/openmw/engine.cpp
+++ b/apps/openmw/engine.cpp
@@ -133,14 +133,6 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
         if (mUseSound)
             mEnvironment.mSoundManager->update (evt.timeSinceLastFrame);
 
-        // update GUI
-        Ogre::RenderWindow* window = mOgre->getWindow();
-        mEnvironment.mWindowManager->wmUpdateFps(window->getLastFPS(),
-                                                 window->getTriangleCount(),
-                                                 window->getBatchCount());
-
-        mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration);
-
         // global scripts
         mEnvironment.mGlobalScripts->run (mEnvironment);
 
@@ -171,6 +163,14 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
         // update world
         mEnvironment.mWorld->update (evt.timeSinceLastFrame);
 
+        // update GUI
+        Ogre::RenderWindow* window = mOgre->getWindow();
+        mEnvironment.mWindowManager->wmUpdateFps(window->getLastFPS(),
+                                                 window->getTriangleCount(),
+                                                 window->getBatchCount());
+
+        mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration);
+
         // report focus object (for debugging)
         if (mReportFocus)
             updateFocusReport (mEnvironment.mFrameDuration);
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
new file mode 100644
index 000000000..d7c61c51a
--- /dev/null
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -0,0 +1,63 @@
+#include "tooltips.hpp"
+
+using namespace MWGui;
+using namespace MyGUI;
+
+ToolTips::ToolTips() :
+    Layout("openmw_tooltips.xml")
+    , mGameMode(true)
+{
+    getWidget(mTextToolTip, "TextToolTip");
+    getWidget(mTextToolTipBox, "TextToolTipBox");
+    getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
+
+    mDynamicToolTipBox->setVisible(false);
+
+    // turn off mouse focus so that getMouseFocusWidget returns the correct widget,
+    // even if the mouse is over the tooltip
+    mDynamicToolTipBox->setNeedMouseFocus(false);
+    mTextToolTipBox->setNeedMouseFocus(false);
+    mTextToolTip->setNeedMouseFocus(false);
+    mMainWidget->setNeedMouseFocus(false);
+}
+
+void ToolTips::onFrame(float frameDuration)
+{
+    /// \todo Store a MWWorld::Ptr in the widget user data, retrieve it here and construct a tooltip dynamically
+
+    const IntSize &viewSize = RenderManager::getInstance().getViewSize();
+
+    Widget* focus = InputManager::getInstance().getMouseFocusWidget();
+    if (focus == 0) return;
+
+    // this the maximum width of the tooltip before it starts word-wrapping
+    setCoord(0, 0, 300, 300);
+
+    mTextToolTip->setCaption("Focused: " + focus->getName() + "\nType: " + focus->getTypeName());
+    const IntSize &textSize = mTextToolTip->getTextSize();
+
+    IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
+
+    IntSize size = textSize + IntSize(12, 12);
+    // make the tooltip stay completely in the viewport
+    if ((tooltipPosition.left + size.width) > viewSize.width)
+    {
+        tooltipPosition.left = viewSize.width - size.width;
+    }
+    if ((tooltipPosition.top + size.height) > viewSize.height)
+    {
+        tooltipPosition.top = viewSize.height - size.height;
+    }
+
+    setCoord(tooltipPosition.left, tooltipPosition.top, size.width, size.height);
+}
+
+void ToolTips::enterGameMode()
+{
+    mGameMode = true;
+}
+
+void ToolTips::enterGuiMode()
+{
+    mGameMode = false;
+}
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
new file mode 100644
index 000000000..aa929ff51
--- /dev/null
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -0,0 +1,30 @@
+
+#ifndef MWGUI_TOOLTIPS_H
+#define MWGUI_TOOLTIPS_H
+
+#include <openengine/gui/layout.hpp>
+
+namespace MWGui
+{
+    class ToolTips : public OEngine::GUI::Layout
+    {
+    public:
+        ToolTips();
+
+        void onFrame(float frameDuration);
+
+        void enterGameMode();
+        void enterGuiMode();
+
+        void adjustScreen(int screenWidth, int screenHeight);
+
+    private:
+        MyGUI::EditBox* mTextToolTip;
+        MyGUI::Widget* mTextToolTipBox;
+
+        MyGUI::Widget* mDynamicToolTipBox;
+
+        bool mGameMode;
+    };
+}
+#endif
diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp
index 34d62ba08..1ef5cae42 100644
--- a/apps/openmw/mwgui/window_manager.cpp
+++ b/apps/openmw/mwgui/window_manager.cpp
@@ -7,6 +7,7 @@
 #include "map_window.hpp"
 #include "stats_window.hpp"
 #include "messagebox.hpp"
+#include "tooltips.hpp"
 
 #include "../mwmechanics/mechanicsmanager.hpp"
 #include "../mwinput/inputmanager.hpp"
@@ -31,6 +32,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment,
   , map(NULL)
   , menu(NULL)
   , stats(NULL)
+  , mToolTips(NULL)
   , mMessageBoxManager(NULL)
   , console(NULL)
   , mJournal(NULL)
@@ -80,6 +82,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment,
     mJournal = new JournalWindow(*this);
     mMessageBoxManager = new MessageBoxManager(this);
     dialogueWindow = new DialogueWindow(*this,environment);
+    mToolTips = new ToolTips();
 
     // The HUD is always on
     hud->setVisible(true);
@@ -118,6 +121,7 @@ WindowManager::~WindowManager()
     delete stats;
     delete mJournal;
     delete dialogueWindow;
+    delete mToolTips;
 
     delete mCharGen;
 
@@ -183,6 +187,11 @@ void WindowManager::updateVisible()
     // Mouse is visible whenever we're not in game mode
     MyGUI::PointerManager::getInstance().setVisible(isGuiMode());
 
+    if (mode == GM_Game)
+        mToolTips->enterGameMode();
+    else
+        mToolTips->enterGuiMode();
+
     switch(mode) {
         case GM_Game:
             // If in game mode, don't show anything.
@@ -408,6 +417,7 @@ void WindowManager::onDialogueWindowBye()
 void WindowManager::onFrame (float frameDuration)
 {
     mMessageBoxManager->onFrame(frameDuration);
+    mToolTips->onFrame(frameDuration);
 }
 
 const ESMS::ESMStore& WindowManager::getStore() const
diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp
index 2b53560ba..1cbd8f6a6 100644
--- a/apps/openmw/mwgui/window_manager.hpp
+++ b/apps/openmw/mwgui/window_manager.hpp
@@ -62,6 +62,7 @@ namespace MWGui
   class Console;
   class JournalWindow;
   class CharacterCreation;
+  class ToolTips;
 
   class TextInputDialog;
   class InfoBoxDialog;
@@ -196,6 +197,7 @@ namespace MWGui
     HUD *hud;
     MapWindow *map;
     MainMenu *menu;
+    ToolTips *mToolTips;
     StatsWindow *stats;
     MessageBoxManager *mMessageBoxManager;
     Console *console;
diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt
index e3a7b9999..49055d2ed 100644
--- a/files/mygui/CMakeLists.txt
+++ b/files/mygui/CMakeLists.txt
@@ -50,6 +50,7 @@ configure_file("${SDIR}/openmw_messagebox_layout.xml" "${DDIR}/openmw_messagebox
 configure_file("${SDIR}/openmw_interactive_messagebox_layout.xml" "${DDIR}/openmw_interactive_messagebox_layout.xml" COPYONLY)
 configure_file("${SDIR}/openmw_journal_layout.xml" "${DDIR}/openmw_journal_layout.xml" COPYONLY)
 configure_file("${SDIR}/openmw_journal_skin.xml" "${DDIR}/openmw_journal_skin.xml" COPYONLY)
+configure_file("${SDIR}/openmw_tooltips.xml" "${DDIR}/openmw_tooltips.xml" 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)
diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml
new file mode 100644
index 000000000..76df7b9a7
--- /dev/null
+++ b/files/mygui/openmw_tooltips.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<MyGUI type="Layout">
+    <Widget type="Widget" layer="Popup" position="0 0 300 200" name="_Main">
+
+        <!-- Simple text-only tooltip -->
+        <Widget type="Widget" skin="HUD_Box" position="0 0 300 200" align="Stretch" name="TextToolTipBox">
+            <Widget type="EditBox" skin="MW_TextEdit" position="0 0 300 200" align="Stretch" name="TextToolTip">
+                <Property key="WordWrap" value="true"/>
+                <Property key="Static" value="true"/>
+                <Property key="TextAlign" value="Left Top"/>
+            </Widget>
+        </Widget>
+
+        <!-- Dynamically constructed tooltip goes here -->
+        <Widget type="Widget" skin="HUD_Box" position="0 0 300 200" align="Stretch" name="DynamicToolTipBox">
+        </Widget>
+
+    </Widget>
+</MyGUI>
+

From d37bc9cba8d6d9bd9afe07dd48c5981171b812fe Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sun, 15 Apr 2012 17:10:08 +0200
Subject: [PATCH 02/44] basic mouse-over info for in-game objects

---
 apps/openmw/mwgui/tooltips.cpp       | 412 +++++++++++++++++++++++++--
 apps/openmw/mwgui/tooltips.hpp       |   6 +
 apps/openmw/mwgui/window_manager.cpp |   5 +
 apps/openmw/mwgui/window_manager.hpp |   2 +
 apps/openmw/mwrender/shadows.cpp     |   5 +-
 apps/openmw/mwworld/world.cpp        |  12 +
 files/mygui/openmw_tooltips.xml      |  10 +-
 7 files changed, 426 insertions(+), 26 deletions(-)

diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index d7c61c51a..7f45bdbdd 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -6,6 +6,7 @@ using namespace MyGUI;
 ToolTips::ToolTips() :
     Layout("openmw_tooltips.xml")
     , mGameMode(true)
+    , mFocusChanged(true)
 {
     getWidget(mTextToolTip, "TextToolTip");
     getWidget(mTextToolTipBox, "TextToolTipBox");
@@ -27,29 +28,389 @@ void ToolTips::onFrame(float frameDuration)
 
     const IntSize &viewSize = RenderManager::getInstance().getViewSize();
 
-    Widget* focus = InputManager::getInstance().getMouseFocusWidget();
-    if (focus == 0) return;
-
-    // this the maximum width of the tooltip before it starts word-wrapping
-    setCoord(0, 0, 300, 300);
-
-    mTextToolTip->setCaption("Focused: " + focus->getName() + "\nType: " + focus->getTypeName());
-    const IntSize &textSize = mTextToolTip->getTextSize();
-
-    IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
-
-    IntSize size = textSize + IntSize(12, 12);
-    // make the tooltip stay completely in the viewport
-    if ((tooltipPosition.left + size.width) > viewSize.width)
+    if (!mGameMode)
     {
-        tooltipPosition.left = viewSize.width - size.width;
-    }
-    if ((tooltipPosition.top + size.height) > viewSize.height)
-    {
-        tooltipPosition.top = viewSize.height - size.height;
-    }
+        mDynamicToolTipBox->setVisible(false);
 
-    setCoord(tooltipPosition.left, tooltipPosition.top, size.width, size.height);
+        Widget* focus = InputManager::getInstance().getMouseFocusWidget();
+        if (focus == 0) return;
+
+        // this the maximum width of the tooltip before it starts word-wrapping
+        setCoord(0, 0, 300, 300);
+
+        mTextToolTip->setCaption("Focused: " + focus->getName() + "\nType: " + focus->getTypeName());
+        const IntSize &textSize = mTextToolTip->getTextSize();
+
+        IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
+
+        IntSize size = textSize + IntSize(12, 12);
+        // make the tooltip stay completely in the viewport
+        if ((tooltipPosition.left + size.width) > viewSize.width)
+        {
+            tooltipPosition.left = viewSize.width - size.width;
+        }
+        if ((tooltipPosition.top + size.height) > viewSize.height)
+        {
+            tooltipPosition.top = viewSize.height - size.height;
+        }
+
+        setCoord(tooltipPosition.left, tooltipPosition.top, size.width, size.height);
+    }
+    else
+    {
+        mTextToolTipBox->setVisible(false);
+
+        if (!mFocusObject.isEmpty())
+        {
+            if (mFocusChanged)
+            {
+                for (size_t i=0; i<mDynamicToolTipBox->getChildCount(); ++i)
+                {
+                    mDynamicToolTipBox->_destroyChildWidget(mDynamicToolTipBox->getChildAt(i));
+                }
+
+                // this the maximum width of the tooltip before it starts word-wrapping
+                setCoord(0, 0, 300, 300);
+
+                IntSize tooltipSize;
+
+                /// \todo Not sure about levelled lists (ESM::CreateLevList and ESM::ItemLevList). I think
+                /// they are supposed to spawn a concrete object (Creature or item of any type), so
+                /// the player wouldn't encounter them and we don't have to handle them here. 
+
+                // --------------------  Door -------------------------------
+                if (mFocusObject.getTypeName() == typeid(ESM::Door).name())
+                {
+                    ESMS::LiveCellRef<ESM::Door, MWWorld::RefData>* ref = mFocusObject.get<ESM::Door>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setProperty("MultiLine", "true");
+
+                    std::string caption = ref->base->name;
+                    /// \todo If destCell is empty, the teleport target is an exterior cell. In that case we 
+                    /// need to fetch that cell (via target position) and retrieve the region name.
+                    if (ref->ref.teleport && (ref->ref.destCell != ""))
+                    {
+                        caption += "\n-";
+                        caption += "\n"+ref->ref.destCell;
+                    }
+                    box->setCaption(caption);
+
+                    /// \todo Lock level, trap (retrieve GMST)
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  NPC -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::NPC).name())
+                {
+                    /// \todo We don't want tooltips for NPCs in combat mode.
+                    ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mFocusObject.get<ESM::NPC>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Creature -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Creature).name())
+                {
+                    ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mFocusObject.get<ESM::Creature>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  CreatureLevList -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Creature).name())
+                {
+                    ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mFocusObject.get<ESM::Creature>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Container -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Container).name())
+                {
+                    ESMS::LiveCellRef<ESM::Container, MWWorld::RefData>* ref = mFocusObject.get<ESM::Container>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo Lock level, trap (retrieve GMST)
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Potion -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Potion).name())
+                {
+                    ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData>* ref = mFocusObject.get<ESM::Potion>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Apparatus -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Apparatus).name())
+                {
+                    ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData>* ref = mFocusObject.get<ESM::Potion>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Armor -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Armor).name())
+                {
+                    ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData>* ref = mFocusObject.get<ESM::Armor>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo weight, armor value, value, durability..
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Book -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Book).name())
+                {
+                    ESMS::LiveCellRef<ESM::Book, MWWorld::RefData>* ref = mFocusObject.get<ESM::Book>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Clothing -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Clothing).name())
+                {
+                    ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData>* ref = mFocusObject.get<ESM::Clothing>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Ingredient -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Ingredient).name())
+                {
+                    ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData>* ref = mFocusObject.get<ESM::Ingredient>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Light -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Light).name())
+                {
+                    ESMS::LiveCellRef<ESM::Light, MWWorld::RefData>* ref = mFocusObject.get<ESM::Light>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(ref->base->name != "");
+                }
+
+                // --------------------  Tool -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Tool).name())
+                {
+                    ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData>* ref = mFocusObject.get<ESM::Tool>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Miscellaneous -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Miscellaneous).name())
+                {
+                    ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData>* ref = mFocusObject.get<ESM::Miscellaneous>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Probe -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Probe).name())
+                {
+                    ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData>* ref = mFocusObject.get<ESM::Probe>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Repair -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Repair).name())
+                {
+                    ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData>* ref = mFocusObject.get<ESM::Repair>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Weapon -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Weapon).name())
+                {
+                    ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData>* ref = mFocusObject.get<ESM::Weapon>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(true);
+                }
+
+                // --------------------  Activator -------------------------------
+                else if (mFocusObject.getTypeName() == typeid(ESM::Activator).name())
+                {
+                    ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData>* ref = mFocusObject.get<ESM::Activator>();
+
+                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+                    box->setTextAlign(Align::HCenter);
+                    box->setProperty("Static", "true");
+                    box->setCaption(ref->base->name);
+
+                    /// \todo
+
+                    tooltipSize = box->getTextSize() + IntSize(12,12);
+
+                    mDynamicToolTipBox->setVisible(ref->base->name != "");
+                }
+
+                else
+                {
+                    // object without tooltip
+                    mDynamicToolTipBox->setVisible(false);
+                }
+
+                // adjust tooltip size to fit its content, position it above the crosshair
+                /// \todo Slide the tooltip along the bounding box of the focused object (like in Morrowind)
+                setCoord(viewSize.width/2 - (tooltipSize.width)/2.f,
+                        viewSize.height/2 - (tooltipSize.height) - 32,
+                        tooltipSize.width,
+                        tooltipSize.height);
+            }
+            mFocusChanged = false;
+        }
+        else
+            mDynamicToolTipBox->setVisible(false);
+    }
 }
 
 void ToolTips::enterGameMode()
@@ -61,3 +422,12 @@ void ToolTips::enterGuiMode()
 {
     mGameMode = false;
 }
+
+void ToolTips::setFocusObject(const MWWorld::Ptr& focus)
+{
+    if (focus != mFocusObject)
+    {
+        mFocusObject = focus;
+        mFocusChanged = true;
+    }
+}
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index aa929ff51..3052abb7a 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -3,6 +3,7 @@
 #define MWGUI_TOOLTIPS_H
 
 #include <openengine/gui/layout.hpp>
+#include "../mwworld/ptr.hpp"
 
 namespace MWGui
 {
@@ -16,6 +17,8 @@ namespace MWGui
         void enterGameMode();
         void enterGuiMode();
 
+        void setFocusObject(const MWWorld::Ptr& focus);
+
         void adjustScreen(int screenWidth, int screenHeight);
 
     private:
@@ -24,6 +27,9 @@ namespace MWGui
 
         MyGUI::Widget* mDynamicToolTipBox;
 
+        MWWorld::Ptr mFocusObject;
+        bool mFocusChanged;
+
         bool mGameMode;
     };
 }
diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp
index 1ef5cae42..909be0ac2 100644
--- a/apps/openmw/mwgui/window_manager.cpp
+++ b/apps/openmw/mwgui/window_manager.cpp
@@ -492,3 +492,8 @@ int WindowManager::toggleFps()
     Settings::Manager::setInt("fps", "HUD", showFPSLevel);
     return showFPSLevel;
 }
+
+void WindowManager::setFocusObject(const MWWorld::Ptr& focus)
+{
+    mToolTips->setFocusObject(focus);
+}
diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp
index 1cbd8f6a6..d5f0683b8 100644
--- a/apps/openmw/mwgui/window_manager.hpp
+++ b/apps/openmw/mwgui/window_manager.hpp
@@ -158,6 +158,8 @@ namespace MWGui
     void setPlayerPos(const float x, const float y); ///< set player position in map space
     void setPlayerDir(const float x, const float y); ///< set player view direction in map space
 
+    void setFocusObject(const MWWorld::Ptr& focus);
+
     void toggleFogOfWar();
 
     int toggleFps();
diff --git a/apps/openmw/mwrender/shadows.cpp b/apps/openmw/mwrender/shadows.cpp
index bf5602f43..9a4ae7243 100644
--- a/apps/openmw/mwrender/shadows.cpp
+++ b/apps/openmw/mwrender/shadows.cpp
@@ -66,7 +66,10 @@ void Shadows::recreate()
     if (split)
     {
         mPSSMSetup = new PSSMShadowCameraSetup();
-        mPSSMSetup->setSplitPadding(5);
+
+        // Make sure to keep this in sync with the camera's near clip distance!
+        mPSSMSetup->setSplitPadding(mRendering->getCamera()->getNearClipDistance());
+
         mPSSMSetup->calculateSplitPoints(3, mRendering->getCamera()->getNearClipDistance(), mShadowFar);
 
         const Real adjustFactors[3] = {64, 64, 64};
diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp
index 1c64039d4..4719a25cf 100644
--- a/apps/openmw/mwworld/world.cpp
+++ b/apps/openmw/mwworld/world.cpp
@@ -13,6 +13,7 @@
 
 #include "../mwsound/soundmanager.hpp"
 
+#include "../mwgui/window_manager.hpp"
 
 #include "ptr.hpp"
 #include "environment.hpp"
@@ -737,6 +738,17 @@ namespace MWWorld
 
         mWeatherManager->update (duration);
 
+        // inform the GUI about focused object
+        try
+        {
+            mEnvironment.mWindowManager->setFocusObject(getPtrViaHandle(mFacedHandle));
+        }
+        catch (std::runtime_error&)
+        {
+            MWWorld::Ptr null;
+            mEnvironment.mWindowManager->setFocusObject(null);
+        }
+
         if (!mRendering->occlusionQuerySupported())
         {
             // cast a ray from player to sun to detect if the sun is visible
diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml
index 76df7b9a7..26fc1eeab 100644
--- a/files/mygui/openmw_tooltips.xml
+++ b/files/mygui/openmw_tooltips.xml
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <MyGUI type="Layout">
-    <Widget type="Widget" layer="Popup" position="0 0 300 200" name="_Main">
+    <Widget type="Widget" layer="Popup" position="0 0 300 300" name="_Main">
 
         <!-- Simple text-only tooltip -->
-        <Widget type="Widget" skin="HUD_Box" position="0 0 300 200" align="Stretch" name="TextToolTipBox">
-            <Widget type="EditBox" skin="MW_TextEdit" position="0 0 300 200" align="Stretch" name="TextToolTip">
+        <Widget type="Widget" skin="HUD_Box" position="0 0 300 300" align="Stretch" name="TextToolTipBox">
+            <Property key="Visible" value="false"/>
+            <Widget type="EditBox" skin="MW_TextEdit" position="0 0 300 300" align="Stretch" name="TextToolTip">
                 <Property key="WordWrap" value="true"/>
                 <Property key="Static" value="true"/>
                 <Property key="TextAlign" value="Left Top"/>
@@ -13,7 +14,8 @@
         </Widget>
 
         <!-- Dynamically constructed tooltip goes here -->
-        <Widget type="Widget" skin="HUD_Box" position="0 0 300 200" align="Stretch" name="DynamicToolTipBox">
+        <Widget type="Widget" skin="HUD_Box" position="0 0 300 300" align="Stretch" name="DynamicToolTipBox">
+            <Property key="Visible" value="false"/>
         </Widget>
 
     </Widget>

From 705d4c6d54f94bad23fdf07efedc5842f73322de Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sun, 15 Apr 2012 21:14:14 +0200
Subject: [PATCH 03/44] mostly complete

---
 apps/openmw/mwgui/stats_window.cpp   |  16 +-
 apps/openmw/mwgui/stats_window.hpp   |   2 +-
 apps/openmw/mwgui/tooltips.cpp       | 720 ++++++++++++++-------------
 apps/openmw/mwgui/tooltips.hpp       |  24 +-
 apps/openmw/mwgui/window_manager.cpp |   2 +-
 files/mygui/openmw_tooltips.xml      |   2 +-
 6 files changed, 406 insertions(+), 360 deletions(-)

diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp
index 675e5141f..23f93cd1b 100644
--- a/apps/openmw/mwgui/stats_window.cpp
+++ b/apps/openmw/mwgui/stats_window.cpp
@@ -251,14 +251,18 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My
     coord2.top += lineHeight;
 }
 
-MyGUI::TextBox* StatsWindow::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
+MyGUI::TextBox* StatsWindow::addValueItem(const std::string text, const std::string& tooltip, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
 {
     MyGUI::TextBox *skillNameWidget, *skillValueWidget;
 
     skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Default);
     skillNameWidget->setCaption(text);
+    skillNameWidget->setUserString("ToolTipType", "Text");
+    skillNameWidget->setUserString("ToolTipText", tooltip);
 
     skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Default);
+    skillValueWidget->setUserString("ToolTipType", "Text");
+    skillValueWidget->setUserString("ToolTipText", tooltip);
     setStyledText(skillValueWidget, style, value);
 
     skillWidgets.push_back(skillNameWidget);
@@ -310,7 +314,7 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId,
             style = CS_Super;
         else if (modified < base)
             style = CS_Sub;
-        MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), style, coord1, coord2);
+        MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), "", boost::lexical_cast<std::string>(static_cast<int>(modified)), style, coord1, coord2);
         skillWidgetMap[skillId] = widget;
     }
 }
@@ -369,8 +373,12 @@ void StatsWindow::updateSkillArea()
     if (!skillWidgets.empty())
         addSeparator(coord1, coord2);
 
-    addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"), boost::lexical_cast<std::string>(static_cast<int>(reputation)), CS_Normal, coord1, coord2);
-    addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"), boost::lexical_cast<std::string>(static_cast<int>(bounty)), CS_Normal, coord1, coord2);
+    addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"),
+                mWindowManager.getGameSettingString("sSkillsMenuReputationHelp", ""),
+                boost::lexical_cast<std::string>(static_cast<int>(reputation)), CS_Normal, coord1, coord2);
+    addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"),
+                mWindowManager.getGameSettingString("sCrimeHelp", ""),
+                boost::lexical_cast<std::string>(static_cast<int>(bounty)), CS_Normal, coord1, coord2);
 
     clientHeight = coord1.top;
     updateScroller();
diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp
index f2731e545..1ce3db98d 100644
--- a/apps/openmw/mwgui/stats_window.hpp
+++ b/apps/openmw/mwgui/stats_window.hpp
@@ -53,7 +53,7 @@ namespace MWGui
             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);
             void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
-            MyGUI::TextBox* addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
+            MyGUI::TextBox* addValueItem(const std::string text, const std::string& tooltip, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
             void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
             void updateScroller();
 
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index 7f45bdbdd..4c435e3bf 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -1,12 +1,15 @@
 #include "tooltips.hpp"
+#include "window_manager.hpp"
+
+#include <boost/lexical_cast.hpp>
 
 using namespace MWGui;
 using namespace MyGUI;
 
-ToolTips::ToolTips() :
+ToolTips::ToolTips(WindowManager* windowManager) :
     Layout("openmw_tooltips.xml")
     , mGameMode(true)
-    , mFocusChanged(true)
+    , mWindowManager(windowManager)
 {
     getWidget(mTextToolTip, "TextToolTip");
     getWidget(mTextToolTipBox, "TextToolTipBox");
@@ -31,19 +34,32 @@ void ToolTips::onFrame(float frameDuration)
     if (!mGameMode)
     {
         mDynamicToolTipBox->setVisible(false);
+        mTextToolTipBox->setVisible(true);
 
         Widget* focus = InputManager::getInstance().getMouseFocusWidget();
-        if (focus == 0) return;
+        if (focus == 0)
+        {
+            mTextToolTipBox->setVisible(false);
+            return;
+        }
+
+        std::string type = focus->getUserString("ToolTipType");
+        std::string text = focus->getUserString("ToolTipText");
+        if (type == "" || text == "")
+        {
+            mTextToolTipBox->setVisible(false);
+            return;
+        }
 
         // this the maximum width of the tooltip before it starts word-wrapping
         setCoord(0, 0, 300, 300);
 
-        mTextToolTip->setCaption("Focused: " + focus->getName() + "\nType: " + focus->getTypeName());
+        mTextToolTip->setCaption(text);
         const IntSize &textSize = mTextToolTip->getTextSize();
 
         IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
 
-        IntSize size = textSize + IntSize(12, 12);
+        IntSize size = textSize + IntSize(6, 6);
         // make the tooltip stay completely in the viewport
         if ((tooltipPosition.left + size.width) > viewSize.width)
         {
@@ -62,351 +78,16 @@ void ToolTips::onFrame(float frameDuration)
 
         if (!mFocusObject.isEmpty())
         {
-            if (mFocusChanged)
-            {
-                for (size_t i=0; i<mDynamicToolTipBox->getChildCount(); ++i)
-                {
-                    mDynamicToolTipBox->_destroyChildWidget(mDynamicToolTipBox->getChildAt(i));
-                }
+            IntSize tooltipSize = getToolTipViaPtr();
 
-                // this the maximum width of the tooltip before it starts word-wrapping
-                setCoord(0, 0, 300, 300);
+            tooltipSize += IntSize(6,6); // padding, adjust for skin
 
-                IntSize tooltipSize;
-
-                /// \todo Not sure about levelled lists (ESM::CreateLevList and ESM::ItemLevList). I think
-                /// they are supposed to spawn a concrete object (Creature or item of any type), so
-                /// the player wouldn't encounter them and we don't have to handle them here. 
-
-                // --------------------  Door -------------------------------
-                if (mFocusObject.getTypeName() == typeid(ESM::Door).name())
-                {
-                    ESMS::LiveCellRef<ESM::Door, MWWorld::RefData>* ref = mFocusObject.get<ESM::Door>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setProperty("MultiLine", "true");
-
-                    std::string caption = ref->base->name;
-                    /// \todo If destCell is empty, the teleport target is an exterior cell. In that case we 
-                    /// need to fetch that cell (via target position) and retrieve the region name.
-                    if (ref->ref.teleport && (ref->ref.destCell != ""))
-                    {
-                        caption += "\n-";
-                        caption += "\n"+ref->ref.destCell;
-                    }
-                    box->setCaption(caption);
-
-                    /// \todo Lock level, trap (retrieve GMST)
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  NPC -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::NPC).name())
-                {
-                    /// \todo We don't want tooltips for NPCs in combat mode.
-                    ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mFocusObject.get<ESM::NPC>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Creature -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Creature).name())
-                {
-                    ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mFocusObject.get<ESM::Creature>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  CreatureLevList -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Creature).name())
-                {
-                    ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mFocusObject.get<ESM::Creature>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Container -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Container).name())
-                {
-                    ESMS::LiveCellRef<ESM::Container, MWWorld::RefData>* ref = mFocusObject.get<ESM::Container>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo Lock level, trap (retrieve GMST)
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Potion -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Potion).name())
-                {
-                    ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData>* ref = mFocusObject.get<ESM::Potion>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Apparatus -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Apparatus).name())
-                {
-                    ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData>* ref = mFocusObject.get<ESM::Potion>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Armor -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Armor).name())
-                {
-                    ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData>* ref = mFocusObject.get<ESM::Armor>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo weight, armor value, value, durability..
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Book -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Book).name())
-                {
-                    ESMS::LiveCellRef<ESM::Book, MWWorld::RefData>* ref = mFocusObject.get<ESM::Book>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Clothing -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Clothing).name())
-                {
-                    ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData>* ref = mFocusObject.get<ESM::Clothing>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Ingredient -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Ingredient).name())
-                {
-                    ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData>* ref = mFocusObject.get<ESM::Ingredient>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Light -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Light).name())
-                {
-                    ESMS::LiveCellRef<ESM::Light, MWWorld::RefData>* ref = mFocusObject.get<ESM::Light>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(ref->base->name != "");
-                }
-
-                // --------------------  Tool -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Tool).name())
-                {
-                    ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData>* ref = mFocusObject.get<ESM::Tool>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Miscellaneous -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Miscellaneous).name())
-                {
-                    ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData>* ref = mFocusObject.get<ESM::Miscellaneous>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Probe -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Probe).name())
-                {
-                    ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData>* ref = mFocusObject.get<ESM::Probe>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Repair -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Repair).name())
-                {
-                    ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData>* ref = mFocusObject.get<ESM::Repair>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Weapon -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Weapon).name())
-                {
-                    ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData>* ref = mFocusObject.get<ESM::Weapon>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(true);
-                }
-
-                // --------------------  Activator -------------------------------
-                else if (mFocusObject.getTypeName() == typeid(ESM::Activator).name())
-                {
-                    ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData>* ref = mFocusObject.get<ESM::Activator>();
-
-                    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("MW_TextEdit", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-                    box->setTextAlign(Align::HCenter);
-                    box->setProperty("Static", "true");
-                    box->setCaption(ref->base->name);
-
-                    /// \todo
-
-                    tooltipSize = box->getTextSize() + IntSize(12,12);
-
-                    mDynamicToolTipBox->setVisible(ref->base->name != "");
-                }
-
-                else
-                {
-                    // object without tooltip
-                    mDynamicToolTipBox->setVisible(false);
-                }
-
-                // adjust tooltip size to fit its content, position it above the crosshair
-                /// \todo Slide the tooltip along the bounding box of the focused object (like in Morrowind)
-                setCoord(viewSize.width/2 - (tooltipSize.width)/2.f,
-                        viewSize.height/2 - (tooltipSize.height) - 32,
-                        tooltipSize.width,
-                        tooltipSize.height);
-            }
-            mFocusChanged = false;
+            // adjust tooltip size to fit its content, position it above the crosshair
+            /// \todo Slide the tooltip along the bounding box of the focused object (like in Morrowind)
+            setCoord(viewSize.width/2 - (tooltipSize.width)/2.f,
+                    viewSize.height/2 - (tooltipSize.height) - 32,
+                    tooltipSize.width,
+                    tooltipSize.height);
         }
         else
             mDynamicToolTipBox->setVisible(false);
@@ -425,9 +106,346 @@ void ToolTips::enterGuiMode()
 
 void ToolTips::setFocusObject(const MWWorld::Ptr& focus)
 {
-    if (focus != mFocusObject)
+    mFocusObject = focus;
+}
+
+IntSize ToolTips::getToolTipViaPtr ()
+{
+    /// \todo we are destroying/creating the tooltip widgets every frame here,
+    /// because the tooltip might change (e.g. when trap is activated)
+    /// is there maybe a better way (listener when the object changes)?
+    for (size_t i=0; i<mDynamicToolTipBox->getChildCount(); ++i)
     {
-        mFocusObject = focus;
-        mFocusChanged = true;
+        mDynamicToolTipBox->_destroyChildWidget(mDynamicToolTipBox->getChildAt(i));
+    }
+
+    // this the maximum width of the tooltip before it starts word-wrapping
+    setCoord(0, 0, 300, 300);
+
+    IntSize tooltipSize;
+
+    // --------------------  Door -------------------------------
+    if (mFocusObject.getTypeName() == typeid(ESM::Door).name())
+    {
+        ESMS::LiveCellRef<ESM::Door, MWWorld::RefData>* ref = mFocusObject.get<ESM::Door>();
+
+        std::string text;
+        /// \todo If destCell is empty, the teleport target is an exterior cell. In that case we 
+        /// need to fetch that cell (via target position) and retrieve the region name.
+        if (ref->ref.teleport && (ref->ref.destCell != ""))
+        {
+            text += "\n" + mWindowManager->getGameSettingString("sTo", "to");
+            text += "\n"+ref->ref.destCell;
+        }
+
+        if (ref->ref.lockLevel > 0)
+            text += "\n" + mWindowManager->getGameSettingString("sLockLevel", "Lock") + ": " + toString(ref->ref.lockLevel);
+        if (ref->ref.trap != "")
+            text += "\n" + mWindowManager->getGameSettingString("sTrapped", "Trapped!");
+
+        tooltipSize = createToolTip(ref->base->name, text);
+    }
+
+    // --------------------  NPC -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::NPC).name())
+    {
+        /// \todo We don't want tooltips for NPCs in combat mode.
+        ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mFocusObject.get<ESM::NPC>();
+
+        tooltipSize = createToolTip(ref->base->name, "");
+    }
+
+    // --------------------  Creature -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Creature).name())
+    {
+        /// \todo We don't want tooltips for Creatures in combat mode.
+        ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mFocusObject.get<ESM::Creature>();
+
+        tooltipSize = createToolTip(ref->base->name, "");
+    }
+
+    // --------------------  Container -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Container).name())
+    {
+        ESMS::LiveCellRef<ESM::Container, MWWorld::RefData>* ref = mFocusObject.get<ESM::Container>();
+
+        std::string text;
+
+        if (ref->ref.lockLevel > 0)
+            text += "\n" + mWindowManager->getGameSettingString("sLockLevel", "Lock") + ": " + toString(ref->ref.lockLevel);
+        if (ref->ref.trap != "")
+            text += "\n" + mWindowManager->getGameSettingString("sTrapped", "Trapped!");
+
+        tooltipSize = createToolTip(ref->base->name, text);
+    }
+
+    // --------------------  Potion -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Potion).name())
+    {
+        ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData>* ref = mFocusObject.get<ESM::Potion>();
+
+        /// \todo magic effects
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Apparatus -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Apparatus).name())
+    {
+        ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData>* ref = mFocusObject.get<ESM::Apparatus>();
+
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sQuality", "Quality") + ": " + toString(ref->base->data.quality);
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Armor -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Armor).name())
+    {
+        ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData>* ref = mFocusObject.get<ESM::Armor>();
+
+        /// \todo magic effects, armor type (medium/light/heavy)
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sArmorRating", "Armor Rating") + ": " + toString(ref->base->data.armor);
+
+        /// \todo where is the current armor health stored?
+        //text += "\n" + mWindowManager->getGameSettingString("sCondition", "Condition") + ": " + toString(ref->base->data.health);
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Book -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Book).name())
+    {
+        ESMS::LiveCellRef<ESM::Book, MWWorld::RefData>* ref = mFocusObject.get<ESM::Book>();
+
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Clothing -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Clothing).name())
+    {
+        ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData>* ref = mFocusObject.get<ESM::Clothing>();
+
+        /// \todo magic effects
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Ingredient -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Ingredient).name())
+    {
+        ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData>* ref = mFocusObject.get<ESM::Ingredient>();
+
+        /// \todo magic effects
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Light -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Light).name())
+    {
+        ESMS::LiveCellRef<ESM::Light, MWWorld::RefData>* ref = mFocusObject.get<ESM::Light>();
+
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Tool -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Tool).name())
+    {
+        ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData>* ref = mFocusObject.get<ESM::Tool>();
+
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sUses", "Uses") + ": " + toString(ref->base->data.uses);
+        text += "\n" + mWindowManager->getGameSettingString("sQuality", "Quality") + ": " + toString(ref->base->data.quality);
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Miscellaneous -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Miscellaneous).name())
+    {
+        ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData>* ref = mFocusObject.get<ESM::Miscellaneous>();
+
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Probe -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Probe).name())
+    {
+        ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData>* ref = mFocusObject.get<ESM::Probe>();
+
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sUses", "Uses") + ": " + toString(ref->base->data.uses);
+        text += "\n" + mWindowManager->getGameSettingString("sQuality", "Quality") + ": " + toString(ref->base->data.quality);
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Repair -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Repair).name())
+    {
+        ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData>* ref = mFocusObject.get<ESM::Repair>();
+
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sUses", "Uses") + ": " + toString(ref->base->data.uses);
+        text += "\n" + mWindowManager->getGameSettingString("sQuality", "Quality") + ": " + toString(ref->base->data.quality);
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+    }
+
+    // --------------------  Weapon -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Weapon).name())
+    {
+        ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData>* ref = mFocusObject.get<ESM::Weapon>();
+
+        /// \todo weapon damage, magic effects, health (condition)
+
+        std::string text;
+        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
+        text += getValueString(ref->base->data.value);
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, "");
+    }
+
+    // --------------------  Activator -------------------------------
+    else if (mFocusObject.getTypeName() == typeid(ESM::Activator).name())
+    {
+        ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData>* ref = mFocusObject.get<ESM::Activator>();
+
+        tooltipSize = createToolTip(ref->base->name, "");
+    }
+
+    else
+    {
+        // object without tooltip
+        mDynamicToolTipBox->setVisible(false);
+    }
+
+    return tooltipSize;
+}
+
+void ToolTips::findImageExtension(std::string& image)
+{
+    int len = image.size();
+    if (len < 4) return;
+
+    if (!Ogre::ResourceGroupManager::getSingleton().resourceExists(Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, image))
+    {
+        // Change texture extension to .dds
+        image[len-3] = 'd';
+        image[len-2] = 'd';
+        image[len-1] = 's';
     }
 }
+
+IntSize ToolTips::createImageToolTip(const std::string& caption, const std::string& image, const std::string& text)
+{
+    // remove the first newline (easier this way)
+    std::string realText = text;
+    if (realText.size() > 0)
+        realText.erase(0, 1);
+
+    std::string realImage = "icons\\" + image;
+    findImageExtension(realImage);
+
+    const int imageSize = 32;
+
+    EditBox* captionWidget = mDynamicToolTipBox->createWidget<EditBox>("NormalText", IntCoord(0, 0, 300, 300), Align::Left | Align::Top, "ToolTipCaption");
+    captionWidget->setProperty("Static", "true");
+    captionWidget->setCaption(caption);
+    EditBox* textWidget = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, imageSize, 300, 262), Align::Stretch, "ToolTipText");
+    textWidget->setProperty("Static", "true");
+    textWidget->setProperty("MultiLine", "true");
+    textWidget->setCaption(realText);
+    textWidget->setTextAlign(Align::HCenter);
+
+    IntSize captionSize = captionWidget->getTextSize();
+    IntSize textSize = textWidget->getTextSize();
+
+    captionSize += IntSize(imageSize, 0); // adjust for image
+    IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width), ((realText != "") ? textSize.height : 0) + imageSize );
+
+    ImageBox* imageWidget = mDynamicToolTipBox->createWidget<ImageBox>("ImageBox",
+        IntCoord((totalSize.width - captionSize.width)/2, 0, imageSize, imageSize),
+        Align::Left | Align::Top, "ToolTipImage");
+    imageWidget->setImageTexture(realImage);
+
+    captionWidget->setCoord( (totalSize.width - captionSize.width)/2 + imageSize, (32-captionSize.height)/2, captionSize.width-imageSize, captionSize.height);
+
+    mDynamicToolTipBox->setVisible(caption != "");
+
+    return totalSize;
+}
+
+IntSize ToolTips::createToolTip(const std::string& caption, const std::string& text)
+{
+    // remove the first newline (easier this way)
+    std::string realText = text;
+    if (realText.size() > 0)
+        realText.erase(0, 1);
+
+    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("NormalText", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+    box->setTextAlign(Align::HCenter);
+    box->setProperty("Static", "true");
+    box->setProperty("MultiLine", "true");
+    box->setCaption(caption + (realText != "" ? "\n#BF9959" + realText : ""));
+
+    mDynamicToolTipBox->setVisible(caption != "");
+
+    return box->getTextSize();
+}
+
+std::string ToolTips::toString(const float value)
+{
+    std::ostringstream stream;
+    stream << std::setprecision(3) << value;
+    return stream.str();
+}
+
+std::string ToolTips::toString(const int value)
+{
+    std::ostringstream stream;
+    stream << value;
+    return stream.str();
+}
+
+std::string ToolTips::getValueString(const int value)
+{
+    if (value == 0)
+        return "";
+    else
+        return "\n" + mWindowManager->getGameSettingString("sValue", "Value") + ": " + toString(value);
+}
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index 3052abb7a..cb1af7349 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -7,10 +7,12 @@
 
 namespace MWGui
 {
+    class WindowManager;
+
     class ToolTips : public OEngine::GUI::Layout
     {
     public:
-        ToolTips();
+        ToolTips(WindowManager* windowManager);
 
         void onFrame(float frameDuration);
 
@@ -27,8 +29,26 @@ namespace MWGui
 
         MyGUI::Widget* mDynamicToolTipBox;
 
+        WindowManager* mWindowManager;
+
         MWWorld::Ptr mFocusObject;
-        bool mFocusChanged;
+
+        void findImageExtension(std::string& image);
+
+        MyGUI::IntSize getToolTipViaPtr ();
+        ///< @return requested tooltip size
+
+        MyGUI::IntSize createImageToolTip(const std::string& caption, const std::string& image, const std::string& text);
+        ///< @return requested tooltip size
+
+        MyGUI::IntSize createToolTip(const std::string& caption, const std::string& text);
+        ///< @return requested tooltip size
+
+        std::string getValueString(const int value);
+        ///< get "Value: X" string or "" if value is 0
+
+        std::string toString(const float value);
+        std::string toString(const int value);
 
         bool mGameMode;
     };
diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp
index 909be0ac2..8ed2050cc 100644
--- a/apps/openmw/mwgui/window_manager.cpp
+++ b/apps/openmw/mwgui/window_manager.cpp
@@ -82,7 +82,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment,
     mJournal = new JournalWindow(*this);
     mMessageBoxManager = new MessageBoxManager(this);
     dialogueWindow = new DialogueWindow(*this,environment);
-    mToolTips = new ToolTips();
+    mToolTips = new ToolTips(this);
 
     // The HUD is always on
     hud->setVisible(true);
diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml
index 26fc1eeab..1d55bd12f 100644
--- a/files/mygui/openmw_tooltips.xml
+++ b/files/mygui/openmw_tooltips.xml
@@ -6,7 +6,7 @@
         <!-- Simple text-only tooltip -->
         <Widget type="Widget" skin="HUD_Box" position="0 0 300 300" align="Stretch" name="TextToolTipBox">
             <Property key="Visible" value="false"/>
-            <Widget type="EditBox" skin="MW_TextEdit" position="0 0 300 300" align="Stretch" name="TextToolTip">
+            <Widget type="EditBox" skin="NormalText" position="0 0 300 300" align="Stretch" name="TextToolTip">
                 <Property key="WordWrap" value="true"/>
                 <Property key="Static" value="true"/>
                 <Property key="TextAlign" value="Left Top"/>

From 5d9648d6457b5b3e812fbfadb4c4a24a093a6f9c Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sun, 15 Apr 2012 22:00:28 +0200
Subject: [PATCH 04/44] fix const reference

---
 apps/openmw/mwgui/stats_window.cpp | 2 +-
 apps/openmw/mwgui/stats_window.hpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp
index 23f93cd1b..374672883 100644
--- a/apps/openmw/mwgui/stats_window.cpp
+++ b/apps/openmw/mwgui/stats_window.cpp
@@ -251,7 +251,7 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My
     coord2.top += lineHeight;
 }
 
-MyGUI::TextBox* StatsWindow::addValueItem(const std::string text, const std::string& tooltip, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
+MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
 {
     MyGUI::TextBox *skillNameWidget, *skillValueWidget;
 
diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp
index 1ce3db98d..66655a055 100644
--- a/apps/openmw/mwgui/stats_window.hpp
+++ b/apps/openmw/mwgui/stats_window.hpp
@@ -53,7 +53,7 @@ namespace MWGui
             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);
             void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
-            MyGUI::TextBox* addValueItem(const std::string text, const std::string& tooltip, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
+            MyGUI::TextBox* addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
             void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
             void updateScroller();
 

From 10398723d877b6ce1b6469fc470dbd96b9a1b236 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sun, 15 Apr 2012 22:44:38 +0200
Subject: [PATCH 05/44] use different image pixel format

---
 libs/openengine/ogre/imagerotate.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libs/openengine/ogre/imagerotate.cpp b/libs/openengine/ogre/imagerotate.cpp
index 1147559d6..11fd5eea6 100644
--- a/libs/openengine/ogre/imagerotate.cpp
+++ b/libs/openengine/ogre/imagerotate.cpp
@@ -54,7 +54,7 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest
                     TEX_TYPE_2D,
                     width, height,
                     0,
-                    PF_A8R8G8B8,
+                    PF_FLOAT16_RGBA,
                     TU_RENDERTARGET);
 
     RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget();
@@ -63,7 +63,6 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest
     vp->setOverlaysEnabled(false);
     vp->setShadowsEnabled(false);
     vp->setBackgroundColour(ColourValue(0,0,0,0));
-    vp->setClearEveryFrame(true, FBT_DEPTH);
 
     rtt->update();
 

From 194ecf274c09140ffd0afa73b9ac359efc0ef15c Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 00:16:35 +0200
Subject: [PATCH 06/44] attribute tooltips

---
 apps/openmw/mwgui/stats_window.cpp | 97 ++++++++++++++++++++++++++++++
 apps/openmw/mwgui/stats_window.hpp |  2 +
 apps/openmw/mwgui/tooltips.cpp     | 83 +++++++++++++++----------
 apps/openmw/mwgui/tooltips.hpp     |  8 +--
 files/mygui/openmw_tooltips.xml    | 10 ---
 5 files changed, 153 insertions(+), 47 deletions(-)

diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp
index 374672883..cf279faf7 100644
--- a/apps/openmw/mwgui/stats_window.cpp
+++ b/apps/openmw/mwgui/stats_window.cpp
@@ -72,6 +72,8 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager)
 
     MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
     t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize);
+
+    setupToolTips();
 }
 
 void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos)
@@ -394,3 +396,98 @@ void StatsWindow::onPinToggled()
 {
     mWindowManager.setHMSVisibility(!mPinned);
 }
+
+void StatsWindow::setupToolTips()
+{
+
+    const ESMS::ESMStore &store = mWindowManager.getStore();
+    MyGUI::Widget* widget;
+
+    getWidget(widget, "Attrib1");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeStrength")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sStrDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_strength.dds");
+    getWidget(widget, "AttribVal1");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeStrength")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sStrDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_strength.dds");
+
+    getWidget(widget, "Attrib2");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeIntelligence")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sIntDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_int.dds");
+    getWidget(widget, "AttribVal2");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeIntelligence")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sIntDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_int.dds");
+
+    getWidget(widget, "Attrib3");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeWillpower")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sWilDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_wilpower.dds");
+    getWidget(widget, "AttribVal3");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeWillpower")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sWilDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_wilpower.dds");
+
+    getWidget(widget, "Attrib4");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeAgility")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sAgiDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_agility.dds");
+    getWidget(widget, "AttribVal4");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeAgility")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sAgiDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_agility.dds");
+
+    getWidget(widget, "Attrib5");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeSpeed")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sSpdDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_speed.dds");
+    getWidget(widget, "AttribVal5");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeSpeed")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sSpdDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_speed.dds");
+
+    getWidget(widget, "Attrib6");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeEndurance")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sEndDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_endurance.dds");
+    getWidget(widget, "AttribVal6");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeEndurance")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sEndDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_endurance.dds");
+
+    getWidget(widget, "Attrib7");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributePersonality")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sPerDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_personality.dds");
+    getWidget(widget, "AttribVal7");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributePersonality")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sPerDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_personality.dds");
+
+    getWidget(widget, "Attrib8");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeLuck")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sLucDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_luck.dds");
+    getWidget(widget, "AttribVal8");
+    widget->setUserString("ToolTipType", "ImageCaptionText");
+    widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeLuck")->str);
+    widget->setUserString("ToolTipText", store.gameSettings.find ("sLucDesc")->str);
+    widget->setUserString("ToolTipImage", "k\\attribute_luck.dds");
+}
diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp
index 66655a055..075c08dd3 100644
--- a/apps/openmw/mwgui/stats_window.hpp
+++ b/apps/openmw/mwgui/stats_window.hpp
@@ -57,6 +57,8 @@ namespace MWGui
             void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
             void updateScroller();
 
+            void setupToolTips();
+
             void onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos);
             void onWindowResize(MyGUI::Window* window);
 
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index 4c435e3bf..4dcb1cda7 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -11,8 +11,6 @@ ToolTips::ToolTips(WindowManager* windowManager) :
     , mGameMode(true)
     , mWindowManager(windowManager)
 {
-    getWidget(mTextToolTip, "TextToolTip");
-    getWidget(mTextToolTipBox, "TextToolTipBox");
     getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
 
     mDynamicToolTipBox->setVisible(false);
@@ -20,8 +18,6 @@ ToolTips::ToolTips(WindowManager* windowManager) :
     // turn off mouse focus so that getMouseFocusWidget returns the correct widget,
     // even if the mouse is over the tooltip
     mDynamicToolTipBox->setNeedMouseFocus(false);
-    mTextToolTipBox->setNeedMouseFocus(false);
-    mTextToolTip->setNeedMouseFocus(false);
     mMainWidget->setNeedMouseFocus(false);
 }
 
@@ -29,37 +25,54 @@ void ToolTips::onFrame(float frameDuration)
 {
     /// \todo Store a MWWorld::Ptr in the widget user data, retrieve it here and construct a tooltip dynamically
 
+    /// \todo we are destroying/creating the tooltip widgets every frame here,
+    /// because the tooltip might change (e.g. when trap is activated)
+    /// is there maybe a better way (listener when the object changes)?
+    for (size_t i=0; i<mDynamicToolTipBox->getChildCount(); ++i)
+    {
+        mDynamicToolTipBox->_destroyChildWidget(mDynamicToolTipBox->getChildAt(i));
+    }
+
     const IntSize &viewSize = RenderManager::getInstance().getViewSize();
 
     if (!mGameMode)
     {
-        mDynamicToolTipBox->setVisible(false);
-        mTextToolTipBox->setVisible(true);
-
         Widget* focus = InputManager::getInstance().getMouseFocusWidget();
         if (focus == 0)
         {
-            mTextToolTipBox->setVisible(false);
-            return;
-        }
-
-        std::string type = focus->getUserString("ToolTipType");
-        std::string text = focus->getUserString("ToolTipText");
-        if (type == "" || text == "")
-        {
-            mTextToolTipBox->setVisible(false);
+            mDynamicToolTipBox->setVisible(false);
             return;
         }
 
         // this the maximum width of the tooltip before it starts word-wrapping
         setCoord(0, 0, 300, 300);
 
-        mTextToolTip->setCaption(text);
-        const IntSize &textSize = mTextToolTip->getTextSize();
+        IntSize tooltipSize;
+
+        std::string type = focus->getUserString("ToolTipType");
+        std::string text = focus->getUserString("ToolTipText");
+        if (type == "")
+        {
+            mDynamicToolTipBox->setVisible(false);
+            return;
+        }
+        else if (type == "Text")
+            tooltipSize = createToolTip(text);
+        else if (type == "CaptionText")
+        {
+            std::string caption = focus->getUserString("ToolTipCaption");
+            tooltipSize = createToolTip(caption, text);
+        }
+        else if (type == "ImageCaptionText")
+        {
+            std::string caption = focus->getUserString("ToolTipCaption");
+            std::string image = focus->getUserString("ToolTipImage");
+            tooltipSize = createImageToolTip(caption, image, text);
+        }
 
         IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
 
-        IntSize size = textSize + IntSize(6, 6);
+        IntSize size = tooltipSize + IntSize(6, 6);
         // make the tooltip stay completely in the viewport
         if ((tooltipPosition.left + size.width) > viewSize.width)
         {
@@ -74,8 +87,6 @@ void ToolTips::onFrame(float frameDuration)
     }
     else
     {
-        mTextToolTipBox->setVisible(false);
-
         if (!mFocusObject.isEmpty())
         {
             IntSize tooltipSize = getToolTipViaPtr();
@@ -111,14 +122,6 @@ void ToolTips::setFocusObject(const MWWorld::Ptr& focus)
 
 IntSize ToolTips::getToolTipViaPtr ()
 {
-    /// \todo we are destroying/creating the tooltip widgets every frame here,
-    /// because the tooltip might change (e.g. when trap is activated)
-    /// is there maybe a better way (listener when the object changes)?
-    for (size_t i=0; i<mDynamicToolTipBox->getChildCount(); ++i)
-    {
-        mDynamicToolTipBox->_destroyChildWidget(mDynamicToolTipBox->getChildAt(i));
-    }
-
     // this the maximum width of the tooltip before it starts word-wrapping
     setCoord(0, 0, 300, 300);
 
@@ -337,7 +340,7 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, "");
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
     }
 
     // --------------------  Activator -------------------------------
@@ -375,7 +378,7 @@ IntSize ToolTips::createImageToolTip(const std::string& caption, const std::stri
 {
     // remove the first newline (easier this way)
     std::string realText = text;
-    if (realText.size() > 0)
+    if (realText.size() > 0 && realText[0] == '\n')
         realText.erase(0, 1);
 
     std::string realImage = "icons\\" + image;
@@ -389,6 +392,7 @@ IntSize ToolTips::createImageToolTip(const std::string& caption, const std::stri
     EditBox* textWidget = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, imageSize, 300, 262), Align::Stretch, "ToolTipText");
     textWidget->setProperty("Static", "true");
     textWidget->setProperty("MultiLine", "true");
+    textWidget->setProperty("WordWrap", "true");
     textWidget->setCaption(realText);
     textWidget->setTextAlign(Align::HCenter);
 
@@ -414,13 +418,14 @@ IntSize ToolTips::createToolTip(const std::string& caption, const std::string& t
 {
     // remove the first newline (easier this way)
     std::string realText = text;
-    if (realText.size() > 0)
+    if (realText.size() > 0 && realText[0] == '\n')
         realText.erase(0, 1);
 
     EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("NormalText", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
     box->setTextAlign(Align::HCenter);
     box->setProperty("Static", "true");
     box->setProperty("MultiLine", "true");
+    box->setProperty("WordWrap", "true");
     box->setCaption(caption + (realText != "" ? "\n#BF9959" + realText : ""));
 
     mDynamicToolTipBox->setVisible(caption != "");
@@ -428,6 +433,20 @@ IntSize ToolTips::createToolTip(const std::string& caption, const std::string& t
     return box->getTextSize();
 }
 
+IntSize ToolTips::createToolTip(const std::string& text)
+{
+    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
+    box->setTextAlign(Align::HCenter);
+    box->setProperty("Static", "true");
+    box->setProperty("MultiLine", "true");
+    box->setProperty("WordWrap", "true");
+    box->setCaption(text);
+
+    mDynamicToolTipBox->setVisible(text != "");
+
+    return box->getTextSize();
+}
+
 std::string ToolTips::toString(const float value)
 {
     std::ostringstream stream;
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index cb1af7349..7a2dded11 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -21,12 +21,7 @@ namespace MWGui
 
         void setFocusObject(const MWWorld::Ptr& focus);
 
-        void adjustScreen(int screenWidth, int screenHeight);
-
     private:
-        MyGUI::EditBox* mTextToolTip;
-        MyGUI::Widget* mTextToolTipBox;
-
         MyGUI::Widget* mDynamicToolTipBox;
 
         WindowManager* mWindowManager;
@@ -44,6 +39,9 @@ namespace MWGui
         MyGUI::IntSize createToolTip(const std::string& caption, const std::string& text);
         ///< @return requested tooltip size
 
+        MyGUI::IntSize createToolTip(const std::string& text);
+        ///< @return requested tooltip size
+
         std::string getValueString(const int value);
         ///< get "Value: X" string or "" if value is 0
 
diff --git a/files/mygui/openmw_tooltips.xml b/files/mygui/openmw_tooltips.xml
index 1d55bd12f..2d5a5da9f 100644
--- a/files/mygui/openmw_tooltips.xml
+++ b/files/mygui/openmw_tooltips.xml
@@ -3,16 +3,6 @@
 <MyGUI type="Layout">
     <Widget type="Widget" layer="Popup" position="0 0 300 300" name="_Main">
 
-        <!-- Simple text-only tooltip -->
-        <Widget type="Widget" skin="HUD_Box" position="0 0 300 300" align="Stretch" name="TextToolTipBox">
-            <Property key="Visible" value="false"/>
-            <Widget type="EditBox" skin="NormalText" position="0 0 300 300" align="Stretch" name="TextToolTip">
-                <Property key="WordWrap" value="true"/>
-                <Property key="Static" value="true"/>
-                <Property key="TextAlign" value="Left Top"/>
-            </Widget>
-        </Widget>
-
         <!-- Dynamically constructed tooltip goes here -->
         <Widget type="Widget" skin="HUD_Box" position="0 0 300 300" align="Stretch" name="DynamicToolTipBox">
             <Property key="Visible" value="false"/>

From f5ab127a39dd06a3b94ae5a9b839f255069f1b0c Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 15:00:44 +0200
Subject: [PATCH 07/44] toggleFullHelp

---
 apps/openmw/mwgui/tooltips.cpp         | 114 ++++++++++++++++++++-----
 apps/openmw/mwgui/tooltips.hpp         |   6 +-
 apps/openmw/mwgui/window_manager.cpp   |   5 ++
 apps/openmw/mwgui/window_manager.hpp   |   1 +
 apps/openmw/mwscript/docs/vmformat.txt |   3 +-
 apps/openmw/mwscript/guiextensions.cpp |  21 ++++-
 6 files changed, 128 insertions(+), 22 deletions(-)

diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index 4dcb1cda7..25361ffcc 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -10,6 +10,7 @@ ToolTips::ToolTips(WindowManager* windowManager) :
     Layout("openmw_tooltips.xml")
     , mGameMode(true)
     , mWindowManager(windowManager)
+    , mFullHelp(false)
 {
     getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
 
@@ -67,7 +68,9 @@ void ToolTips::onFrame(float frameDuration)
         {
             std::string caption = focus->getUserString("ToolTipCaption");
             std::string image = focus->getUserString("ToolTipImage");
-            tooltipSize = createImageToolTip(caption, image, text);
+            std::string sizeString = focus->getUserString("ToolTipImageSize");
+            int size = (sizeString != "" ? boost::lexical_cast<int>(sizeString) : 32);
+            tooltipSize = createImageToolTip(caption, image, size, text);
         }
 
         IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
@@ -179,6 +182,11 @@ IntSize ToolTips::getToolTipViaPtr ()
         if (ref->ref.trap != "")
             text += "\n" + mWindowManager->getGameSettingString("sTrapped", "Trapped!");
 
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
         tooltipSize = createToolTip(ref->base->name, text);
     }
 
@@ -192,7 +200,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Apparatus -------------------------------
@@ -205,7 +218,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Armor -------------------------------
@@ -222,7 +240,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Book -------------------------------
@@ -234,7 +257,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Clothing -------------------------------
@@ -247,7 +275,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Ingredient -------------------------------
@@ -260,7 +293,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Light -------------------------------
@@ -272,7 +310,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Tool -------------------------------
@@ -286,7 +329,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Miscellaneous -------------------------------
@@ -298,7 +346,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Probe -------------------------------
@@ -312,7 +365,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Repair -------------------------------
@@ -326,7 +384,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Weapon -------------------------------
@@ -340,7 +403,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
         text += getValueString(ref->base->data.value);
 
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, text);
+        if (mFullHelp) {
+            text += "\n Owner: " + ref->ref.owner;
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
     }
 
     // --------------------  Activator -------------------------------
@@ -348,7 +416,12 @@ IntSize ToolTips::getToolTipViaPtr ()
     {
         ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData>* ref = mFocusObject.get<ESM::Activator>();
 
-        tooltipSize = createToolTip(ref->base->name, "");
+        std::string text;
+        if (mFullHelp) {
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createToolTip(ref->base->name, text);
     }
 
     else
@@ -374,7 +447,7 @@ void ToolTips::findImageExtension(std::string& image)
     }
 }
 
-IntSize ToolTips::createImageToolTip(const std::string& caption, const std::string& image, const std::string& text)
+IntSize ToolTips::createImageToolTip(const std::string& caption, const std::string& image, const int imageSize, const std::string& text)
 {
     // remove the first newline (easier this way)
     std::string realText = text;
@@ -384,12 +457,10 @@ IntSize ToolTips::createImageToolTip(const std::string& caption, const std::stri
     std::string realImage = "icons\\" + image;
     findImageExtension(realImage);
 
-    const int imageSize = 32;
-
     EditBox* captionWidget = mDynamicToolTipBox->createWidget<EditBox>("NormalText", IntCoord(0, 0, 300, 300), Align::Left | Align::Top, "ToolTipCaption");
     captionWidget->setProperty("Static", "true");
     captionWidget->setCaption(caption);
-    EditBox* textWidget = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, imageSize, 300, 262), Align::Stretch, "ToolTipText");
+    EditBox* textWidget = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, imageSize, 300, 300-imageSize), Align::Stretch, "ToolTipText");
     textWidget->setProperty("Static", "true");
     textWidget->setProperty("MultiLine", "true");
     textWidget->setProperty("WordWrap", "true");
@@ -407,7 +478,7 @@ IntSize ToolTips::createImageToolTip(const std::string& caption, const std::stri
         Align::Left | Align::Top, "ToolTipImage");
     imageWidget->setImageTexture(realImage);
 
-    captionWidget->setCoord( (totalSize.width - captionSize.width)/2 + imageSize, (32-captionSize.height)/2, captionSize.width-imageSize, captionSize.height);
+    captionWidget->setCoord( (totalSize.width - captionSize.width)/2 + imageSize, (imageSize-captionSize.height)/2, captionSize.width-imageSize, captionSize.height);
 
     mDynamicToolTipBox->setVisible(caption != "");
 
@@ -468,3 +539,8 @@ std::string ToolTips::getValueString(const int value)
     else
         return "\n" + mWindowManager->getGameSettingString("sValue", "Value") + ": " + toString(value);
 }
+
+void ToolTips::toggleFullHelp()
+{
+    mFullHelp = !mFullHelp;
+}
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index 7a2dded11..f546f3976 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -19,6 +19,8 @@ namespace MWGui
         void enterGameMode();
         void enterGuiMode();
 
+        void toggleFullHelp(); ///< show extra info in item tooltips (owner, script)
+
         void setFocusObject(const MWWorld::Ptr& focus);
 
     private:
@@ -33,7 +35,7 @@ namespace MWGui
         MyGUI::IntSize getToolTipViaPtr ();
         ///< @return requested tooltip size
 
-        MyGUI::IntSize createImageToolTip(const std::string& caption, const std::string& image, const std::string& text);
+        MyGUI::IntSize createImageToolTip(const std::string& caption, const std::string& image, const int imageSize, const std::string& text);
         ///< @return requested tooltip size
 
         MyGUI::IntSize createToolTip(const std::string& caption, const std::string& text);
@@ -49,6 +51,8 @@ namespace MWGui
         std::string toString(const int value);
 
         bool mGameMode;
+
+        bool mFullHelp;
     };
 }
 #endif
diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp
index 8ed2050cc..b18ee4e43 100644
--- a/apps/openmw/mwgui/window_manager.cpp
+++ b/apps/openmw/mwgui/window_manager.cpp
@@ -497,3 +497,8 @@ void WindowManager::setFocusObject(const MWWorld::Ptr& focus)
 {
     mToolTips->setFocusObject(focus);
 }
+
+void WindowManager::toggleFullHelp()
+{
+    mToolTips->toggleFullHelp();
+}
diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp
index d5f0683b8..d76d15dd4 100644
--- a/apps/openmw/mwgui/window_manager.hpp
+++ b/apps/openmw/mwgui/window_manager.hpp
@@ -161,6 +161,7 @@ namespace MWGui
     void setFocusObject(const MWWorld::Ptr& focus);
 
     void toggleFogOfWar();
+    void toggleFullHelp(); ///< show extra info in item tooltips (owner, script)
 
     int toggleFps();
     ///< toggle fps display @return resulting fps level
diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt
index 58960aac4..378b2412a 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 0x2000151: ToggleFullHelp
+opcodes 0x2000152-0x3ffffff unused
diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp
index 426378efc..f7be161d6 100644
--- a/apps/openmw/mwscript/guiextensions.cpp
+++ b/apps/openmw/mwscript/guiextensions.cpp
@@ -80,6 +80,19 @@ namespace MWScript
                 }
         };
 
+        class OpToggleFullHelp : public Interpreter::Opcode0
+        {
+            public:
+
+                virtual void execute (Interpreter::Runtime& runtime)
+                {
+                    InterpreterContext& context =
+                        static_cast<InterpreterContext&> (runtime.getContext());
+
+                    context.getEnvironment().mWindowManager->toggleFullHelp();
+                }
+        };
+
         const int opcodeEnableBirthMenu = 0x200000e;
         const int opcodeEnableClassMenu = 0x200000f;
         const int opcodeEnableNameMenu = 0x2000010;
@@ -93,6 +106,7 @@ namespace MWScript
         const int opcodeShowRestMenu = 0x2000018;
         const int opcodeGetButtonPressed = 0x2000137;
         const int opcodeToggleFogOfWar = 0x2000145;
+        const int opcodeToggleFullHelp = 0x2000151;
 
         void registerExtensions (Compiler::Extensions& extensions)
         {
@@ -101,7 +115,7 @@ namespace MWScript
             extensions.registerInstruction ("enablenamemenu", "", opcodeEnableNameMenu);
             extensions.registerInstruction ("enableracemenu", "", opcodeEnableRaceMenu);
             extensions.registerInstruction ("enablestatsreviewmenu", "",
-                opcodeEnableStatsReviewMenu);
+opcodeEnableStatsReviewMenu);
 
             extensions.registerInstruction ("enableinventorymenu", "", opcodeEnableInventoryMenu);
             extensions.registerInstruction ("enablemagicmenu", "", opcodeEnableMagicMenu);
@@ -117,6 +131,9 @@ namespace MWScript
 
             extensions.registerInstruction ("togglefogofwar", "", opcodeToggleFogOfWar);
             extensions.registerInstruction ("tfow", "", opcodeToggleFogOfWar);
+
+            extensions.registerInstruction ("togglefullhelp", "", opcodeToggleFullHelp);
+            extensions.registerInstruction ("tfh", "", opcodeToggleFullHelp);
         }
 
         void installOpcodes (Interpreter::Interpreter& interpreter)
@@ -154,6 +171,8 @@ namespace MWScript
             interpreter.installSegment5 (opcodeGetButtonPressed, new OpGetButtonPressed);
 
             interpreter.installSegment5 (opcodeToggleFogOfWar, new OpToggleFogOfWar);
+
+            interpreter.installSegment5 (opcodeToggleFullHelp, new OpToggleFullHelp);
         }
     }
 }

From b3dc1931a947b03a0895bb854eff3fd4d4e5fb25 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 15:48:01 +0200
Subject: [PATCH 08/44] general GUI refactoring, part 1

---
 apps/openmw/mwgui/review.cpp       | 37 ++++++++++-------------
 apps/openmw/mwgui/review.hpp       |  9 +-----
 apps/openmw/mwgui/stats_window.cpp | 47 +++++++++++++-----------------
 apps/openmw/mwgui/stats_window.hpp |  9 +-----
 files/mygui/openmw_button.skin.xml | 10 +++----
 files/mygui/openmw_edit.skin.xml   |  4 +--
 files/mygui/openmw_list.skin.xml   | 10 +++----
 libs/openengine/gui/layout.hpp     | 14 +++++++++
 8 files changed, 64 insertions(+), 76 deletions(-)

diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp
index cb0d9969c..dbd832580 100644
--- a/apps/openmw/mwgui/review.cpp
+++ b/apps/openmw/mwgui/review.cpp
@@ -28,21 +28,25 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
     getWidget(nameWidget, "NameText");
     getWidget(button, "NameButton");
     button->setCaption(mWindowManager.getGameSettingString("sName", ""));
+    adjustButtonSize(button);
     button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onNameClicked);;
 
     getWidget(raceWidget, "RaceText");
     getWidget(button, "RaceButton");
     button->setCaption(mWindowManager.getGameSettingString("sRace", ""));
+    adjustButtonSize(button);
     button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onRaceClicked);;
 
     getWidget(classWidget, "ClassText");
     getWidget(button, "ClassButton");
     button->setCaption(mWindowManager.getGameSettingString("sClass", ""));
+    adjustButtonSize(button);
     button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onClassClicked);;
 
     getWidget(birthSignWidget, "SignText");
     getWidget(button, "SignButton");
     button->setCaption(mWindowManager.getGameSettingString("sBirthSign", ""));
+    adjustButtonSize(button);
     button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBirthSignClicked);;
 
     // Setup dynamic stats
@@ -181,13 +185,14 @@ void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanic
     {
         float modified = value.getModified(), base = value.getBase();
         std::string text = boost::lexical_cast<std::string>(std::floor(modified));
-        ColorStyle style = CS_Normal;
+        std::string state = "normal";
         if (modified > base)
-            style = CS_Super;
+            state = "increased";
         else if (modified < base)
-            style = CS_Sub;
+            state = "decreased";
 
-        setStyledText(widget, style, text);
+        widget->setCaption(text);
+        widget->_setWidgetState(state);
     }
 }
 
@@ -210,17 +215,6 @@ void ReviewDialog::configureSkills(const std::vector<int>& major, const std::vec
     }
 }
 
-void ReviewDialog::setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value)
-{
-    widget->setCaption(value);
-    if (style == CS_Super)
-        widget->setTextColour(MyGUI::Colour(0, 1, 0));
-    else if (style == CS_Sub)
-        widget->setTextColour(MyGUI::Colour(1, 0, 0));
-    else
-        widget->setTextColour(MyGUI::Colour(1, 1, 1));
-}
-
 void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
 {
     MyGUI::ImageBox* separator = skillClientWidget->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default);
@@ -240,7 +234,7 @@ void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, M
     coord2.top += lineHeight;
 }
 
-MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
+MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
 {
     MyGUI::TextBox* skillNameWidget;
     MyGUI::TextBox* skillValueWidget;
@@ -249,7 +243,8 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::st
     skillNameWidget->setCaption(text);
 
     skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Default);
-    setStyledText(skillValueWidget, style, value);
+    skillValueWidget->setCaption(value);
+    skillValueWidget->_setWidgetState(state);
 
     skillWidgets.push_back(skillNameWidget);
     skillWidgets.push_back(skillValueWidget);
@@ -295,12 +290,12 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId
         float base = stat.getBase();
         float modified = stat.getModified();
 
-        ColorStyle style = CS_Normal;
+        std::string state = "normal";
         if (modified > base)
-            style = CS_Super;
+            state = "increased";
         else if (modified < base)
-            style = CS_Sub;
-        MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), style, coord1, coord2);
+            state = "decreased";
+        MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), state, coord1, coord2);
         skillWidgetMap[skillId] = widget;
     }
 }
diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp
index 588c1b6b5..76ca5a2d7 100644
--- a/apps/openmw/mwgui/review.hpp
+++ b/apps/openmw/mwgui/review.hpp
@@ -69,17 +69,10 @@ namespace MWGui
         void onBirthSignClicked(MyGUI::Widget* _sender);
 
     private:
-        enum ColorStyle
-        {
-            CS_Sub,
-            CS_Normal,
-            CS_Super
-        };
-        void setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value);
         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);
         void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
-        MyGUI::TextBox* addValueItem(const std::string text, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
+        MyGUI::TextBox* addValueItem(const std::string text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
         void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
         void updateScroller();
         void updateSkillArea();
diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp
index cf279faf7..42194740f 100644
--- a/apps/openmw/mwgui/stats_window.cpp
+++ b/apps/openmw/mwgui/stats_window.cpp
@@ -113,17 +113,6 @@ void StatsWindow::setPlayerName(const std::string& playerName)
     static_cast<MyGUI::Window*>(mMainWidget)->setCaption(playerName);
 }
 
-void StatsWindow::setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value)
-{
-    widget->setCaption(value);
-    if (style == CS_Super)
-        widget->setTextColour(MyGUI::Colour(0, 1, 0));
-    else if (style == CS_Sub)
-        widget->setTextColour(MyGUI::Colour(1, 0, 0));
-    else
-        widget->setTextColour(MyGUI::Colour(1, 1, 1));
-}
-
 void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
 {
     static const char *ids[] =
@@ -140,12 +129,15 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>&
             valueString << value.getModified();
             setText (id, valueString.str());
 
+            MyGUI::TextBox* box;
+            getWidget(box, id);
+
             if (value.getModified()>value.getBase())
-                setTextColor (id, 0, 1, 0);
+                box->_setWidgetState("increased");
             else if (value.getModified()<value.getBase())
-                setTextColor (id, 1, 0, 0);
+                box->_setWidgetState("decreased");
             else
-                setTextColor (id, 1, 1, 1);
+                box->_setWidgetState("normal");
 
             break;
         }
@@ -195,13 +187,14 @@ void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechani
     {
         float modified = value.getModified(), base = value.getBase();
         std::string text = boost::lexical_cast<std::string>(std::floor(modified));
-        ColorStyle style = CS_Normal;
+        std::string state = "normal";
         if (modified > base)
-            style = CS_Super;
+            state = "increased";
         else if (modified < base)
-            style = CS_Sub;
+            state = "decreased";
 
-        setStyledText(widget, style, text);
+        widget->setCaption(text);
+        widget->_setWidgetState(state);
     }
 }
 
@@ -253,7 +246,7 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My
     coord2.top += lineHeight;
 }
 
-MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
+MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
 {
     MyGUI::TextBox *skillNameWidget, *skillValueWidget;
 
@@ -265,7 +258,8 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st
     skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Default);
     skillValueWidget->setUserString("ToolTipType", "Text");
     skillValueWidget->setUserString("ToolTipText", tooltip);
-    setStyledText(skillValueWidget, style, value);
+    skillValueWidget->setCaption(value);
+    skillValueWidget->_setWidgetState(state);
 
     skillWidgets.push_back(skillNameWidget);
     skillWidgets.push_back(skillValueWidget);
@@ -311,12 +305,13 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId,
         float base = stat.getBase();
         float modified = stat.getModified();
 
-        ColorStyle style = CS_Normal;
+        std::string state = "normal";
         if (modified > base)
-            style = CS_Super;
+            state = "increased";
         else if (modified < base)
-            style = CS_Sub;
-        MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), "", boost::lexical_cast<std::string>(static_cast<int>(modified)), style, coord1, coord2);
+            state = "decreased";
+        MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), "",
+            boost::lexical_cast<std::string>(static_cast<int>(modified)), state, coord1, coord2);
         skillWidgetMap[skillId] = widget;
     }
 }
@@ -377,10 +372,10 @@ void StatsWindow::updateSkillArea()
 
     addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"),
                 mWindowManager.getGameSettingString("sSkillsMenuReputationHelp", ""),
-                boost::lexical_cast<std::string>(static_cast<int>(reputation)), CS_Normal, coord1, coord2);
+                boost::lexical_cast<std::string>(static_cast<int>(reputation)), "normal", coord1, coord2);
     addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"),
                 mWindowManager.getGameSettingString("sCrimeHelp", ""),
-                boost::lexical_cast<std::string>(static_cast<int>(bounty)), CS_Normal, coord1, coord2);
+                boost::lexical_cast<std::string>(static_cast<int>(bounty)), "normal", coord1, coord2);
 
     clientHeight = coord1.top;
     updateScroller();
diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp
index 075c08dd3..ecbc82894 100644
--- a/apps/openmw/mwgui/stats_window.hpp
+++ b/apps/openmw/mwgui/stats_window.hpp
@@ -43,17 +43,10 @@ namespace MWGui
             void updateSkillArea();
 
         private:
-            enum ColorStyle
-            {
-                CS_Sub,
-                CS_Normal,
-                CS_Super
-            };
-            void setStyledText(MyGUI::TextBox* widget, ColorStyle style, const std::string &value);
             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);
             void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
-            MyGUI::TextBox* addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, ColorStyle style, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
+            MyGUI::TextBox* addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
             void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
             void updateScroller();
 
diff --git a/files/mygui/openmw_button.skin.xml b/files/mygui/openmw_button.skin.xml
index 1c6893026..b88e99406 100644
--- a/files/mygui/openmw_button.skin.xml
+++ b/files/mygui/openmw_button.skin.xml
@@ -47,7 +47,6 @@
     <Skin name="MW_Button" size="136 24">
         <Property key="FontName" value = "Default"/>
         <Property key="TextAlign" value = "ALIGN_CENTER" />
-        <Property key="TextColour" value = "0.6 0.6 0.6" />
 
         <Child type="Widget" skin="BTN_Left" offset="0 4 4 16" align="ALIGN_VSTRETCH ALIGN_LEFT"/>
         <Child type="Widget" skin="BTN_Right" offset="132 4 4 16" align="ALIGN_VSTRETCH ALIGN_RIGHT"/>
@@ -59,11 +58,10 @@
         <Child type="Widget" skin="BTN_BottomRight" offset="132 20 4 4" align="ALIGN_BOTTOM ALIGN_RIGHT"/>
 
         <BasisSkin type="SimpleText" offset="4 4 128 16" align="ALIGN_STRETCH">
-            <!--State name="disable" colour="0.87 0.87 0.87"/-->
-            <!--State name="normal" colour="0 0 0"/-->
-            <State name="active" colour="FF0000"/>
-            <State name="pressed" colour="0000FF"/>
-            <State name="select" colour="00FF00"/>
+            <State name="disabled" colour="0.5 0.5 0.5" shift="0"/>
+            <State name="normal" colour="0.75 0.6 0.35" shift="0"/>
+            <State name="highlighted" colour="0.85 0.76 0.60" shift="0"/>
+            <State name="pushed" colour="1 1 1" shift="0"/>
         </BasisSkin>
    </Skin>
 </MyGUI>
diff --git a/files/mygui/openmw_edit.skin.xml b/files/mygui/openmw_edit.skin.xml
index a86317d62..02fee4b17 100644
--- a/files/mygui/openmw_edit.skin.xml
+++ b/files/mygui/openmw_edit.skin.xml
@@ -13,7 +13,7 @@
     <Skin name="MW_TextEdit" size="512 20" texture="mwgui.png">
         <Property key="FontName" value = "Default"/>
         <Property key="TextAlign" value = "ALIGN_LEFT ALIGN_VCENTER" />
-        <Property key="TextColour" value = "0.6 0.6 0.6" />
+        <Property key="TextColour" value = "0.75 0.6 0.35" />
 
         <BasisSkin type="SubSkin" offset = "0 0 512 2" align = "ALIGN_TOP ALIGN_HSTRETCH">
             <State name="normal" offset = "2 2 512 2"/>
@@ -34,7 +34,7 @@
     <Skin name="MW_TextBoxEdit" size="512 20" texture="mwgui.png">
         <Property key="FontName" value = "Default"/>
         <Property key="TextAlign" value = "ALIGN_LEFT ALIGN_TOP" />
-        <Property key="TextColour" value = "0.6 0.6 0.6" />
+        <Property key="TextColour" value = "0.75 0.6 0.35" />
 
         <BasisSkin type="SubSkin" offset = "0 0 512 2" align = "ALIGN_TOP ALIGN_HSTRETCH">
             <State name="normal" offset = "2 2 512 2"/>
diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml
index 0ac8e03ba..5ec975a1b 100644
--- a/files/mygui/openmw_list.skin.xml
+++ b/files/mygui/openmw_list.skin.xml
@@ -180,10 +180,10 @@
         <Property key="TextAlign" value = "ALIGN_LEFT ALIGN_VCENTER" />
 
         <BasisSkin type="SimpleText" offset = "2 0 1 5" align = "ALIGN_STRETCH">
-            <State name="normal" colour = "0.70 0.57 0.33"/>
-            <State name="active" colour = "0.70 0.57 0.33"/>
-            <State name="pressed" colour = "0.33 0.38 0.67"/>
-            <State name="select" colour = "0.33 0.38 0.67"/>
+            <State name="disabled" colour="0.70 0.57 0.33" shift="0"/>
+            <State name="normal" colour="0.70 0.57 0.33" shift="0"/>
+            <State name="highlighted" colour="0.85 0.76 0.60" shift="0"/>
+            <State name="pushed" colour="0.33 0.38 0.67" shift="0"/>
         </BasisSkin>
     </Skin>
 
@@ -219,7 +219,7 @@
         <Child type="Widget" skin="Default" offset = "3 3 493 509" align = "ALIGN_STRETCH" name = "Client">
         </Child>
 
-        <_BasisSkin type="MainSkin" offset = "0 0 0 0" align = "ALIGN_LEFT ALIGN_TOP"/>
+        <BasisSkin type="MainSkin" offset = "0 0 0 0" align = "ALIGN_LEFT ALIGN_TOP"/>
 
     </Skin>
 
diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp
index 05a23e8ae..b95dcc4a5 100644
--- a/libs/openengine/gui/layout.hpp
+++ b/libs/openengine/gui/layout.hpp
@@ -115,6 +115,13 @@ namespace GUI
       static_cast<MyGUI::TextBox*>(pt)->setCaption(caption);
     }
 
+    void setState(const std::string& widget, const std::string& state)
+    {
+      MyGUI::Widget* pt;
+      getWidget(pt, widget);
+      pt->_setWidgetState(state);
+    }
+
     void setTextColor(const std::string& name, float r, float g, float b)
     {
       MyGUI::Widget* pt;
@@ -131,6 +138,13 @@ namespace GUI
       pt->setImageTexture(imgName);
     }
 
+    void adjustButtonSize(MyGUI::Button* button)
+    {
+      // adjust size of button to fit its text
+      MyGUI::IntSize size = button->getTextSize();
+      button->setSize(size.width + 24, button->getSize().height);
+    }
+
   protected:
 
     MyGUI::Widget* mMainWidget;

From 14377ba789ee001503a6441cd713d08b55db0d76 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 17:30:57 +0200
Subject: [PATCH 09/44] window caption fix

---
 apps/openmw/mwgui/stats_window.cpp | 1 +
 libs/openengine/gui/layout.hpp     | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp
index 42194740f..b007fc1d4 100644
--- a/apps/openmw/mwgui/stats_window.cpp
+++ b/apps/openmw/mwgui/stats_window.cpp
@@ -111,6 +111,7 @@ void StatsWindow::setBar(const std::string& name, const std::string& tname, int
 void StatsWindow::setPlayerName(const std::string& playerName)
 {
     static_cast<MyGUI::Window*>(mMainWidget)->setCaption(playerName);
+    adjustWindowCaption();
 }
 
 void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp
index b95dcc4a5..bda8935af 100644
--- a/libs/openengine/gui/layout.hpp
+++ b/libs/openengine/gui/layout.hpp
@@ -85,7 +85,7 @@ namespace GUI
       // adjust the size of the window caption so that all text is visible
       // NOTE: this assumes that mMainWidget is of type Window.
       MyGUI::TextBox* box = static_cast<MyGUI::Window*>(mMainWidget)->getCaptionWidget();
-      box->setSize(box->getTextSize().width + 48, box->getSize().height);
+      box->setSize(box->getTextSize().width + 24, box->getSize().height);
 
       // in order to trigger alignment updates, we need to update the parent
       // mygui doesn't provide a proper way of doing this, so we are just changing size

From 424a90aa92fd766db35316b3fafe6be7342951f7 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 17:46:54 +0200
Subject: [PATCH 10/44] back & ok button caption

---
 apps/openmw/mwgui/birth.cpp  | 2 ++
 apps/openmw/mwgui/class.cpp  | 2 ++
 apps/openmw/mwgui/race.cpp   | 5 ++---
 apps/openmw/mwgui/review.cpp | 2 ++
 4 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp
index e9c15fab4..100356e28 100644
--- a/apps/openmw/mwgui/birth.cpp
+++ b/apps/openmw/mwgui/birth.cpp
@@ -28,10 +28,12 @@ BirthDialog::BirthDialog(WindowManager& parWindowManager)
     // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
+    backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
     backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
 
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
+    okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
     okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
 
     updateBirths();
diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp
index 75e534b42..791e24f2a 100644
--- a/apps/openmw/mwgui/class.cpp
+++ b/apps/openmw/mwgui/class.cpp
@@ -29,10 +29,12 @@ GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowMan
     // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
+    backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
     backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
 
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
+    okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
     okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
 }
 
diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp
index 880c0bc52..9a84f551c 100644
--- a/apps/openmw/mwgui/race.cpp
+++ b/apps/openmw/mwgui/race.cpp
@@ -72,10 +72,12 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager)
     // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
+    backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
     backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked);
 
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
+    okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
     okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked);
 
     updateRaces();
@@ -94,15 +96,12 @@ void RaceDialog::setNextButtonShow(bool shown)
     // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system.
     if (shown)
     {
-        okButton->setCaption("Next");
-
         // Adjust back button when next is shown
         backButton->setCoord(MyGUI::IntCoord(471 - 18, 397, 53, 23));
         okButton->setCoord(MyGUI::IntCoord(532 - 18, 397, 42 + 18, 23));
     }
     else
     {
-        okButton->setCaption("OK");
         backButton->setCoord(MyGUI::IntCoord(471, 397, 53, 23));
         okButton->setCoord(MyGUI::IntCoord(532, 397, 42, 23));
     }
diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp
index dbd832580..f531fe536 100644
--- a/apps/openmw/mwgui/review.cpp
+++ b/apps/openmw/mwgui/review.cpp
@@ -93,10 +93,12 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
     // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
+    backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
     backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBackClicked);
 
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
+    okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
     okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onOkClicked);
 }
 

From cfa37b0e7721ee17e98f08ee3b9588783a27271c Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 19:14:05 +0200
Subject: [PATCH 11/44] fix another bunch of gui stuff, some strings were
 untranslated and buttons were not resized to fit their text

---
 apps/openmw/mwgui/birth.cpp                   | 22 ++----
 apps/openmw/mwgui/class.cpp                   | 73 +++++++++----------
 apps/openmw/mwgui/map_window.cpp              |  8 +-
 apps/openmw/mwgui/race.cpp                    | 19 ++---
 apps/openmw/mwgui/review.cpp                  |  6 +-
 apps/openmw/mwgui/text_input.cpp              | 16 ++--
 apps/openmw/mwgui/tooltips.hpp                | 12 +++
 ...w_chargen_generate_class_result_layout.xml | 12 +--
 files/mygui/openmw_text.skin.xml              |  6 +-
 9 files changed, 92 insertions(+), 82 deletions(-)

diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp
index 100356e28..44c165743 100644
--- a/apps/openmw/mwgui/birth.cpp
+++ b/apps/openmw/mwgui/birth.cpp
@@ -25,7 +25,6 @@ BirthDialog::BirthDialog(WindowManager& parWindowManager)
     birthList->eventListMouseItemActivate += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
     birthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
     backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
@@ -48,21 +47,16 @@ void BirthDialog::setNextButtonShow(bool shown)
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
 
-    // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system.
     if (shown)
-    {
-        okButton->setCaption("Next");
-
-        // Adjust back button when next is shown
-        backButton->setCoord(MyGUI::IntCoord(375 - 18, 340, 53, 23));
-        okButton->setCoord(MyGUI::IntCoord(431 - 18, 340, 42 + 18, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sNext", ""));
     else
-    {
-        okButton->setCaption("OK");
-        backButton->setCoord(MyGUI::IntCoord(375, 340, 53, 23));
-        okButton->setCoord(MyGUI::IntCoord(431, 340, 42, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
+
+    int okButtonWidth = okButton->getTextSize().width + 24;
+    int backButtonWidth = backButton->getTextSize().width + 24;
+
+    okButton->setCoord(473 - okButtonWidth, 340, okButtonWidth, 23);
+    backButton->setCoord(473 - okButtonWidth - backButtonWidth - 6, 340, backButtonWidth, 23);
 }
 
 void BirthDialog::open()
diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp
index 791e24f2a..9f1fc5d2a 100644
--- a/apps/openmw/mwgui/class.cpp
+++ b/apps/openmw/mwgui/class.cpp
@@ -26,7 +26,6 @@ GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowMan
     getWidget(classImage, "ClassImage");
     getWidget(className, "ClassName");
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
     backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
@@ -36,6 +35,11 @@ GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowMan
     getWidget(okButton, "OKButton");
     okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
     okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
+
+    int okButtonWidth = okButton->getTextSize().width + 24;
+    int backButtonWidth = backButton->getTextSize().width + 24;
+    okButton->setCoord(315 - okButtonWidth, 219, okButtonWidth, 23);
+    backButton->setCoord(315 - okButtonWidth - backButtonWidth - 6, 219, backButtonWidth, 23);
 }
 
 void GenerateClassResultDialog::open()
@@ -104,7 +108,6 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager)
 
     getWidget(classImage, "ClassImage");
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
     backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
@@ -125,21 +128,16 @@ void PickClassDialog::setNextButtonShow(bool shown)
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
 
-    // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system.
     if (shown)
-    {
-        okButton->setCaption("Next");
-
-        // Adjust back button when next is shown
-        backButton->setCoord(MyGUI::IntCoord(382 - 18, 265, 53, 23));
-        okButton->setCoord(MyGUI::IntCoord(434 - 18, 265, 42 + 18, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sNext", ""));
     else
-    {
-        okButton->setCaption("OK");
-        backButton->setCoord(MyGUI::IntCoord(382, 265, 53, 23));
-        okButton->setCoord(MyGUI::IntCoord(434, 265, 42, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
+
+    int okButtonWidth = okButton->getTextSize().width + 24;
+    int backButtonWidth = backButton->getTextSize().width + 24;
+
+    okButton->setCoord(476 - okButtonWidth, 265, okButtonWidth, 23);
+    backButton->setCoord(476 - okButtonWidth - backButtonWidth - 6, 265, backButtonWidth, 23);
 }
 
 void PickClassDialog::open()
@@ -425,9 +423,9 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager)
     // Make sure the edit box has focus
     MyGUI::InputManager::getInstance().setKeyFocusWidget(editName);
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr descriptionButton;
     getWidget(descriptionButton, "DescriptionButton");
+    descriptionButton->setCaption(mWindowManager.getGameSettingString("sCreateClassMenu1", ""));
     descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked);
 
     MyGUI::ButtonPtr backButton;
@@ -509,32 +507,27 @@ std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMinorSkills() const
 
 void CreateClassDialog::setNextButtonShow(bool shown)
 {
-    MyGUI::ButtonPtr descriptionButton;
-    getWidget(descriptionButton, "DescriptionButton");
-
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
 
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
 
-    // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system.
-    if (shown)
-    {
-        okButton->setCaption("Next");
+    MyGUI::ButtonPtr descriptionButton;
+    getWidget(descriptionButton, "DescriptionButton");
 
-        // Adjust back button when next is shown
-        descriptionButton->setCoord(MyGUI::IntCoord(207 - 18, 158, 143, 23));
-        backButton->setCoord(MyGUI::IntCoord(356 - 18, 158, 53, 23));
-        okButton->setCoord(MyGUI::IntCoord(417 - 18, 158, 42 + 18, 23));
-    }
+    if (shown)
+        okButton->setCaption(mWindowManager.getGameSettingString("sNext", ""));
     else
-    {
-        okButton->setCaption("OK");
-        descriptionButton->setCoord(MyGUI::IntCoord(207, 158, 143, 23));
-        backButton->setCoord(MyGUI::IntCoord(356, 158, 53, 23));
-        okButton->setCoord(MyGUI::IntCoord(417, 158, 42, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
+
+    int okButtonWidth = okButton->getTextSize().width + 24;
+    int backButtonWidth = backButton->getTextSize().width + 24;
+    int descriptionButtonWidth = descriptionButton->getTextSize().width + 24;
+
+    okButton->setCoord(459 - okButtonWidth, 158, okButtonWidth, 23);
+    backButton->setCoord(459 - okButtonWidth - backButtonWidth - 6, 158, backButtonWidth, 23);
+    descriptionButton->setCoord(459 - okButtonWidth - backButtonWidth - descriptionButtonWidth - 12, 158, descriptionButtonWidth, 23);
 }
 
 void CreateClassDialog::open()
@@ -681,11 +674,12 @@ SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowM
     specialization2->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
     specializationId = ESM::Class::Combat;
 
-    // TODO: These buttons should be managed by a Dialog class
     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);
 }
 
 // widget controls
@@ -730,11 +724,12 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager)
         attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked);
     }
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr cancelButton;
     getWidget(cancelButton, "CancelButton");
     cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
     cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
+    int buttonWidth = cancelButton->getTextSize().width + 24;
+    cancelButton->setCoord(186 - buttonWidth, 180, buttonWidth, 21);
 }
 
 // widget controls
@@ -819,11 +814,12 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager)
         }
     }
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr cancelButton;
     getWidget(cancelButton, "CancelButton");
     cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
     cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
+    int buttonWidth = cancelButton->getTextSize().width + 24;
+    cancelButton->setCoord(447 - buttonWidth, 218, buttonWidth, 21);
 }
 
 // widget controls
@@ -849,11 +845,12 @@ DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager)
 
     getWidget(textEdit, "TextEdit");
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
     okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked);
     okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", ""));
+    int buttonWidth = okButton->getTextSize().width + 24;
+    okButton->setCoord(234 - buttonWidth, 214, buttonWidth, 24);
 
     // Make sure the edit box has focus
     MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit);
diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp
index 0e9d57c3c..e0c828fdc 100644
--- a/apps/openmw/mwgui/map_window.cpp
+++ b/apps/openmw/mwgui/map_window.cpp
@@ -29,6 +29,9 @@ MapWindow::MapWindow(WindowManager& parWindowManager) :
 
     getWidget(mButton, "WorldButton");
     mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
+    mButton->setCaption(mWindowManager.getGameSettingString("sWorld", ""));
+    int width = mButton->getTextSize().width + 24;
+    mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22);
 
     MyGUI::Button* eventbox;
     getWidget(eventbox, "EventBox");
@@ -97,7 +100,10 @@ void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
     mGlobalMap->setVisible(mGlobal);
     mLocalMap->setVisible(!mGlobal);
 
-    mButton->setCaption( mGlobal ? "Local" : "World" );
+    mButton->setCaption( mGlobal ? mWindowManager.getGameSettingString("sWorld", "") :
+            mWindowManager.getGameSettingString("sLocal", ""));
+    int width = mButton->getTextSize().width + 24;
+    mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22);
 }
 
 void MapWindow::onPinToggled()
diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp
index 9a84f551c..275759c9f 100644
--- a/apps/openmw/mwgui/race.cpp
+++ b/apps/openmw/mwgui/race.cpp
@@ -69,7 +69,6 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager)
     setText("SpellPowerT", mWindowManager.getGameSettingString("sRaceMenu7", "Specials"));
     getWidget(spellPowerList, "SpellPowerList");
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
     backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
@@ -93,18 +92,16 @@ void RaceDialog::setNextButtonShow(bool shown)
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
 
-    // TODO: All hardcoded coords for buttons are temporary, will be replaced with a dynamic system.
     if (shown)
-    {
-        // Adjust back button when next is shown
-        backButton->setCoord(MyGUI::IntCoord(471 - 18, 397, 53, 23));
-        okButton->setCoord(MyGUI::IntCoord(532 - 18, 397, 42 + 18, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sNext", ""));
     else
-    {
-        backButton->setCoord(MyGUI::IntCoord(471, 397, 53, 23));
-        okButton->setCoord(MyGUI::IntCoord(532, 397, 42, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
+
+    int okButtonWidth = okButton->getTextSize().width + 24;
+    int backButtonWidth = backButton->getTextSize().width + 24;
+
+    okButton->setCoord(574 - okButtonWidth, 397, okButtonWidth, 23);
+    backButton->setCoord(574 - okButtonWidth - backButtonWidth - 6, 397, backButtonWidth, 23);
 }
 
 void RaceDialog::open()
diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp
index f531fe536..7dfe514de 100644
--- a/apps/openmw/mwgui/review.cpp
+++ b/apps/openmw/mwgui/review.cpp
@@ -90,7 +90,6 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
 
     static_cast<MyGUI::WindowPtr>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ReviewDialog::onWindowResize);
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr backButton;
     getWidget(backButton, "BackButton");
     backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
@@ -100,6 +99,11 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
     getWidget(okButton, "OKButton");
     okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
     okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onOkClicked);
+
+    int backButtonWidth = backButton->getTextSize().width + 24;
+    int okButtonWidth = okButton->getTextSize().width + 24;
+    okButton->setCoord(502 - okButtonWidth, 372, okButtonWidth, 23);
+    backButton->setCoord(502 - okButtonWidth - backButtonWidth - 6, 372, backButtonWidth, 23);
 }
 
 void ReviewDialog::open()
diff --git a/apps/openmw/mwgui/text_input.cpp b/apps/openmw/mwgui/text_input.cpp
index 8ac07e766..7d84a9b9f 100644
--- a/apps/openmw/mwgui/text_input.cpp
+++ b/apps/openmw/mwgui/text_input.cpp
@@ -12,7 +12,6 @@ TextInputDialog::TextInputDialog(WindowManager& parWindowManager)
     getWidget(textEdit, "TextEdit");
     textEdit->eventEditSelectAccept += newDelegate(this, &TextInputDialog::onTextAccepted);
 
-    // TODO: These buttons should be managed by a Dialog class
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
     okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked);
@@ -25,16 +24,15 @@ void TextInputDialog::setNextButtonShow(bool shown)
 {
     MyGUI::ButtonPtr okButton;
     getWidget(okButton, "OKButton");
+
     if (shown)
-    {
-        okButton->setCaption("Next");
-        okButton->setCoord(MyGUI::IntCoord(264 - 18, 60, 42 + 18, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sNext", ""));
     else
-    {
-        okButton->setCaption("OK");
-        okButton->setCoord(MyGUI::IntCoord(264, 60, 42, 23));
-    }
+        okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
+
+    int okButtonWidth = okButton->getTextSize().width + 24;
+
+    okButton->setCoord(306 - okButtonWidth, 60, okButtonWidth, 23);
 }
 
 void TextInputDialog::setTextLabel(const std::string &label)
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index f546f3976..a3447eb44 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -9,6 +9,18 @@ namespace MWGui
 {
     class WindowManager;
 
+    // Info about tooltip that is supplied by the MWWorld::Class object
+    // Not used yet, but it will replace the if-else-if blocks in tooltips.cpp
+    struct ToolTipInfo
+    {
+    public:
+        std::string caption;
+        std::string text;
+        std::string image;
+
+        /// \todo enchantments (armor, cloth, weapons), magic effects (potions, ingredients)
+    };
+
     class ToolTips : public OEngine::GUI::Layout
     {
     public:
diff --git a/files/mygui/openmw_chargen_generate_class_result_layout.xml b/files/mygui/openmw_chargen_generate_class_result_layout.xml
index 7ec926eb0..26ebe17e1 100644
--- a/files/mygui/openmw_chargen_generate_class_result_layout.xml
+++ b/files/mygui/openmw_chargen_generate_class_result_layout.xml
@@ -1,27 +1,29 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <MyGUI type="Layout">
-    <Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 330 217" name="_Main">
+    <Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 330 256" name="_Main">
         <!-- Class image -->
         <Widget type="Widget" skin="MW_Box" position="32 10 265 138" align="ALIGN_LEFT ALIGN_TOP">
             <Widget type="ImageBox" skin="ImageBox" position="2 2 261 134" name="ClassImage" align="ALIGN_LEFT ALIGN_TOP" />
         </Widget>
 
         <!-- Class text -->
-        <Widget type="TextBox" skin="SandText" position="32 152 265 18" name="ReflectT" align="ALIGN_LEFT ALIGN_TOP">
+        <Widget type="EditBox" skin="SandText" position="32 152 265 40" name="ReflectT" align="ALIGN_LEFT ALIGN_TOP">
             <Property key="Caption" value="Your personality and past reflect a:"/>
             <Property key="TextAlign" value="ALIGN_TOP ALIGN_HCENTER"/>
+            <Property key="MultiLine" value="true"/>
+            <Property key="WordWrap" value="true"/>
         </Widget>
-        <Widget type="TextBox" skin="SandText" position="32 170 265 18" name="ClassName" align="ALIGN_LEFT ALIGN_TOP">
+        <Widget type="TextBox" skin="SandText" position="32 192 265 23" name="ClassName" align="ALIGN_LEFT ALIGN_TOP">
             <Property key="Caption" value="[Class]"/>
             <Property key="TextAlign" value="ALIGN_TOP ALIGN_HCENTER"/>
         </Widget>
 
         <!-- Dialog buttons -->
-        <Widget type="Button" skin="MW_Button" position="220 184 53 23" name="BackButton">
+        <Widget type="Button" skin="MW_Button" position="220 219 53 23" name="BackButton">
             <Property key="Caption" value="Back"/>
         </Widget>
-        <Widget type="Button" skin="MW_Button" position="277 184 42 23" name="OKButton">
+        <Widget type="Button" skin="MW_Button" position="277 219 42 23" name="OKButton">
             <Property key="Caption" value="OK"/>
         </Widget>
     </Widget>
diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml
index 6ae14c558..9f87c93b3 100644
--- a/files/mygui/openmw_text.skin.xml
+++ b/files/mygui/openmw_text.skin.xml
@@ -94,19 +94,19 @@
     </Skin>
 
     <Skin name = "MW_DynamicStat_Red" size = "204 18">
-        <Child type="TextBox" skin="SandText" offset = "0 0 70 18" align = "ALIGN_LEFT ALIGN_TOP" name = "Text" />
+        <Child type="TextBox" skin="SandText" offset = "0 0 100 18" align = "ALIGN_LEFT ALIGN_TOP" name = "Text" />
         <Child type="ProgressBar" skin="MW_Progress_Red" offset = "74 0 130 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "Bar" />
         <Child type="TextBox" skin="SandTextC" offset = "74 0 130 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "BarText" />
     </Skin>
 
     <Skin name = "MW_DynamicStat_Blue" size = "204 18">
-        <Child type="TextBox" skin="SandText" offset = "0 0 70 18" align = "ALIGN_LEFT ALIGN_TOP" name = "Text" />
+        <Child type="TextBox" skin="SandText" offset = "0 0 100 18" align = "ALIGN_LEFT ALIGN_TOP" name = "Text" />
         <Child type="ProgressBar" skin="MW_Progress_Blue" offset = "74 0 130 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "Bar" />
         <Child type="TextBox" skin="SandTextC" offset = "74 0 130 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "BarText" />
     </Skin>
 
     <Skin name = "MW_DynamicStat_Green" size = "204 18">
-        <Child type="TextBox" skin="SandText" offset = "0 0 70 18" align = "ALIGN_LEFT ALIGN_TOP" name = "Text" />
+        <Child type="TextBox" skin="SandText" offset = "0 0 100 18" align = "ALIGN_LEFT ALIGN_TOP" name = "Text" />
         <Child type="ProgressBar" skin="MW_Progress_Green" offset = "74 0 130 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "Bar" />
         <Child type="TextBox" skin="SandTextC" offset = "74 0 130 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "BarText" />
     </Skin>

From f1b80c6ff7441f7e1b91d6e3c1b166c275dbdedc Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 19:23:24 +0200
Subject: [PATCH 12/44] fixed text input box

---
 files/mygui/openmw_text_input_layout.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/files/mygui/openmw_text_input_layout.xml b/files/mygui/openmw_text_input_layout.xml
index 6a7ad27f0..c8f76b257 100644
--- a/files/mygui/openmw_text_input_layout.xml
+++ b/files/mygui/openmw_text_input_layout.xml
@@ -4,10 +4,10 @@
     <Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 320 97" name="_Main">
 
         <!-- Appearance -->
-        <Widget type="TextBox" skin="ProgressText" position="10 12 300 18" name="LabelT" align="ALIGN_LEFT ALIGN_TOP">
+        <Widget type="TextBox" skin="ProgressText" position="6 6 300 18" name="LabelT" align="ALIGN_LEFT ALIGN_TOP">
             <Property key="TextAlign" value="ALIGN_LEFT ALIGN_TOP"/>
         </Widget>
-        <Widget type="EditBox" skin="MW_TextEdit" position="10 28 300 30" name="TextEdit" align="ALIGN_LEFT ALIGN_TOP"/>
+        <Widget type="EditBox" skin="MW_TextEdit" position="6 28 300 30" name="TextEdit" align="ALIGN_LEFT ALIGN_TOP"/>
 
         <!-- Dialog buttons -->
         <Widget type="Button" skin="MW_Button" position="264 60 42 23" name="OKButton">

From 53b48196f953c388546899d4f209a92809e324db Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 19:30:52 +0200
Subject: [PATCH 13/44] add interface for tooltips to MWWorld::Class

---
 apps/openmw/mwworld/class.cpp | 10 ++++++++++
 apps/openmw/mwworld/class.hpp |  7 +++++++
 2 files changed, 17 insertions(+)

diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp
index d49b98d0f..c886f2348 100644
--- a/apps/openmw/mwworld/class.cpp
+++ b/apps/openmw/mwworld/class.cpp
@@ -173,4 +173,14 @@ namespace MWWorld
     {
         throw std::runtime_error ("class does not have an down sound");
     }
+
+    MWGui::ToolTipInfo Class::getToolTipInfo (const Ptr& ptr)
+    {
+        throw std::runtime_error ("class does not have a tool tip");
+    }
+
+    bool Class::hasToolTip (const Ptr& ptr)
+    {
+        return false;
+    }
 }
diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp
index e474e9b92..5441b874d 100644
--- a/apps/openmw/mwworld/class.hpp
+++ b/apps/openmw/mwworld/class.hpp
@@ -12,6 +12,7 @@
 #include "physicssystem.hpp"
 
 #include "../mwrender/renderinginterface.hpp"
+#include "../mwgui/tooltips.hpp"
 
 namespace Ogre
 {
@@ -86,6 +87,12 @@ namespace MWWorld
             ///< Return creature stats or throw an exception, if class does not have creature stats
             /// (default implementation: throw an exceoption)
 
+            virtual bool hasToolTip (const Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const Ptr& ptr) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual MWMechanics::NpcStats& getNpcStats (const Ptr& ptr) const;
             ///< Return NPC stats or throw an exception, if class does not have NPC stats
             /// (default implementation: throw an exceoption)

From 282f37b1b71e04ad51cddc35ac924d2435bd6265 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 19:34:46 +0200
Subject: [PATCH 14/44] fix compilation

---
 apps/openmw/mwworld/class.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp
index c886f2348..10368901b 100644
--- a/apps/openmw/mwworld/class.cpp
+++ b/apps/openmw/mwworld/class.cpp
@@ -174,12 +174,12 @@ namespace MWWorld
         throw std::runtime_error ("class does not have an down sound");
     }
 
-    MWGui::ToolTipInfo Class::getToolTipInfo (const Ptr& ptr)
+    MWGui::ToolTipInfo Class::getToolTipInfo (const Ptr& ptr) const
     {
         throw std::runtime_error ("class does not have a tool tip");
     }
 
-    bool Class::hasToolTip (const Ptr& ptr)
+    bool Class::hasToolTip (const Ptr& ptr) const
     {
         return false;
     }

From c4825cdb4300391cb84963abdc63c3e9f35df9fb Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 20:20:18 +0200
Subject: [PATCH 15/44] fixed gold pickup sound for international MW versions,
 fix npc tooltip

---
 apps/openmw/mwclass/misc.cpp   |  5 +++--
 apps/openmw/mwgui/tooltips.cpp | 14 ++++++++++++--
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp
index 84099caaa..596344042 100644
--- a/apps/openmw/mwclass/misc.cpp
+++ b/apps/openmw/mwclass/misc.cpp
@@ -7,6 +7,7 @@
 
 #include "../mwworld/ptr.hpp"
 #include "../mwworld/actiontake.hpp"
+#include "../mwworld/world.hpp"
 #include "../mwworld/environment.hpp"
 
 #include "../mwrender/objects.hpp"
@@ -90,7 +91,7 @@ namespace MWClass
         ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
             ptr.get<ESM::Miscellaneous>();
 
-        if (ref->base->name =="Gold")
+        if (ref->base->name == environment.mWorld->getStore().gameSettings.search("sGold")->str)
         {
             return std::string("Item Gold Up");
         }
@@ -102,7 +103,7 @@ namespace MWClass
         ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
             ptr.get<ESM::Miscellaneous>();
 
-        if (ref->base->name =="Gold")
+        if (ref->base->name == environment.mWorld->getStore().gameSettings.search("sGold")->str)
         {
             return std::string("Item Gold Down");
         }
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index 25361ffcc..ce3174168 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -158,7 +158,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         /// \todo We don't want tooltips for NPCs in combat mode.
         ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mFocusObject.get<ESM::NPC>();
 
-        tooltipSize = createToolTip(ref->base->name, "");
+        std::string text;
+        if (mFullHelp) {
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createToolTip(ref->base->name, text);
     }
 
     // --------------------  Creature -------------------------------
@@ -167,7 +172,12 @@ IntSize ToolTips::getToolTipViaPtr ()
         /// \todo We don't want tooltips for Creatures in combat mode.
         ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mFocusObject.get<ESM::Creature>();
 
-        tooltipSize = createToolTip(ref->base->name, "");
+        std::string text;
+        if (mFullHelp) {
+            text += "\n Script: " + ref->base->script;
+        }
+
+        tooltipSize = createToolTip(ref->base->name, text);
     }
 
     // --------------------  Container -------------------------------

From 13b67faf2f38c3692db617c4d31d6f1c33ed3d74 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 20:39:41 +0200
Subject: [PATCH 16/44] adding more safety checks

---
 apps/openmw/mwrender/renderingmanager.cpp | 5 +++--
 files/settings-default.cfg                | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index c1462807f..a35560848 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -54,9 +54,10 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
 
     // disable unsupported effects
     const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
-    if (caps->getNumMultiRenderTargets() < 2)
+    if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects"))
         Settings::Manager::setBool("shader", "Water", false);
-    if (!caps->isShaderProfileSupported("fp40") && !caps->isShaderProfileSupported("ps_4_0"))
+    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
diff --git a/files/settings-default.cfg b/files/settings-default.cfg
index 553a82e49..e4a0c020a 100644
--- a/files/settings-default.cfg
+++ b/files/settings-default.cfg
@@ -86,6 +86,7 @@ num lights = 8
 
 [Water]
 # Enable this to get fancy-looking water with reflections and refractions
+# Only available if object shaders are on
 # All the settings below have no effect if this is false
 shader = true
 

From cdd4d83d9e4a73ba10e83ee3ae93662783f39056 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 16 Apr 2012 22:58:16 +0200
Subject: [PATCH 17/44] moved the tooltip info to the appropriate
 MWWorld::Class classes

---
 apps/openmw/mwclass/activator.cpp    |  27 ++-
 apps/openmw/mwclass/activator.hpp    |   6 +
 apps/openmw/mwclass/apparatus.cpp    |  35 +++
 apps/openmw/mwclass/apparatus.hpp    |   6 +
 apps/openmw/mwclass/armor.cpp        |  49 ++++
 apps/openmw/mwclass/armor.hpp        |   6 +
 apps/openmw/mwclass/book.cpp         |  35 +++
 apps/openmw/mwclass/book.hpp         |   6 +
 apps/openmw/mwclass/clothing.cpp     |  36 +++
 apps/openmw/mwclass/clothing.hpp     |   6 +
 apps/openmw/mwclass/container.cpp    |  36 +++
 apps/openmw/mwclass/container.hpp    |   6 +
 apps/openmw/mwclass/creature.cpp     |  25 ++
 apps/openmw/mwclass/creature.hpp     |   6 +
 apps/openmw/mwclass/door.cpp         |  42 ++++
 apps/openmw/mwclass/door.hpp         |   6 +
 apps/openmw/mwclass/ingredient.cpp   |  36 +++
 apps/openmw/mwclass/ingredient.hpp   |   6 +
 apps/openmw/mwclass/light.cpp        |  36 +++
 apps/openmw/mwclass/light.hpp        |   6 +
 apps/openmw/mwclass/lockpick.cpp     |  39 +++
 apps/openmw/mwclass/lockpick.hpp     |   6 +
 apps/openmw/mwclass/misc.cpp         |  42 ++++
 apps/openmw/mwclass/misc.hpp         |   6 +
 apps/openmw/mwclass/npc.cpp          |  25 ++
 apps/openmw/mwclass/npc.hpp          |   6 +
 apps/openmw/mwclass/potion.cpp       |  36 +++
 apps/openmw/mwclass/potion.hpp       |   6 +
 apps/openmw/mwclass/probe.cpp        |  39 +++
 apps/openmw/mwclass/probe.hpp        |   6 +
 apps/openmw/mwclass/repair.cpp       |  39 +++
 apps/openmw/mwclass/repair.hpp       |   6 +
 apps/openmw/mwclass/weapon.cpp       |  41 ++++
 apps/openmw/mwclass/weapon.hpp       |   6 +
 apps/openmw/mwgui/tooltips.cpp       | 343 +++------------------------
 apps/openmw/mwgui/tooltips.hpp       |  19 +-
 apps/openmw/mwgui/window_manager.cpp |   5 +
 apps/openmw/mwgui/window_manager.hpp |   1 +
 apps/openmw/mwworld/class.cpp        |   2 +-
 apps/openmw/mwworld/class.hpp        |   2 +-
 40 files changed, 769 insertions(+), 323 deletions(-)

diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp
index 6749a2bfd..1f6badce9 100644
--- a/apps/openmw/mwclass/activator.cpp
+++ b/apps/openmw/mwclass/activator.cpp
@@ -7,7 +7,8 @@
 #include <components/esm_store/cell_store.hpp>
 
 #include "../mwworld/ptr.hpp"
-
+#include "../mwworld/environment.hpp"
+#include "../mwgui/window_manager.hpp"
 
 namespace MWClass
 {
@@ -63,4 +64,28 @@ namespace MWClass
 
         registerClass (typeid (ESM::Activator).name(), instance);
     }
+
+    bool Activator::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
+            ptr.get<ESM::Activator>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Activator::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
+            ptr.get<ESM::Activator>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+
+        std::string text;
+        if (environment.mWindowManager->getFullHelp())
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp
index 08be8a5ff..e5d826e58 100644
--- a/apps/openmw/mwclass/activator.hpp
+++ b/apps/openmw/mwclass/activator.hpp
@@ -18,6 +18,12 @@ namespace MWClass
             ///< \return name (the one that is to be presented to the user; not the internal one);
             /// can return an empty string.
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual std::string getScript (const MWWorld::Ptr& ptr) const;
             ///< Return name of the script attached to ptr
 
diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp
index 90db40b5a..16e5d8f6e 100644
--- a/apps/openmw/mwclass/apparatus.cpp
+++ b/apps/openmw/mwclass/apparatus.cpp
@@ -8,9 +8,13 @@
 #include "../mwworld/ptr.hpp"
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
+#include "../mwworld/world.hpp"
 
 #include "../mwrender/objects.hpp"
 
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
+
 #include "../mwsound/soundmanager.hpp"
 
 namespace MWClass
@@ -94,4 +98,35 @@ namespace MWClass
     {
         return std::string("Item Apparatus Down");
     }
+
+    bool Apparatus::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
+            ptr.get<ESM::Apparatus>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Apparatus::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
+            ptr.get<ESM::Apparatus>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sQuality")->str + ": " + MWGui::ToolTips::toString(ref->base->data.quality);
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp
index 861610f6c..d942ac0cb 100644
--- a/apps/openmw/mwclass/apparatus.hpp
+++ b/apps/openmw/mwclass/apparatus.hpp
@@ -28,6 +28,12 @@ namespace MWClass
             virtual int getValue (const MWWorld::Ptr& ptr) const;
             ///< Return trade value of the object. Throws an exception, if the object can't be traded.
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             static void registerSelf();
 
             virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const;
diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp
index 8e1f81136..dd343b25d 100644
--- a/apps/openmw/mwclass/armor.cpp
+++ b/apps/openmw/mwclass/armor.cpp
@@ -16,6 +16,8 @@
 
 #include "../mwrender/objects.hpp"
 
+#include "../mwgui/window_manager.hpp"
+
 #include "../mwsound/soundmanager.hpp"
 
 namespace MWClass
@@ -196,4 +198,51 @@ namespace MWClass
         else
             return std::string("Item Armor Heavy Down");
     }
+
+    bool Armor::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
+            ptr.get<ESM::Armor>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Armor::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
+            ptr.get<ESM::Armor>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        // get armor type string (light/medium/heavy)
+        int armorType = getEquipmentSkill(ptr, environment);
+        std::string typeText;
+        if (armorType == ESM::Skill::LightArmor)
+            typeText = environment.mWorld->getStore().gameSettings.search("sLight")->str;
+        else if (armorType == ESM::Skill::MediumArmor)
+            typeText = environment.mWorld->getStore().gameSettings.search("sMedium")->str;
+        else
+            typeText = environment.mWorld->getStore().gameSettings.search("sHeavy")->str;
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sArmorRating")->str + ": " + MWGui::ToolTips::toString(ref->base->data.armor);
+
+        /// \todo store the current armor health somewhere
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sCondition")->str + ": " + MWGui::ToolTips::toString(ref->base->data.health);
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight) + " (" + typeText + ")";
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp
index de5ca3983..36366db73 100644
--- a/apps/openmw/mwclass/armor.hpp
+++ b/apps/openmw/mwclass/armor.hpp
@@ -40,6 +40,12 @@ namespace MWClass
             /// Return the index of the skill this item corresponds to when equiopped or -1, if there is
             /// no such skill.
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual int getValue (const MWWorld::Ptr& ptr) const;
             ///< Return trade value of the object. Throws an exception, if the object can't be traded.
 
diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp
index 9069d9476..f60f87936 100644
--- a/apps/openmw/mwclass/book.cpp
+++ b/apps/openmw/mwclass/book.cpp
@@ -8,9 +8,12 @@
 #include "../mwworld/ptr.hpp"
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
+#include "../mwworld/world.hpp"
 
 #include "../mwrender/objects.hpp"
 
+#include "../mwgui/window_manager.hpp"
+
 #include "../mwsound/soundmanager.hpp"
 
 namespace MWClass
@@ -96,4 +99,36 @@ namespace MWClass
     {
         return std::string("Item Book Down");
     }
+
+    bool Book::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
+            ptr.get<ESM::Book>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Book::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
+            ptr.get<ESM::Book>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp
index 4738187cd..8ed99db91 100644
--- a/apps/openmw/mwclass/book.hpp
+++ b/apps/openmw/mwclass/book.hpp
@@ -25,6 +25,12 @@ namespace MWClass
             virtual std::string getScript (const MWWorld::Ptr& ptr) const;
             ///< Return name of the script attached to ptr
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual int getValue (const MWWorld::Ptr& ptr) const;
             ///< Return trade value of the object. Throws an exception, if the object can't be traded.
 
diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp
index 672a2b60a..6835ad2ed 100644
--- a/apps/openmw/mwclass/clothing.cpp
+++ b/apps/openmw/mwclass/clothing.cpp
@@ -9,6 +9,10 @@
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
 #include "../mwworld/inventorystore.hpp"
+#include "../mwworld/world.hpp"
+
+#include "../mwgui/tooltips.hpp"
+#include "../mwgui/window_manager.hpp"
 
 #include "../mwrender/objects.hpp"
 
@@ -161,4 +165,36 @@ namespace MWClass
         }
         return std::string("Item Clothes Down");
     }
+
+    bool Clothing::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
+            ptr.get<ESM::Clothing>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Clothing::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
+            ptr.get<ESM::Clothing>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp
index 97e09012d..04bab0edc 100644
--- a/apps/openmw/mwclass/clothing.hpp
+++ b/apps/openmw/mwclass/clothing.hpp
@@ -34,6 +34,12 @@ namespace MWClass
             /// Return the index of the skill this item corresponds to when equiopped or -1, if there is
             /// no such skill.
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual int getValue (const MWWorld::Ptr& ptr) const;
             ///< Return trade value of the object. Throws an exception, if the object can't be traded.
 
diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp
index 29b3331ba..23c640dc9 100644
--- a/apps/openmw/mwclass/container.cpp
+++ b/apps/openmw/mwclass/container.cpp
@@ -10,6 +10,10 @@
 #include "../mwworld/containerstore.hpp"
 #include "../mwworld/customdata.hpp"
 #include "../mwworld/environment.hpp"
+#include "../mwworld/world.hpp"
+
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
 
 #include "../mwrender/objects.hpp"
 
@@ -137,4 +141,36 @@ namespace MWClass
 
         registerClass (typeid (ESM::Container).name(), instance);
     }
+
+    bool Container::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
+            ptr.get<ESM::Container>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Container::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
+            ptr.get<ESM::Container>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+
+        std::string text;
+        if (ref->ref.lockLevel > 0)
+            text += "\n" + environment.mWorld->getStore().gameSettings.search("sLockLevel")->str + ": " + MWGui::ToolTips::toString(ref->ref.lockLevel);
+        if (ref->ref.trap != "")
+            text += "\n" + environment.mWorld->getStore().gameSettings.search("sTrapped")->str;
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp
index 387714176..3ff40c917 100644
--- a/apps/openmw/mwclass/container.hpp
+++ b/apps/openmw/mwclass/container.hpp
@@ -24,6 +24,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const;
             ///< Return container store
 
diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp
index 7270fd22b..8d5a53969 100644
--- a/apps/openmw/mwclass/creature.cpp
+++ b/apps/openmw/mwclass/creature.cpp
@@ -12,6 +12,8 @@
 #include "../mwworld/customdata.hpp"
 #include "../mwworld/containerstore.hpp"
 
+#include "../mwgui/window_manager.hpp"
+
 namespace
 {
     struct CustomData : public MWWorld::CustomData
@@ -140,4 +142,27 @@ namespace MWClass
 
         registerClass (typeid (ESM::Creature).name(), instance);
     }
+
+    bool Creature::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        /// \todo We don't want tooltips for Creatures in combat mode.
+
+        return true;
+    }
+
+    MWGui::ToolTipInfo Creature::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
+            ptr.get<ESM::Creature>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+
+        std::string text;
+        if (environment.mWindowManager->getFullHelp())
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp
index 8eb45e838..61d9267f9 100644
--- a/apps/openmw/mwclass/creature.hpp
+++ b/apps/openmw/mwclass/creature.hpp
@@ -32,6 +32,12 @@ namespace MWClass
             ///< \return name (the one that is to be presented to the user; not the internal one);
             /// can return an empty string.
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const;
             ///< Return creature stats
 
diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp
index 9d6c6a78d..e06fdecda 100644
--- a/apps/openmw/mwclass/door.cpp
+++ b/apps/openmw/mwclass/door.cpp
@@ -12,6 +12,9 @@
 #include "../mwworld/environment.hpp"
 #include "../mwworld/world.hpp"
 
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
+
 #include "../mwrender/objects.hpp"
 
 #include "../mwsound/soundmanager.hpp"
@@ -142,4 +145,43 @@ namespace MWClass
 
         registerClass (typeid (ESM::Door).name(), instance);
     }
+
+    bool Door::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
+            ptr.get<ESM::Door>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Door::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
+            ptr.get<ESM::Door>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+
+        std::string text;
+
+        /// \todo If destCell is empty, the teleport target is an exterior cell. In that case we 
+        /// need to fetch that cell (via target position) and retrieve the region name.
+        if (ref->ref.teleport && (ref->ref.destCell != ""))
+        {
+            text += "\n" + environment.mWorld->getStore().gameSettings.search("sTo")->str;
+            text += "\n"+ref->ref.destCell;
+        }
+
+        if (ref->ref.lockLevel > 0)
+            text += "\n" + environment.mWorld->getStore().gameSettings.search("sLockLevel")->str + ": " + MWGui::ToolTips::toString(ref->ref.lockLevel);
+        if (ref->ref.trap != "")
+            text += "\n" + environment.mWorld->getStore().gameSettings.search("sTrapped")->str;
+
+        if (environment.mWindowManager->getFullHelp())
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp
index aecb4224c..c7b7f5d8c 100644
--- a/apps/openmw/mwclass/door.hpp
+++ b/apps/openmw/mwclass/door.hpp
@@ -22,6 +22,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const;
             ///< Lock object
 
diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp
index 9707e79a8..a22f5c60a 100644
--- a/apps/openmw/mwclass/ingredient.cpp
+++ b/apps/openmw/mwclass/ingredient.cpp
@@ -8,6 +8,10 @@
 #include "../mwworld/ptr.hpp"
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
+#include "../mwworld/world.hpp"
+
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
 
 #include "../mwrender/objects.hpp"
 
@@ -92,4 +96,36 @@ namespace MWClass
     {
         return std::string("Item Ingredient Down");
     }
+
+    bool Ingredient::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
+            ptr.get<ESM::Ingredient>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Ingredient::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
+            ptr.get<ESM::Ingredient>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp
index 2d7717672..ba241c2f3 100644
--- a/apps/openmw/mwclass/ingredient.hpp
+++ b/apps/openmw/mwclass/ingredient.hpp
@@ -22,6 +22,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual std::string getScript (const MWWorld::Ptr& ptr) const;
             ///< Return name of the script attached to ptr
 
diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp
index f67dd4cf0..c01017aaf 100644
--- a/apps/openmw/mwclass/light.cpp
+++ b/apps/openmw/mwclass/light.cpp
@@ -10,6 +10,10 @@
 #include "../mwworld/nullaction.hpp"
 #include "../mwworld/environment.hpp"
 #include "../mwworld/inventorystore.hpp"
+#include "../mwworld/world.hpp"
+
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
 
 #include "../mwsound/soundmanager.hpp"
 
@@ -134,4 +138,36 @@ namespace MWClass
     {
         return std::string("Item Misc Down");
     }
+
+    bool Light::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
+            ptr.get<ESM::Light>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Light::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
+            ptr.get<ESM::Light>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp
index bde252c28..347e55190 100644
--- a/apps/openmw/mwclass/light.hpp
+++ b/apps/openmw/mwclass/light.hpp
@@ -23,6 +23,12 @@ namespace MWClass
             ///< \return name (the one that is to be presented to the user; not the internal one);
             /// can return an empty string.
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp
index 76bc3948f..36a097bab 100644
--- a/apps/openmw/mwclass/lockpick.cpp
+++ b/apps/openmw/mwclass/lockpick.cpp
@@ -9,6 +9,9 @@
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
 #include "../mwworld/inventorystore.hpp"
+#include "../mwworld/world.hpp"
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
 
 #include "../mwrender/objects.hpp"
 
@@ -105,4 +108,40 @@ namespace MWClass
     {
         return std::string("Item Lockpick Down");
     }
+
+    bool Lockpick::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
+            ptr.get<ESM::Tool>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Lockpick::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
+            ptr.get<ESM::Tool>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        /// \todo store remaining uses somewhere
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sUses")->str + ": " + MWGui::ToolTips::toString(ref->base->data.uses);
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sQuality")->str + ": " + MWGui::ToolTips::toString(ref->base->data.quality);
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp
index 1b56234af..8b5f658f5 100644
--- a/apps/openmw/mwclass/lockpick.hpp
+++ b/apps/openmw/mwclass/lockpick.hpp
@@ -22,6 +22,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual std::string getScript (const MWWorld::Ptr& ptr) const;
             ///< Return name of the script attached to ptr
 
diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp
index 596344042..8cd2554a1 100644
--- a/apps/openmw/mwclass/misc.cpp
+++ b/apps/openmw/mwclass/misc.cpp
@@ -10,10 +10,15 @@
 #include "../mwworld/world.hpp"
 #include "../mwworld/environment.hpp"
 
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
+
 #include "../mwrender/objects.hpp"
 
 #include "../mwsound/soundmanager.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace MWClass
 {
     void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@@ -109,4 +114,41 @@ namespace MWClass
         }
         return std::string("Item Misc Down");
     }
+
+    bool Miscellaneous::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
+            ptr.get<ESM::Miscellaneous>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Miscellaneous::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
+            ptr.get<ESM::Miscellaneous>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        if (ref->base->name == environment.mWorld->getStore().gameSettings.search("sGold")->str)
+            info.caption += " (" + boost::lexical_cast<std::string>(ref->base->data.value) + ")";
+        else
+        {
+            text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+            text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+        }
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp
index fc002280c..dda8a352e 100644
--- a/apps/openmw/mwclass/misc.hpp
+++ b/apps/openmw/mwclass/misc.hpp
@@ -22,6 +22,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual std::string getScript (const MWWorld::Ptr& ptr) const;
             ///< Return name of the script attached to ptr
 
diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp
index c053ad130..7f78d53f3 100644
--- a/apps/openmw/mwclass/npc.cpp
+++ b/apps/openmw/mwclass/npc.cpp
@@ -19,6 +19,8 @@
 #include "../mwworld/inventorystore.hpp"
 #include "../mwworld/customdata.hpp"
 
+#include "../mwgui/window_manager.hpp"
+
 namespace
 {
     const Ogre::Radian kOgrePi (Ogre::Math::PI);
@@ -299,4 +301,27 @@ namespace MWClass
         std::cout << "class npc:" << typeid (ESM::NPC).name();
         registerClass (typeid (ESM::NPC).name(), instance);
     }
+
+    bool Npc::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        /// \todo We don't want tooltips for NPCs in combat mode.
+
+        return true;
+    }
+
+    MWGui::ToolTipInfo Npc::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
+            ptr.get<ESM::NPC>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+
+        std::string text;
+        if (environment.mWindowManager->getFullHelp())
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp
index f210eda5f..46eccf26a 100644
--- a/apps/openmw/mwclass/npc.hpp
+++ b/apps/openmw/mwclass/npc.hpp
@@ -38,6 +38,12 @@ namespace MWClass
             virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const;
             ///< Return container store
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const;
             ///< Return inventory store
 
diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp
index 642211df3..2936afd19 100644
--- a/apps/openmw/mwclass/potion.cpp
+++ b/apps/openmw/mwclass/potion.cpp
@@ -8,6 +8,10 @@
 #include "../mwworld/ptr.hpp"
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
+#include "../mwworld/world.hpp"
+
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
 
 #include "../mwrender/objects.hpp"
 
@@ -94,4 +98,36 @@ namespace MWClass
     {
         return std::string("Item Potion Down");
     }
+
+    bool Potion::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
+            ptr.get<ESM::Potion>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Potion::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
+            ptr.get<ESM::Potion>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp
index 7d3017937..7b98fd897 100644
--- a/apps/openmw/mwclass/potion.hpp
+++ b/apps/openmw/mwclass/potion.hpp
@@ -22,6 +22,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual std::string getScript (const MWWorld::Ptr& ptr) const;
             ///< Return name of the script attached to ptr
 
diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp
index 923c29ee6..c70368642 100644
--- a/apps/openmw/mwclass/probe.cpp
+++ b/apps/openmw/mwclass/probe.cpp
@@ -9,6 +9,9 @@
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
 #include "../mwworld/inventorystore.hpp"
+#include "../mwworld/world.hpp"
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
 
 #include "../mwrender/objects.hpp"
 
@@ -104,4 +107,40 @@ namespace MWClass
     {
         return std::string("Item Probe Down");
     }
+
+    bool Probe::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
+            ptr.get<ESM::Probe>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Probe::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
+            ptr.get<ESM::Probe>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        /// \todo store remaining uses somewhere
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sUses")->str + ": " + MWGui::ToolTips::toString(ref->base->data.uses);
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sQuality")->str + ": " + MWGui::ToolTips::toString(ref->base->data.quality);
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp
index 232b52364..e454279a1 100644
--- a/apps/openmw/mwclass/probe.hpp
+++ b/apps/openmw/mwclass/probe.hpp
@@ -22,6 +22,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual std::string getScript (const MWWorld::Ptr& ptr) const;
             ///< Return name of the script attached to ptr
 
diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp
index d6433f5df..2befdaac9 100644
--- a/apps/openmw/mwclass/repair.cpp
+++ b/apps/openmw/mwclass/repair.cpp
@@ -8,6 +8,9 @@
 #include "../mwworld/ptr.hpp"
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
+#include "../mwworld/world.hpp"
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
 
 #include "../mwrender/objects.hpp"
 
@@ -94,4 +97,40 @@ namespace MWClass
     {
         return std::string("Item Repair Down");
     }
+
+    bool Repair::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
+            ptr.get<ESM::Repair>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Repair::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
+            ptr.get<ESM::Repair>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        /// \todo store remaining uses somewhere
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sUses")->str + ": " + MWGui::ToolTips::toString(ref->base->data.uses);
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sQuality")->str + ": " + MWGui::ToolTips::toString(ref->base->data.quality);
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp
index 0a9d9c253..2b8eba2f4 100644
--- a/apps/openmw/mwclass/repair.hpp
+++ b/apps/openmw/mwclass/repair.hpp
@@ -22,6 +22,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual std::string getScript (const MWWorld::Ptr& ptr) const;
             ///< Return name of the script attached to ptr
 
diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp
index 7790e6a80..1fb871572 100644
--- a/apps/openmw/mwclass/weapon.cpp
+++ b/apps/openmw/mwclass/weapon.cpp
@@ -9,6 +9,10 @@
 #include "../mwworld/actiontake.hpp"
 #include "../mwworld/environment.hpp"
 #include "../mwworld/inventorystore.hpp"
+#include "../mwworld/world.hpp"
+
+#include "../mwgui/window_manager.hpp"
+#include "../mwgui/tooltips.hpp"
 
 #include "../mwrender/objects.hpp"
 
@@ -245,4 +249,41 @@ namespace MWClass
 
         return std::string("Item Misc Down");
     }
+
+    bool Weapon::hasToolTip (const MWWorld::Ptr& ptr) const
+    {
+        ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
+            ptr.get<ESM::Weapon>();
+
+        return (ref->base->name != "");
+    }
+
+    MWGui::ToolTipInfo Weapon::getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
+    {
+        ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
+            ptr.get<ESM::Weapon>();
+
+        MWGui::ToolTipInfo info;
+        info.caption = ref->base->name;
+        info.icon = ref->base->icon;
+
+        std::string text;
+
+        /// \todo weapon type, damage
+
+        /// \todo store the current weapon health somewhere
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sCondition")->str + ": " + MWGui::ToolTips::toString(ref->base->data.health);
+
+        text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
+        text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
+
+        if (environment.mWindowManager->getFullHelp()) {
+            text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
+            text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
+        }
+
+        info.text = text;
+
+        return info;
+    }
 }
diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp
index 505c45645..1956ec1a9 100644
--- a/apps/openmw/mwclass/weapon.hpp
+++ b/apps/openmw/mwclass/weapon.hpp
@@ -22,6 +22,12 @@ namespace MWClass
                 const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
             ///< Generate action for activation
 
+            virtual bool hasToolTip (const MWWorld::Ptr& ptr) const;
+            ///< @return true if this object has a tooltip when focused (default implementation: false)
+
+            virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
+            ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
+
             virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const;
             ///< \return Item health data available?
 
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index ce3174168..345ed847b 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -1,6 +1,8 @@
 #include "tooltips.hpp"
 #include "window_manager.hpp"
 
+#include "../mwworld/class.hpp"
+
 #include <boost/lexical_cast.hpp>
 
 using namespace MWGui;
@@ -130,314 +132,24 @@ IntSize ToolTips::getToolTipViaPtr ()
 
     IntSize tooltipSize;
 
-    // --------------------  Door -------------------------------
-    if (mFocusObject.getTypeName() == typeid(ESM::Door).name())
+    const MWWorld::Class& object = MWWorld::Class::get (mFocusObject);
+    if (!object.hasToolTip(mFocusObject))
     {
-        ESMS::LiveCellRef<ESM::Door, MWWorld::RefData>* ref = mFocusObject.get<ESM::Door>();
-
-        std::string text;
-        /// \todo If destCell is empty, the teleport target is an exterior cell. In that case we 
-        /// need to fetch that cell (via target position) and retrieve the region name.
-        if (ref->ref.teleport && (ref->ref.destCell != ""))
-        {
-            text += "\n" + mWindowManager->getGameSettingString("sTo", "to");
-            text += "\n"+ref->ref.destCell;
-        }
-
-        if (ref->ref.lockLevel > 0)
-            text += "\n" + mWindowManager->getGameSettingString("sLockLevel", "Lock") + ": " + toString(ref->ref.lockLevel);
-        if (ref->ref.trap != "")
-            text += "\n" + mWindowManager->getGameSettingString("sTrapped", "Trapped!");
-
-        tooltipSize = createToolTip(ref->base->name, text);
+        mDynamicToolTipBox->setVisible(false);
     }
-
-    // --------------------  NPC -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::NPC).name())
-    {
-        /// \todo We don't want tooltips for NPCs in combat mode.
-        ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mFocusObject.get<ESM::NPC>();
-
-        std::string text;
-        if (mFullHelp) {
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createToolTip(ref->base->name, text);
-    }
-
-    // --------------------  Creature -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Creature).name())
-    {
-        /// \todo We don't want tooltips for Creatures in combat mode.
-        ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mFocusObject.get<ESM::Creature>();
-
-        std::string text;
-        if (mFullHelp) {
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createToolTip(ref->base->name, text);
-    }
-
-    // --------------------  Container -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Container).name())
-    {
-        ESMS::LiveCellRef<ESM::Container, MWWorld::RefData>* ref = mFocusObject.get<ESM::Container>();
-
-        std::string text;
-
-        if (ref->ref.lockLevel > 0)
-            text += "\n" + mWindowManager->getGameSettingString("sLockLevel", "Lock") + ": " + toString(ref->ref.lockLevel);
-        if (ref->ref.trap != "")
-            text += "\n" + mWindowManager->getGameSettingString("sTrapped", "Trapped!");
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createToolTip(ref->base->name, text);
-    }
-
-    // --------------------  Potion -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Potion).name())
-    {
-        ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData>* ref = mFocusObject.get<ESM::Potion>();
-
-        /// \todo magic effects
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Apparatus -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Apparatus).name())
-    {
-        ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData>* ref = mFocusObject.get<ESM::Apparatus>();
-
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sQuality", "Quality") + ": " + toString(ref->base->data.quality);
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Armor -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Armor).name())
-    {
-        ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData>* ref = mFocusObject.get<ESM::Armor>();
-
-        /// \todo magic effects, armor type (medium/light/heavy)
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sArmorRating", "Armor Rating") + ": " + toString(ref->base->data.armor);
-
-        /// \todo where is the current armor health stored?
-        //text += "\n" + mWindowManager->getGameSettingString("sCondition", "Condition") + ": " + toString(ref->base->data.health);
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Book -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Book).name())
-    {
-        ESMS::LiveCellRef<ESM::Book, MWWorld::RefData>* ref = mFocusObject.get<ESM::Book>();
-
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Clothing -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Clothing).name())
-    {
-        ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData>* ref = mFocusObject.get<ESM::Clothing>();
-
-        /// \todo magic effects
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Ingredient -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Ingredient).name())
-    {
-        ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData>* ref = mFocusObject.get<ESM::Ingredient>();
-
-        /// \todo magic effects
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Light -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Light).name())
-    {
-        ESMS::LiveCellRef<ESM::Light, MWWorld::RefData>* ref = mFocusObject.get<ESM::Light>();
-
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Tool -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Tool).name())
-    {
-        ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData>* ref = mFocusObject.get<ESM::Tool>();
-
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sUses", "Uses") + ": " + toString(ref->base->data.uses);
-        text += "\n" + mWindowManager->getGameSettingString("sQuality", "Quality") + ": " + toString(ref->base->data.quality);
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Miscellaneous -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Miscellaneous).name())
-    {
-        ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData>* ref = mFocusObject.get<ESM::Miscellaneous>();
-
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Probe -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Probe).name())
-    {
-        ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData>* ref = mFocusObject.get<ESM::Probe>();
-
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sUses", "Uses") + ": " + toString(ref->base->data.uses);
-        text += "\n" + mWindowManager->getGameSettingString("sQuality", "Quality") + ": " + toString(ref->base->data.quality);
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Repair -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Repair).name())
-    {
-        ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData>* ref = mFocusObject.get<ESM::Repair>();
-
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sUses", "Uses") + ": " + toString(ref->base->data.uses);
-        text += "\n" + mWindowManager->getGameSettingString("sQuality", "Quality") + ": " + toString(ref->base->data.quality);
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Weapon -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Weapon).name())
-    {
-        ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData>* ref = mFocusObject.get<ESM::Weapon>();
-
-        /// \todo weapon damage, magic effects, health (condition)
-
-        std::string text;
-        text += "\n" + mWindowManager->getGameSettingString("sWeight", "Weight") + ": " + toString(ref->base->data.weight);
-        text += getValueString(ref->base->data.value);
-
-        if (mFullHelp) {
-            text += "\n Owner: " + ref->ref.owner;
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createImageToolTip(ref->base->name, ref->base->icon, 32, text);
-    }
-
-    // --------------------  Activator -------------------------------
-    else if (mFocusObject.getTypeName() == typeid(ESM::Activator).name())
-    {
-        ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData>* ref = mFocusObject.get<ESM::Activator>();
-
-        std::string text;
-        if (mFullHelp) {
-            text += "\n Script: " + ref->base->script;
-        }
-
-        tooltipSize = createToolTip(ref->base->name, text);
-    }
-
     else
     {
-        // object without tooltip
-        mDynamicToolTipBox->setVisible(false);
+        mDynamicToolTipBox->setVisible(true);
+
+        ToolTipInfo info = object.getToolTipInfo(mFocusObject, mWindowManager->getEnvironment());
+        if (info.icon == "")
+        {
+            tooltipSize= createToolTip(info.caption, info.text);
+        }
+        else
+        {
+            tooltipSize = createImageToolTip(info.caption, info.icon, 32, info.text);
+        }
     }
 
     return tooltipSize;
@@ -490,8 +202,6 @@ IntSize ToolTips::createImageToolTip(const std::string& caption, const std::stri
 
     captionWidget->setCoord( (totalSize.width - captionSize.width)/2 + imageSize, (imageSize-captionSize.height)/2, captionSize.width-imageSize, captionSize.height);
 
-    mDynamicToolTipBox->setVisible(caption != "");
-
     return totalSize;
 }
 
@@ -509,8 +219,6 @@ IntSize ToolTips::createToolTip(const std::string& caption, const std::string& t
     box->setProperty("WordWrap", "true");
     box->setCaption(caption + (realText != "" ? "\n#BF9959" + realText : ""));
 
-    mDynamicToolTipBox->setVisible(caption != "");
-
     return box->getTextSize();
 }
 
@@ -523,8 +231,6 @@ IntSize ToolTips::createToolTip(const std::string& text)
     box->setProperty("WordWrap", "true");
     box->setCaption(text);
 
-    mDynamicToolTipBox->setVisible(text != "");
-
     return box->getTextSize();
 }
 
@@ -542,15 +248,28 @@ std::string ToolTips::toString(const int value)
     return stream.str();
 }
 
-std::string ToolTips::getValueString(const int value)
+std::string ToolTips::getValueString(const int value, const std::string& prefix)
 {
     if (value == 0)
         return "";
     else
-        return "\n" + mWindowManager->getGameSettingString("sValue", "Value") + ": " + toString(value);
+        return "\n" + prefix + ": " + toString(value);
+}
+
+std::string ToolTips::getMiscString(const std::string& text, const std::string& prefix)
+{
+    if (text == "")
+        return "";
+    else
+        return "\n" + prefix + ": " + text;
 }
 
 void ToolTips::toggleFullHelp()
 {
     mFullHelp = !mFullHelp;
 }
+
+bool ToolTips::getFullHelp() const
+{
+    return mFullHelp;
+}
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index a3447eb44..46aab3876 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -10,13 +10,12 @@ namespace MWGui
     class WindowManager;
 
     // Info about tooltip that is supplied by the MWWorld::Class object
-    // Not used yet, but it will replace the if-else-if blocks in tooltips.cpp
     struct ToolTipInfo
     {
     public:
         std::string caption;
         std::string text;
-        std::string image;
+        std::string icon;
 
         /// \todo enchantments (armor, cloth, weapons), magic effects (potions, ingredients)
     };
@@ -32,9 +31,19 @@ namespace MWGui
         void enterGuiMode();
 
         void toggleFullHelp(); ///< show extra info in item tooltips (owner, script)
+        bool getFullHelp() const;
 
         void setFocusObject(const MWWorld::Ptr& focus);
 
+        static std::string getValueString(const int value, const std::string& prefix);
+        ///< @return "prefix: value" or "" if value is 0
+
+        static std::string getMiscString(const std::string& text, const std::string& prefix);
+        ///< @return "prefix: text" or "" if text is empty
+
+        static std::string toString(const float value);
+        static std::string toString(const int value);
+
     private:
         MyGUI::Widget* mDynamicToolTipBox;
 
@@ -56,12 +65,6 @@ namespace MWGui
         MyGUI::IntSize createToolTip(const std::string& text);
         ///< @return requested tooltip size
 
-        std::string getValueString(const int value);
-        ///< get "Value: X" string or "" if value is 0
-
-        std::string toString(const float value);
-        std::string toString(const int value);
-
         bool mGameMode;
 
         bool mFullHelp;
diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp
index b18ee4e43..f49bcfaf8 100644
--- a/apps/openmw/mwgui/window_manager.cpp
+++ b/apps/openmw/mwgui/window_manager.cpp
@@ -502,3 +502,8 @@ void WindowManager::toggleFullHelp()
 {
     mToolTips->toggleFullHelp();
 }
+
+bool WindowManager::getFullHelp() const
+{
+    return mToolTips->getFullHelp();
+}
diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp
index d76d15dd4..1b1eff1dc 100644
--- a/apps/openmw/mwgui/window_manager.hpp
+++ b/apps/openmw/mwgui/window_manager.hpp
@@ -162,6 +162,7 @@ namespace MWGui
 
     void toggleFogOfWar();
     void toggleFullHelp(); ///< show extra info in item tooltips (owner, script)
+    bool getFullHelp() const;
 
     int toggleFps();
     ///< toggle fps display @return resulting fps level
diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp
index 10368901b..aaf19963d 100644
--- a/apps/openmw/mwworld/class.cpp
+++ b/apps/openmw/mwworld/class.cpp
@@ -174,7 +174,7 @@ namespace MWWorld
         throw std::runtime_error ("class does not have an down sound");
     }
 
-    MWGui::ToolTipInfo Class::getToolTipInfo (const Ptr& ptr) const
+    MWGui::ToolTipInfo Class::getToolTipInfo (const Ptr& ptr, MWWorld::Environment& environment) const
     {
         throw std::runtime_error ("class does not have a tool tip");
     }
diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp
index 5441b874d..1b7b8b66a 100644
--- a/apps/openmw/mwworld/class.hpp
+++ b/apps/openmw/mwworld/class.hpp
@@ -90,7 +90,7 @@ namespace MWWorld
             virtual bool hasToolTip (const Ptr& ptr) const;
             ///< @return true if this object has a tooltip when focused (default implementation: false)
 
-            virtual MWGui::ToolTipInfo getToolTipInfo (const Ptr& ptr) const;
+            virtual MWGui::ToolTipInfo getToolTipInfo (const Ptr& ptr, MWWorld::Environment& environment) const;
             ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip.
 
             virtual MWMechanics::NpcStats& getNpcStats (const Ptr& ptr) const;

From a11c4da16c3688d8a4760c7f866e8edc518614f2 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Tue, 17 Apr 2012 14:22:03 +0200
Subject: [PATCH 18/44] vertex colour tweak

---
 apps/openmw/mwrender/shaderhelper.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/apps/openmw/mwrender/shaderhelper.cpp b/apps/openmw/mwrender/shaderhelper.cpp
index 5354251f8..1d29be2b8 100644
--- a/apps/openmw/mwrender/shaderhelper.cpp
+++ b/apps/openmw/mwrender/shaderhelper.cpp
@@ -256,9 +256,9 @@ void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool s
         }
 
         outStream <<
-        "   float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
+        "   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, fogColour.xyz, fogValue); \n"
+        "   oColor.xyz = lerp(lightingFinal * tex.xyz * vertexColour.xyz, fogColour.xyz, fogValue); \n"
         "   oColor.a = tex.a * diffuse.a * vertexColour.a; \n";
 
         if (mrt) outStream <<

From c044fadcc303ad9f5621a75a21bc54770844e5df Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Tue, 17 Apr 2012 15:31:16 +0200
Subject: [PATCH 19/44] show weapon type & damage in the tooltip

---
 apps/openmw/mwclass/weapon.cpp | 53 ++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp
index 1fb871572..d2ea92126 100644
--- a/apps/openmw/mwclass/weapon.cpp
+++ b/apps/openmw/mwclass/weapon.cpp
@@ -269,10 +269,59 @@ namespace MWClass
 
         std::string text;
 
-        /// \todo weapon type, damage
+        // weapon type & damage. arrows / bolts don't have his info.
+        if (ref->base->data.type < 12)
+        {
+            text += "\n" + environment.mWorld->getStore().gameSettings.search("sType")->str + " ";
+
+            std::map <int, std::pair <std::string, std::string> > mapping;
+            mapping[ESM::Weapon::ShortBladeOneHand] = std::make_pair("sSkillShortblade", "sOneHanded");
+            mapping[ESM::Weapon::LongBladeOneHand] = std::make_pair("sSkillLongblade", "sOneHanded");
+            mapping[ESM::Weapon::LongBladeTwoHand] = std::make_pair("sSkillLongblade", "sTwoHanded");
+            mapping[ESM::Weapon::BluntOneHand] = std::make_pair("sSkillBluntweapon", "sOneHanded");
+            mapping[ESM::Weapon::BluntTwoClose] = std::make_pair("sSkillBluntweapon", "sTwoHanded");
+            mapping[ESM::Weapon::BluntTwoWide] = std::make_pair("sSkillBluntweapon", "sTwoHanded");
+            mapping[ESM::Weapon::SpearTwoWide] = std::make_pair("sSkillSpear", "sTwoHanded");
+            mapping[ESM::Weapon::AxeOneHand] = std::make_pair("sSkillAxe", "sOneHanded");
+            mapping[ESM::Weapon::AxeTwoHand] = std::make_pair("sSkillAxe", "sTwoHanded");
+            mapping[ESM::Weapon::MarksmanBow] = std::make_pair("sSkillMarksman", "");
+            mapping[ESM::Weapon::MarksmanCrossbow] = std::make_pair("sSkillMarksman", "");
+            mapping[ESM::Weapon::MarksmanThrown] = std::make_pair("sSkillMarksman", "");
+
+            std::string type = mapping[ref->base->data.type].first;
+            std::string oneOrTwoHanded = mapping[ref->base->data.type].second;
+
+            text += environment.mWorld->getStore().gameSettings.search(type)->str +
+                ((oneOrTwoHanded != "") ? ", " + environment.mWorld->getStore().gameSettings.search(oneOrTwoHanded)->str : "");
+
+            // weapon damage
+            if (ref->base->data.type >= 9)
+            {
+                // marksman
+                text += "\n" + environment.mWorld->getStore().gameSettings.search("sAttack")->str + ": "
+                    + MWGui::ToolTips::toString(static_cast<int>(ref->base->data.chop[0]))
+                    + " - " + MWGui::ToolTips::toString(static_cast<int>(ref->base->data.chop[1]));
+            }
+            else
+            {
+                // Chop
+                text += "\n" + environment.mWorld->getStore().gameSettings.search("sChop")->str + ": "
+                    + MWGui::ToolTips::toString(static_cast<int>(ref->base->data.chop[0]))
+                    + " - " + MWGui::ToolTips::toString(static_cast<int>(ref->base->data.chop[1]));
+                // Slash
+                text += "\n" + environment.mWorld->getStore().gameSettings.search("sSlash")->str + ": "
+                    + MWGui::ToolTips::toString(static_cast<int>(ref->base->data.slash[0]))
+                    + " - " + MWGui::ToolTips::toString(static_cast<int>(ref->base->data.slash[1]));
+                // Thrust
+                text += "\n" + environment.mWorld->getStore().gameSettings.search("sThrust")->str + ": "
+                    + MWGui::ToolTips::toString(static_cast<int>(ref->base->data.thrust[0]))
+                    + " - " + MWGui::ToolTips::toString(static_cast<int>(ref->base->data.thrust[1]));
+            }
+        }
 
         /// \todo store the current weapon health somewhere
-        text += "\n" + environment.mWorld->getStore().gameSettings.search("sCondition")->str + ": " + MWGui::ToolTips::toString(ref->base->data.health);
+        if (ref->base->data.type < 11) // thrown weapons and arrows/bolts don't have health, only quantity
+            text += "\n" + environment.mWorld->getStore().gameSettings.search("sCondition")->str + ": " + MWGui::ToolTips::toString(ref->base->data.health);
 
         text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
         text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);

From c2fdacc84fc5f1a3f69a9e2f1c74ff875f9d6d8b Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Tue, 17 Apr 2012 15:51:02 +0200
Subject: [PATCH 20/44] show the creature name for soul gems (if any)

---
 apps/openmw/mwclass/misc.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp
index 8cd2554a1..222ac1b78 100644
--- a/apps/openmw/mwclass/misc.cpp
+++ b/apps/openmw/mwclass/misc.cpp
@@ -132,6 +132,12 @@ namespace MWClass
         info.caption = ref->base->name;
         info.icon = ref->base->icon;
 
+        if (ref->ref.soul != "")
+        {
+            const ESM::Creature *creature = environment.mWorld->getStore().creatures.search(ref->ref.soul);
+            info.caption += " (" + creature->name + ")";
+        }
+
         std::string text;
 
         if (ref->base->name == environment.mWorld->getStore().gameSettings.search("sGold")->str)

From 8eb06363449bb638882b77ff28c0ce19901bcda0 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Tue, 17 Apr 2012 16:00:13 +0200
Subject: [PATCH 21/44] restored gui-mode tooltips

---
 apps/openmw/mwgui/tooltips.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index 345ed847b..fd44c7d9b 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -89,6 +89,7 @@ void ToolTips::onFrame(float frameDuration)
         }
 
         setCoord(tooltipPosition.left, tooltipPosition.top, size.width, size.height);
+        mDynamicToolTipBox->setVisible(true);
     }
     else
     {

From 94993b515c7abade56d4885d46ea305ea42c7947 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Tue, 17 Apr 2012 16:49:28 +0200
Subject: [PATCH 22/44] clean up and tooltip padding

---
 apps/openmw/mwgui/tooltips.cpp | 100 +++++++++++++++------------------
 apps/openmw/mwgui/tooltips.hpp |   8 +--
 2 files changed, 45 insertions(+), 63 deletions(-)

diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index fd44c7d9b..ab766dc56 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -47,9 +47,6 @@ void ToolTips::onFrame(float frameDuration)
             return;
         }
 
-        // this the maximum width of the tooltip before it starts word-wrapping
-        setCoord(0, 0, 300, 300);
-
         IntSize tooltipSize;
 
         std::string type = focus->getUserString("ToolTipType");
@@ -60,11 +57,11 @@ void ToolTips::onFrame(float frameDuration)
             return;
         }
         else if (type == "Text")
-            tooltipSize = createToolTip(text);
+            tooltipSize = createToolTip(text, "", 0, "");
         else if (type == "CaptionText")
         {
             std::string caption = focus->getUserString("ToolTipCaption");
-            tooltipSize = createToolTip(caption, text);
+            tooltipSize = createToolTip(caption, "", 0, text);
         }
         else if (type == "ImageCaptionText")
         {
@@ -72,23 +69,22 @@ void ToolTips::onFrame(float frameDuration)
             std::string image = focus->getUserString("ToolTipImage");
             std::string sizeString = focus->getUserString("ToolTipImageSize");
             int size = (sizeString != "" ? boost::lexical_cast<int>(sizeString) : 32);
-            tooltipSize = createImageToolTip(caption, image, size, text);
+            tooltipSize = createToolTip(caption, image, size, text);
         }
 
         IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
 
-        IntSize size = tooltipSize + IntSize(6, 6);
         // make the tooltip stay completely in the viewport
-        if ((tooltipPosition.left + size.width) > viewSize.width)
+        if ((tooltipPosition.left + tooltipSize.width) > viewSize.width)
         {
-            tooltipPosition.left = viewSize.width - size.width;
+            tooltipPosition.left = viewSize.width - tooltipSize.width;
         }
-        if ((tooltipPosition.top + size.height) > viewSize.height)
+        if ((tooltipPosition.top + tooltipSize.height) > viewSize.height)
         {
-            tooltipPosition.top = viewSize.height - size.height;
+            tooltipPosition.top = viewSize.height - tooltipSize.height;
         }
 
-        setCoord(tooltipPosition.left, tooltipPosition.top, size.width, size.height);
+        setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height);
         mDynamicToolTipBox->setVisible(true);
     }
     else
@@ -97,8 +93,6 @@ void ToolTips::onFrame(float frameDuration)
         {
             IntSize tooltipSize = getToolTipViaPtr();
 
-            tooltipSize += IntSize(6,6); // padding, adjust for skin
-
             // adjust tooltip size to fit its content, position it above the crosshair
             /// \todo Slide the tooltip along the bounding box of the focused object (like in Morrowind)
             setCoord(viewSize.width/2 - (tooltipSize.width)/2.f,
@@ -145,11 +139,11 @@ IntSize ToolTips::getToolTipViaPtr ()
         ToolTipInfo info = object.getToolTipInfo(mFocusObject, mWindowManager->getEnvironment());
         if (info.icon == "")
         {
-            tooltipSize= createToolTip(info.caption, info.text);
+            tooltipSize = createToolTip(info.caption, "", 0, info.text);
         }
         else
         {
-            tooltipSize = createImageToolTip(info.caption, info.icon, 32, info.text);
+            tooltipSize = createToolTip(info.caption, info.icon, 32, info.text);
         }
     }
 
@@ -170,71 +164,65 @@ void ToolTips::findImageExtension(std::string& image)
     }
 }
 
-IntSize ToolTips::createImageToolTip(const std::string& caption, const std::string& image, const int imageSize, const std::string& text)
+IntSize ToolTips::createToolTip(const std::string& caption, const std::string& image, const int imageSize, const std::string& text)
 {
     // remove the first newline (easier this way)
     std::string realText = text;
     if (realText.size() > 0 && realText[0] == '\n')
         realText.erase(0, 1);
 
+    // this the maximum width of the tooltip before it starts word-wrapping
+    setCoord(0, 0, 300, 300);
+
+    const IntPoint padding(8, 8);
+
+    const int imageCaptionHPadding = 8;
+    const int imageCaptionVPadding = 4;
+
     std::string realImage = "icons\\" + image;
     findImageExtension(realImage);
 
     EditBox* captionWidget = mDynamicToolTipBox->createWidget<EditBox>("NormalText", IntCoord(0, 0, 300, 300), Align::Left | Align::Top, "ToolTipCaption");
     captionWidget->setProperty("Static", "true");
     captionWidget->setCaption(caption);
-    EditBox* textWidget = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, imageSize, 300, 300-imageSize), Align::Stretch, "ToolTipText");
+    IntSize captionSize = captionWidget->getTextSize();
+
+    int captionHeight = std::max(captionSize.height, imageSize);
+
+    EditBox* textWidget = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, captionHeight+imageCaptionVPadding, 300, 300-captionHeight-imageCaptionVPadding), Align::Stretch, "ToolTipText");
     textWidget->setProperty("Static", "true");
     textWidget->setProperty("MultiLine", "true");
     textWidget->setProperty("WordWrap", "true");
     textWidget->setCaption(realText);
-    textWidget->setTextAlign(Align::HCenter);
-
-    IntSize captionSize = captionWidget->getTextSize();
+    textWidget->setTextAlign(Align::HCenter | Align::Top);
     IntSize textSize = textWidget->getTextSize();
 
     captionSize += IntSize(imageSize, 0); // adjust for image
-    IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width), ((realText != "") ? textSize.height : 0) + imageSize );
+    IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),
+        ((realText != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
 
-    ImageBox* imageWidget = mDynamicToolTipBox->createWidget<ImageBox>("ImageBox",
-        IntCoord((totalSize.width - captionSize.width)/2, 0, imageSize, imageSize),
-        Align::Left | Align::Top, "ToolTipImage");
-    imageWidget->setImageTexture(realImage);
+    if (image != "")
+    {
+        ImageBox* imageWidget = mDynamicToolTipBox->createWidget<ImageBox>("ImageBox",
+            IntCoord((totalSize.width - captionSize.width - imageCaptionHPadding)/2, 0, imageSize, imageSize),
+            Align::Left | Align::Top, "ToolTipImage");
+        imageWidget->setImageTexture(realImage);
+        imageWidget->setPosition (imageWidget->getPosition() + padding);
+    }
 
-    captionWidget->setCoord( (totalSize.width - captionSize.width)/2 + imageSize, (imageSize-captionSize.height)/2, captionSize.width-imageSize, captionSize.height);
+    captionWidget->setCoord( (totalSize.width - captionSize.width)/2 + imageSize,
+        (captionHeight-captionSize.height)/2,
+        captionSize.width-imageSize,
+        captionSize.height);
+
+    captionWidget->setPosition (captionWidget->getPosition() + padding);
+    textWidget->setPosition (textWidget->getPosition() + IntPoint(0, padding.top)); // only apply vertical padding, the horizontal works automatically due to Align::HCenter
+
+    totalSize += IntSize(padding.left*2, padding.top*2);
 
     return totalSize;
 }
 
-IntSize ToolTips::createToolTip(const std::string& caption, const std::string& text)
-{
-    // remove the first newline (easier this way)
-    std::string realText = text;
-    if (realText.size() > 0 && realText[0] == '\n')
-        realText.erase(0, 1);
-
-    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("NormalText", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-    box->setTextAlign(Align::HCenter);
-    box->setProperty("Static", "true");
-    box->setProperty("MultiLine", "true");
-    box->setProperty("WordWrap", "true");
-    box->setCaption(caption + (realText != "" ? "\n#BF9959" + realText : ""));
-
-    return box->getTextSize();
-}
-
-IntSize ToolTips::createToolTip(const std::string& text)
-{
-    EditBox* box = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, 0, 300, 300), Align::Stretch, "ToolTip");
-    box->setTextAlign(Align::HCenter);
-    box->setProperty("Static", "true");
-    box->setProperty("MultiLine", "true");
-    box->setProperty("WordWrap", "true");
-    box->setCaption(text);
-
-    return box->getTextSize();
-}
-
 std::string ToolTips::toString(const float value)
 {
     std::ostringstream stream;
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index 46aab3876..d84a1093b 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -56,13 +56,7 @@ namespace MWGui
         MyGUI::IntSize getToolTipViaPtr ();
         ///< @return requested tooltip size
 
-        MyGUI::IntSize createImageToolTip(const std::string& caption, const std::string& image, const int imageSize, const std::string& text);
-        ///< @return requested tooltip size
-
-        MyGUI::IntSize createToolTip(const std::string& caption, const std::string& text);
-        ///< @return requested tooltip size
-
-        MyGUI::IntSize createToolTip(const std::string& text);
+        MyGUI::IntSize createToolTip(const std::string& caption, const std::string& image, const int imageSize, const std::string& text);
         ///< @return requested tooltip size
 
         bool mGameMode;

From 2e57cf5730ed326d45f1c828d158bb6bb408d1c7 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Tue, 17 Apr 2012 18:47:51 +0200
Subject: [PATCH 23/44] fixed the tooltip for doors leading to exteriors, fixed
 map window cell name

---
 apps/openmw/mwclass/door.cpp         | 26 ++++++++++++++++++++++----
 apps/openmw/mwgui/window_manager.cpp |  5 ++++-
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp
index e06fdecda..794d57d1c 100644
--- a/apps/openmw/mwclass/door.cpp
+++ b/apps/openmw/mwclass/door.cpp
@@ -164,12 +164,30 @@ namespace MWClass
 
         std::string text;
 
-        /// \todo If destCell is empty, the teleport target is an exterior cell. In that case we 
-        /// need to fetch that cell (via target position) and retrieve the region name.
-        if (ref->ref.teleport && (ref->ref.destCell != ""))
+        if (ref->ref.teleport)
         {
+            std::string dest;
+            if (ref->ref.destCell != "")
+            {
+                // door leads to an interior, use interior name as tooltip
+                dest = ref->ref.destCell;
+            }
+            else
+            {
+                // door leads to exterior, use cell name (if any), otherwise translated region name
+                int x,y;
+                environment.mWorld->positionToIndex (ref->ref.doorDest.pos[0], ref->ref.doorDest.pos[1], x, y);
+                const ESM::Cell* cell = environment.mWorld->getStore().cells.findExt(x,y);
+                if (cell->name != "")
+                    dest = cell->name;
+                else
+                {
+                    const ESM::Region* region = environment.mWorld->getStore().regions.search(cell->region);
+                    dest = region->name;
+                }
+            }
             text += "\n" + environment.mWorld->getStore().gameSettings.search("sTo")->str;
-            text += "\n"+ref->ref.destCell;
+            text += "\n"+dest;
         }
 
         if (ref->ref.lockLevel > 0)
diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp
index f49bcfaf8..0188a15b3 100644
--- a/apps/openmw/mwgui/window_manager.cpp
+++ b/apps/openmw/mwgui/window_manager.cpp
@@ -433,7 +433,10 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
         if (cell->cell->name != "")
             name = cell->cell->name;
         else
-            name = cell->cell->region;
+        {
+            const ESM::Region* region = environment.mWorld->getStore().regions.search(cell->cell->region);
+            name = region->name;
+        }
 
         map->setCellName( name );
 

From 046ef39c4a6f756f167147d34f112057c6c9914f Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Wed, 18 Apr 2012 01:10:00 +0200
Subject: [PATCH 24/44] use camera-relative rendering to prevent precision
 artifacts when moving far from (0,0,0)

---
 apps/openmw/mwrender/renderingmanager.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index a35560848..3082cf0d7 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -52,6 +52,10 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
     // Load resources
     ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
 
+    // Due to the huge world size of MW, we'll want camera-relative rendering.
+    // This prevents precision artifacts when moving very far from the origin.
+    mRendering.getScene()->setCameraRelativeRendering(true);
+
     // disable unsupported effects
     const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
     if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects"))

From d568b27b9272ca46670b59ffba4b85336d79cb76 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Wed, 18 Apr 2012 16:53:56 +0200
Subject: [PATCH 25/44] spell widget i18n improvements (used e.g. in birth
 menu)

---
 apps/openmw/mwclass/weapon.cpp | 30 +++++++++++++++++++++++
 apps/openmw/mwgui/tooltips.cpp | 44 +++++++++++++++++++---------------
 apps/openmw/mwgui/tooltips.hpp | 14 +++++++++--
 apps/openmw/mwgui/widgets.cpp  | 20 +++++++++++-----
 4 files changed, 81 insertions(+), 27 deletions(-)

diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp
index d2ea92126..bfb5074b0 100644
--- a/apps/openmw/mwclass/weapon.cpp
+++ b/apps/openmw/mwclass/weapon.cpp
@@ -326,6 +326,36 @@ namespace MWClass
         text += "\n" + environment.mWorld->getStore().gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
         text += MWGui::ToolTips::getValueString(ref->base->data.value, environment.mWorld->getStore().gameSettings.search("sValue")->str);
 
+        // this should be going into a custom mygui widget MWEnchantment
+        /*
+        // enchantments
+        if (ref->base->enchant != "")
+        {
+            const ESM::Enchantment* enchant = environment.mWorld->getStore().enchants.search(ref->base->enchant);
+            if (enchant->data.type == ESM::Enchantment::CastOnce)
+                text += "\n" + environment.mWorld->getStore().gameSettings.search("sItemCastOnce")->str;
+            else if (enchant->data.type == ESM::Enchantment::WhenStrikes)
+                text += "\n" + environment.mWorld->getStore().gameSettings.search("sItemCastWhenStrikes")->str;
+            else if (enchant->data.type == ESM::Enchantment::WhenUsed)
+                text += "\n" + environment.mWorld->getStore().gameSettings.search("sItemCastWhenUsed")->str;
+            else if (enchant->data.type == ESM::Enchantment::ConstantEffect)
+                text += "\n" + environment.mWorld->getStore().gameSettings.search("sItemCastConstant")->str;
+
+            if (enchant->data.type == ESM::Enchantment::WhenStrikes
+                || enchant->data.type == ESM::Enchantment::WhenUsed)
+            {
+                /// \todo store the current enchantment charge somewhere
+               // info.currentCharge = enchant->data.charge;
+                //info.totalCharge = enchant->data.charge;
+            }
+        }
+        */
+        if (ref->base->enchant != "")
+        {
+            const ESM::Enchantment* enchant = environment.mWorld->getStore().enchants.search(ref->base->enchant);
+            info.enchant = enchant;
+        }
+
         if (environment.mWindowManager->getFullHelp()) {
             text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
             text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index ab766dc56..5c69cedb6 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -51,26 +51,35 @@ void ToolTips::onFrame(float frameDuration)
 
         std::string type = focus->getUserString("ToolTipType");
         std::string text = focus->getUserString("ToolTipText");
+
+        ToolTipInfo info;
+
         if (type == "")
         {
             mDynamicToolTipBox->setVisible(false);
             return;
-        }
+        }        
         else if (type == "Text")
-            tooltipSize = createToolTip(text, "", 0, "");
+        {
+            info.caption = text;
+        }
         else if (type == "CaptionText")
         {
             std::string caption = focus->getUserString("ToolTipCaption");
-            tooltipSize = createToolTip(caption, "", 0, text);
+            info.caption = caption;
+            info.text = text;
         }
         else if (type == "ImageCaptionText")
         {
             std::string caption = focus->getUserString("ToolTipCaption");
             std::string image = focus->getUserString("ToolTipImage");
             std::string sizeString = focus->getUserString("ToolTipImageSize");
-            int size = (sizeString != "" ? boost::lexical_cast<int>(sizeString) : 32);
-            tooltipSize = createToolTip(caption, image, size, text);
+
+            info.text = text;
+            info.caption = caption;
+            info.icon = image;
         }
+        tooltipSize = createToolTip(info);
 
         IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
 
@@ -137,14 +146,7 @@ IntSize ToolTips::getToolTipViaPtr ()
         mDynamicToolTipBox->setVisible(true);
 
         ToolTipInfo info = object.getToolTipInfo(mFocusObject, mWindowManager->getEnvironment());
-        if (info.icon == "")
-        {
-            tooltipSize = createToolTip(info.caption, "", 0, info.text);
-        }
-        else
-        {
-            tooltipSize = createToolTip(info.caption, info.icon, 32, info.text);
-        }
+        tooltipSize = createToolTip(info);
     }
 
     return tooltipSize;
@@ -164,12 +166,16 @@ void ToolTips::findImageExtension(std::string& image)
     }
 }
 
-IntSize ToolTips::createToolTip(const std::string& caption, const std::string& image, const int imageSize, const std::string& text)
+IntSize ToolTips::createToolTip(const ToolTipInfo& info)
 {
+    std::string caption = info.caption;
+    std::string image = info.icon;
+    int imageSize = (image != "") ? 32 : 0;
+    std::string text = info.text;
+
     // remove the first newline (easier this way)
-    std::string realText = text;
-    if (realText.size() > 0 && realText[0] == '\n')
-        realText.erase(0, 1);
+    if (text.size() > 0 && text[0] == '\n')
+        text.erase(0, 1);
 
     // this the maximum width of the tooltip before it starts word-wrapping
     setCoord(0, 0, 300, 300);
@@ -193,13 +199,13 @@ IntSize ToolTips::createToolTip(const std::string& caption, const std::string& i
     textWidget->setProperty("Static", "true");
     textWidget->setProperty("MultiLine", "true");
     textWidget->setProperty("WordWrap", "true");
-    textWidget->setCaption(realText);
+    textWidget->setCaption(text);
     textWidget->setTextAlign(Align::HCenter | Align::Top);
     IntSize textSize = textWidget->getTextSize();
 
     captionSize += IntSize(imageSize, 0); // adjust for image
     IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),
-        ((realText != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
+        ((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
 
     if (image != "")
     {
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index d84a1093b..c00faba86 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -13,11 +13,21 @@ namespace MWGui
     struct ToolTipInfo
     {
     public:
+        ToolTipInfo() :
+            enchant(0),
+            effects(0)
+        {
+        };
+
         std::string caption;
         std::string text;
         std::string icon;
 
-        /// \todo enchantments (armor, cloth, weapons), magic effects (potions, ingredients)
+        // enchantment (for cloth, armor, weapons)
+        const ESM::Enchantment* enchant;
+
+        // effects (for potions, ingredients)
+        const ESM::EffectList* effects;
     };
 
     class ToolTips : public OEngine::GUI::Layout
@@ -56,7 +66,7 @@ namespace MWGui
         MyGUI::IntSize getToolTipViaPtr ();
         ///< @return requested tooltip size
 
-        MyGUI::IntSize createToolTip(const std::string& caption, const std::string& image, const int imageSize, const std::string& text);
+        MyGUI::IntSize createToolTip(const ToolTipInfo& info);
         ///< @return requested tooltip size
 
         bool mGameMode;
diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp
index 74603aaf1..c83383468 100644
--- a/apps/openmw/mwgui/widgets.cpp
+++ b/apps/openmw/mwgui/widgets.cpp
@@ -290,6 +290,12 @@ void MWSpellEffect::updateWidgets()
     {
         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", "");
+
             // TODO: Get name of effect from GMST
             std::string spellLine = "";
             if (effect.skill >= 0 && effect.skill < ESM::Skill::Length)
@@ -313,22 +319,24 @@ void MWSpellEffect::updateWidgets()
             if (effect.magnMin >= 0 || effect.magnMax >= 0)
             {
                 if (effect.magnMin == effect.magnMax)
-                    spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " pts";
+                    spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " " + ((effect.magnMin == 1) ? pt : pts);
                 else
                 {
-                    spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " to " + boost::lexical_cast<std::string>(effect.magnMin) + " pts";
+                    spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + to + boost::lexical_cast<std::string>(effect.magnMin) + " " + pts;
                 }
             }
             if (effect.duration >= 0)
             {
-                spellLine += " for " + boost::lexical_cast<std::string>(effect.duration) + " secs";
+                spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast<std::string>(effect.duration) + ((effect.duration == 1) ? sec : secs);
             }
+
+            std::string on = mWindowManager->getGameSettingString("sonword", "");
             if (effect.range == ESM::RT_Self)
-                spellLine += " on Self";
+                spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", "");
             else if (effect.range == ESM::RT_Touch)
-                spellLine += " on Touch";
+                spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", "");
             else if (effect.range == ESM::RT_Target)
-                spellLine += " on Target";
+                spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", "");
             static_cast<MyGUI::TextBox*>(textWidget)->setCaption(spellLine);
         }
         else

From c7381d44917629cd804875c23ded7ab2d3cbd539 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Wed, 18 Apr 2012 18:09:30 +0200
Subject: [PATCH 26/44] adding widget MWEnchantment

---
 apps/openmw/mwgui/widgets.cpp | 44 +++++++++++++++++++++++++++++++++++
 apps/openmw/mwgui/widgets.hpp | 29 ++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp
index c83383468..568b31455 100644
--- a/apps/openmw/mwgui/widgets.cpp
+++ b/apps/openmw/mwgui/widgets.cpp
@@ -264,6 +264,50 @@ MWSpell::~MWSpell()
 {
 }
 
+/* MWEnchantment */
+
+MWEnchantment::MWEnchantment()
+    : mWindowManager(nullptr)
+{
+}
+
+void MWEnchantment::setEnchantmentId(const std::string &enchantId)
+{
+    id = enchantId;
+    updateWidgets();
+}
+
+void MWEnchantment::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord)
+{
+    const ESMS::ESMStore &store = mWindowManager->getStore();
+    const ESM::Enchantment *enchant = store.enchants.search(id);
+    MYGUI_ASSERT(enchant, "enchantment with id '" << id << "' not found");
+
+    MWSpellEffectPtr effect = nullptr;
+    std::vector<ESM::ENAMstruct>::const_iterator end = enchant->effects.list.end();
+    for (std::vector<ESM::ENAMstruct>::const_iterator it = enchant->effects.list.begin(); it != end; ++it)
+    {
+        effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
+        effect->setWindowManager(mWindowManager);
+        effect->setSpellEffect(*it);
+        effects.push_back(effect);
+        coord.top += effect->getHeight();
+    }
+}
+
+void MWEnchantment::updateWidgets()
+{
+}
+
+void MWEnchantment::initialiseOverride()
+{
+    Base::initialiseOverride();
+}
+
+MWEnchantment::~MWEnchantment()
+{
+}
+
 /* MWSpellEffect */
 
 MWSpellEffect::MWSpellEffect()
diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp
index a7916285e..595ee83b6 100644
--- a/apps/openmw/mwgui/widgets.hpp
+++ b/apps/openmw/mwgui/widgets.hpp
@@ -126,7 +126,7 @@ namespace MWGui
         protected:
             virtual ~MWSpell();
 
-		virtual void initialiseOverride();
+            virtual void initialiseOverride();
 
         private:
             void updateWidgets();
@@ -137,6 +137,33 @@ namespace MWGui
         };
         typedef MWSpell* MWSpellPtr;
 
+        class MYGUI_EXPORT MWEnchantment : public Widget
+        {
+            MYGUI_RTTI_DERIVED( MWEnchantment );
+        public:
+            MWEnchantment();
+
+            typedef MWMechanics::Stat<int> EnchantmentValue;
+
+            void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
+            void setEnchantmentId(const std::string &enchantId);
+            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord);
+
+            const std::string &getSpellId() const { return id; }
+
+        protected:
+            virtual ~MWEnchantment();
+
+            virtual void initialiseOverride();
+
+        private:
+            void updateWidgets();
+
+            WindowManager* mWindowManager;
+            std::string id;
+        };
+        typedef MWEnchantment* MWEnchantmentPtr;
+
         class MYGUI_EXPORT MWSpellEffect : public Widget
         {
             MYGUI_RTTI_DERIVED( MWSpellEffect );

From 4889902b9879aecdf45542b2d5584052de15cb9e Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Wed, 18 Apr 2012 21:18:53 +0200
Subject: [PATCH 27/44] magic effect widget improvements, read name of effect
 from GMST and don't show duration/target for constant effects

---
 apps/openmw/mwgui/birth.cpp      |   2 +-
 apps/openmw/mwgui/widgets.cpp    | 180 ++++++++++++++++++++++++++++---
 apps/openmw/mwgui/widgets.hpp    |   6 +-
 files/mygui/openmw_list.skin.xml |   4 +
 4 files changed, 178 insertions(+), 14 deletions(-)

diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp
index 44c165743..046017204 100644
--- a/apps/openmw/mwgui/birth.cpp
+++ b/apps/openmw/mwgui/birth.cpp
@@ -202,7 +202,7 @@ void BirthDialog::updateSpells()
 
                 MyGUI::IntCoord spellCoord = coord;
                 spellCoord.height = 24; // TODO: This should be fetched from the skin somehow, or perhaps a widget in the layout as a template?
-                spellWidget->createEffectWidgets(spellItems, spellArea, spellCoord);
+                spellWidget->createEffectWidgets(spellItems, spellArea, spellCoord, category);
                 coord.top = spellCoord.top;
 
                 ++i;
diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp
index 568b31455..58cfee991 100644
--- a/apps/openmw/mwgui/widgets.cpp
+++ b/apps/openmw/mwgui/widgets.cpp
@@ -222,7 +222,7 @@ void MWSpell::setSpellId(const std::string &spellId)
     updateWidgets();
 }
 
-void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord)
+void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, const int category)
 {
     const ESMS::ESMStore &store = mWindowManager->getStore();
     const ESM::Spell *spell = store.spells.search(id);
@@ -234,6 +234,7 @@ void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI:
     {
         effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
         effect->setWindowManager(mWindowManager);
+        effect->setConstant(category == 0);
         effect->setSpellEffect(*it);
         effects.push_back(effect);
         coord.top += effect->getHeight();
@@ -340,8 +341,7 @@ void MWSpellEffect::updateWidgets()
             std::string sec =  " " + mWindowManager->getGameSettingString("ssecond", "");
             std::string secs =  " " + mWindowManager->getGameSettingString("sseconds", "");
 
-            // TODO: Get name of effect from GMST
-            std::string spellLine = "";
+            std::string spellLine = effectIDToString(effect.effectID);
             if (effect.skill >= 0 && effect.skill < ESM::Skill::Length)
             {
                 spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[effect.skill], "");
@@ -369,18 +369,24 @@ void MWSpellEffect::updateWidgets()
                     spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + to + boost::lexical_cast<std::string>(effect.magnMin) + " " + pts;
                 }
             }
-            if (effect.duration >= 0)
+
+            // constant effects have no duration and no target
+            if (!mIsConstant)
             {
-                spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast<std::string>(effect.duration) + ((effect.duration == 1) ? sec : secs);
+                if (effect.duration >= 0)
+                {
+                    spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast<std::string>(effect.duration) + ((effect.duration == 1) ? sec : secs);
+                }
+
+                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", "");
             }
 
-            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<MyGUI::TextBox*>(textWidget)->setCaption(spellLine);
         }
         else
@@ -394,6 +400,156 @@ void MWSpellEffect::updateWidgets()
     }
 }
 
+std::string MWSpellEffect::effectIDToString(const short effectID)
+{
+    // Map effect ID to GMST name
+    // http://www.uesp.net/morrow/hints/mweffects.shtml
+    std::map<short, std::string> names;
+    names[85] ="sEffectAbsorbAttribute";
+    names[88] ="sEffectAbsorbFatigue";
+    names[86] ="sEffectAbsorbHealth";
+    names[87] ="sEffectAbsorbSpellPoints";
+    names[89] ="sEffectAbsorbSkill";
+    names[63] ="sEffectAlmsiviIntervention";
+    names[47] ="sEffectBlind";
+    names[123] ="sEffectBoundBattleAxe";
+    names[129] ="sEffectBoundBoots";
+    names[127] ="sEffectBoundCuirass";
+    names[120] ="sEffectBoundDagger";
+    names[131] ="sEffectBoundGloves";
+    names[128] ="sEffectBoundHelm";
+    names[125] ="sEffectBoundLongbow";
+    names[121] ="sEffectBoundLongsword";
+    names[122] ="sEffectBoundMace";
+    names[130] ="sEffectBoundShield";
+    names[124] ="sEffectBoundSpear";
+    names[7] ="sEffectBurden";
+    names[50] ="sEffectCalmCreature";
+    names[49] ="sEffectCalmHumanoid";
+    names[40] ="sEffectChameleon";
+    names[44] ="sEffectCharm";
+    names[118] ="sEffectCommandCreatures";
+    names[119] ="sEffectCommandHumanoids";
+    names[132] ="sEffectCorpus"; // NB this typo. (bethesda made it)
+    names[70] ="sEffectCureBlightDisease";
+    names[69] ="sEffectCureCommonDisease";
+    names[71] ="sEffectCureCorprusDisease";
+    names[73] ="sEffectCureParalyzation";
+    names[72] ="sEffectCurePoison";
+    names[22] ="sEffectDamageAttribute";
+    names[25] ="sEffectDamageFatigue";
+    names[23] ="sEffectDamageHealth";
+    names[24] ="sEffectDamageMagicka";
+    names[26] ="sEffectDamageSkill";
+    names[54] ="sEffectDemoralizeCreature";
+    names[53] ="sEffectDemoralizeHumanoid";
+    names[64] ="sEffectDetectAnimal";
+    names[65] ="sEffectDetectEnchantment";
+    names[66] ="sEffectDetectKey";
+    names[38] ="sEffectDisintegrateArmor";
+    names[37] ="sEffectDisintegrateWeapon";
+    names[57] ="sEffectDispel";
+    names[62] ="sEffectDivineIntervention";
+    names[17] ="sEffectDrainAttribute";
+    names[20] ="sEffectDrainFatigue";
+    names[18] ="sEffectDrainHealth";
+    names[19] ="sEffectDrainSpellpoints";
+    names[21] ="sEffectDrainSkill";
+    names[8] ="sEffectFeather";
+    names[14] ="sEffectFireDamage";
+    names[4] ="sEffectFireShield";
+    names[117] ="sEffectFortifyAttackBonus";
+    names[79] ="sEffectFortifyAttribute";
+    names[82] ="sEffectFortifyFatigue";
+    names[80] ="sEffectFortifyHealth";
+    names[81] ="sEffectFortifySpellpoints";
+    names[84] ="sEffectFortifyMagickaMultiplier";
+    names[83] ="sEffectFortifySkill";
+    names[52] ="sEffectFrenzyCreature";
+    names[51] ="sEffectFrenzyHumanoid";
+    names[16] ="sEffectFrostDamage";
+    names[6] ="sEffectFrostShield";
+    names[39] ="sEffectInvisibility";
+    names[9] ="sEffectJump";
+    names[10] ="sEffectLevitate";
+    names[41] ="sEffectLight";
+    names[5] ="sEffectLightningShield";
+    names[12] ="sEffectLock";
+    names[60] ="sEffectMark";
+    names[43] ="sEffectNightEye";
+    names[13] ="sEffectOpen";
+    names[45] ="sEffectParalyze";
+    names[27] ="sEffectPoison";
+    names[56] ="sEffectRallyCreature";
+    names[55] ="sEffectRallyHumanoid";
+    names[61] ="sEffectRecall";
+    names[68] ="sEffectReflect";
+    names[100] ="sEffectRemoveCurse";
+    names[95] ="sEffectResistBlightDisease";
+    names[94] ="sEffectResistCommonDisease";
+    names[96] ="sEffectResistCorprusDisease";
+    names[90] ="sEffectResistFire";
+    names[91] ="sEffectResistFrost";
+    names[93] ="sEffectResistMagicka";
+    names[98] ="sEffectResistNormalWeapons";
+    names[99] ="sEffectResistParalysis";
+    names[97] ="sEffectResistPoison";
+    names[92] ="sEffectResistShock";
+    names[74] ="sEffectRestoreAttribute";
+    names[77] ="sEffectRestoreFatigue";
+    names[75] ="sEffectRestoreHealth";
+    names[76] ="sEffectRestoreSpellPoints";
+    names[78] ="sEffectRestoreSkill";
+    names[42] ="sEffectSanctuary";
+    names[3] ="sEffectShield";
+    names[15] ="sEffectShockDamage";
+    names[46] ="sEffectSilence";
+    names[11] ="sEffectSlowFall";
+    names[58] ="sEffectSoultrap";
+    names[48] ="sEffectSound";
+    names[67] ="sEffectSpellAbsorption";
+    names[136] ="sEffectStuntedMagicka";
+    names[106] ="sEffectSummonAncestralGhost";
+    names[110] ="sEffectSummonBonelord";
+    names[108] ="sEffectSummonLeastBonewalker";
+    names[134] ="sEffectSummonCenturionSphere";
+    names[103] ="sEffectSummonClannfear";
+    names[104] ="sEffectSummonDaedroth";
+    names[105] ="sEffectSummonDremora";
+    names[114] ="sEffectSummonFlameAtronach";
+    names[115] ="sEffectSummonFrostAtronach";
+    names[113] ="sEffectSummonGoldenSaint";
+    names[109] ="sEffectSummonGreaterBonewalker";
+    names[112] ="sEffectSummonHunger";
+    names[102] ="sEffectSummonScamp";
+    names[107] ="sEffectSummonSkeletalMinion";
+    names[116] ="sEffectSummonStormAtronach";
+    names[111] ="sEffectSummonWingedTwilight";
+    names[135] ="sEffectSunDamage";
+    names[1] ="sEffectSwiftSwim";
+    names[59] ="sEffectTelekinesis";
+    names[101] ="sEffectTurnUndead";
+    names[133] ="sEffectVampirism";
+    names[0] ="sEffectWaterBreathing";
+    names[2] ="sEffectWaterWalking";
+    names[33] ="sEffectWeaknesstoBlightDisease";
+    names[32] ="sEffectWeaknesstoCommonDisease";
+    names[34] ="sEffectWeaknesstoCorprusDisease";
+    names[28] ="sEffectWeaknesstoFire";
+    names[29] ="sEffectWeaknesstoFrost";
+    names[31] ="sEffectWeaknesstoMagicka";
+    names[36] ="sEffectWeaknesstoNormalWeapons";
+    names[35] ="sEffectWeaknesstoPoison";
+    names[30] ="sEffectWeaknesstoShock";
+
+    assert(names.find(effectID) != names.end() && "Unimplemented effect type");
+    std::string res = mWindowManager->getGameSettingString(names[effectID], "");
+    if (res == "")
+        std::cout << "Warning: Unknown effect name " << names[effectID] << std::endl;
+
+    return res;
+}
+
 MWSpellEffect::~MWSpellEffect()
 {
 }
diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp
index 595ee83b6..8ac27795d 100644
--- a/apps/openmw/mwgui/widgets.hpp
+++ b/apps/openmw/mwgui/widgets.hpp
@@ -119,7 +119,7 @@ namespace MWGui
 
             void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
             void setSpellId(const std::string &id);
-            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord);
+            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, const int category);
 
             const std::string &getSpellId() const { return id; }
 
@@ -174,6 +174,9 @@ namespace MWGui
 
             void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
             void setSpellEffect(SpellEffectValue value);
+            void setConstant(bool constant) { mIsConstant = constant; }
+
+            std::string effectIDToString(const short effectID);
 
             const SpellEffectValue &getSpellEffect() const { return effect; }
 
@@ -188,6 +191,7 @@ namespace MWGui
 
             WindowManager* mWindowManager;
             SpellEffectValue effect;
+            bool mIsConstant; // constant effect
             MyGUI::ImageBox* imageWidget;
             MyGUI::TextBox* textWidget;
         };
diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml
index 5ec975a1b..02075ad1a 100644
--- a/files/mygui/openmw_list.skin.xml
+++ b/files/mygui/openmw_list.skin.xml
@@ -184,6 +184,10 @@
             <State name="normal" colour="0.70 0.57 0.33" shift="0"/>
             <State name="highlighted" colour="0.85 0.76 0.60" shift="0"/>
             <State name="pushed" colour="0.33 0.38 0.67" shift="0"/>
+            <State name="disabled_checked" colour="0.33 0.38 0.67" shift="0"/>
+            <State name="normal_checked" colour="0.33 0.38 0.67" shift="0"/>
+            <State name="highlighted_checked" colour="0.33 0.38 0.67" shift="0"/>
+            <State name="pushed_checked" colour="0.33 0.38 0.67" shift="0"/>
         </BasisSkin>
     </Skin>
 

From aa4a1b675fcc138c5b15f7d031846f2253b62f89 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Thu, 19 Apr 2012 01:08:26 +0200
Subject: [PATCH 28/44] fixed the sky reflection issue

---
 apps/openmw/mwrender/renderconst.hpp      |  2 ++
 apps/openmw/mwrender/renderingmanager.cpp |  2 ++
 apps/openmw/mwrender/water.cpp            | 44 ++++++++++++++++++-----
 apps/openmw/mwrender/water.hpp            |  9 ++++-
 4 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/apps/openmw/mwrender/renderconst.hpp b/apps/openmw/mwrender/renderconst.hpp
index 2c7f9e9ac..c4aa093c0 100644
--- a/apps/openmw/mwrender/renderconst.hpp
+++ b/apps/openmw/mwrender/renderconst.hpp
@@ -52,6 +52,8 @@ enum VisibilityFlags
     // Sun glare (not visible in reflection)
     RV_Glare = 128,
 
+    RV_OcclusionQuery = 256,
+
     RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water,
 
     /// \todo markers (normally hidden)
diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index 3082cf0d7..581973811 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -225,6 +225,8 @@ void RenderingManager::update (float duration){
     mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() );
 
     checkUnderwater();
+
+    mWater->update();
 }
 void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){
     if(store->cell->data.flags & store->cell->HasWater){
diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp
index 71cf56dfd..445677808 100644
--- a/apps/openmw/mwrender/water.cpp
+++ b/apps/openmw/mwrender/water.cpp
@@ -11,7 +11,8 @@ namespace MWRender
 Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
     mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()),
     mIsUnderwater(false), mVisibilityFlags(0),
-    mReflectionTarget(0), mActive(1), mToggled(1)
+    mReflectionTarget(0), mActive(1), mToggled(1),
+    mReflectionRenderActive(false)
 {
     mSky = sky;
 
@@ -81,6 +82,8 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
 
     mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
 
+    mSceneManager->addRenderQueueListener(this);
+
 
     // ----------------------------------------------------------------------------------------------
     // ---------------------------------- reflection debug overlay ----------------------------------
@@ -161,6 +164,7 @@ void Water::changeCell(const ESM::Cell* cell)
 void Water::setHeight(const float height)
 {
     mTop = height;
+    mWaterPlane = Plane(Vector3::UNIT_Y, height);
     mWaterNode->setPosition(0, height, 0);
 }
 
@@ -220,17 +224,15 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
         mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance());
         mReflectionCamera->setAspectRatio(mCamera->getAspectRatio());
         mReflectionCamera->setFOVy(mCamera->getFOVy());
+        mReflectionRenderActive = true;
 
-        // Some messy code to get the skybox to show up at all
-        // The problem here is that it gets clipped by the water plane
-        // Therefore scale it up a bit
+        /// \todo For some reason this camera is delayed for 1 frame, which causes ugly sky reflection behaviour..
+        /// to circumvent this we just scale the sky up, so it's not that noticable
         Vector3 pos = mCamera->getRealPosition();
         pos.y = mTop*2 - pos.y;
         mSky->setSkyPosition(pos);
-        mSky->scaleSky(mCamera->getFarClipDistance() / 1000.f);
-
-        mReflectionCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop));
-        mReflectionCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop));
+        mSky->scaleSky(mCamera->getFarClipDistance() / 5000.f);
+        mReflectionCamera->enableReflection(mWaterPlane);
     }
 }
 
@@ -240,8 +242,9 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
     {
         mSky->resetSkyPosition();
         mSky->scaleSky(1);
-        mReflectionCamera->disableCustomNearClipPlane();
         mReflectionCamera->disableReflection();
+        mReflectionCamera->disableCustomNearClipPlane();
+        mReflectionRenderActive = false;
     }
 }
 
@@ -290,4 +293,27 @@ void Water::updateVisible()
         mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater);
 }
 
+void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation)
+{
+    // We don't want the sky to get clipped by custom near clip plane (the water plane)
+    if (queueGroupId < 20 && mReflectionRenderActive)
+    {
+        mReflectionCamera->disableCustomNearClipPlane();
+        Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS());
+    }
+}
+
+void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation)
+{
+    if (queueGroupId < 20 && mReflectionRenderActive)
+    {
+        mReflectionCamera->enableCustomNearClipPlane(mWaterPlane);
+        Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS());
+    }
+}
+
+void Water::update()
+{
+}
+
 } // namespace
diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp
index f14482e2b..c8b8d311e 100644
--- a/apps/openmw/mwrender/water.hpp
+++ b/apps/openmw/mwrender/water.hpp
@@ -11,7 +11,7 @@ namespace MWRender {
     class SkyManager;
 
     /// Water rendering 	
-    class Water : public Ogre::RenderTargetListener
+    class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener
     {
         static const int CELL_SIZE = 8192;
         Ogre::Camera *mCamera;
@@ -27,11 +27,17 @@ namespace MWRender {
         bool mToggled;
         int mTop;
 
+        bool mReflectionRenderActive;
+
         Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
 
     protected:
         void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
         void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
+
+        void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation);
+        void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation);
+
         void updateVisible();
 
         SkyManager* mSky;
@@ -55,6 +61,7 @@ namespace MWRender {
         void setActive(bool active);
 
         void toggle();
+        void update();
 
         void setViewportBackground(const Ogre::ColourValue& bg);
 

From fb0e649191270e9c4f4720c2a4983520cf01a632 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Thu, 19 Apr 2012 01:10:55 +0200
Subject: [PATCH 29/44] minor fix

---
 apps/openmw/mwrender/occlusionquery.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp
index 80b804dce..6d3f67de9 100644
--- a/apps/openmw/mwrender/occlusionquery.cpp
+++ b/apps/openmw/mwrender/occlusionquery.cpp
@@ -65,6 +65,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
     mBBQueryTotal->createBillboard(Vector3::ZERO);
     mBBQueryTotal->setMaterialName("QueryTotalPixels");
     mBBQueryTotal->setRenderQueueGroup(RQG_OcclusionQuery+1);
+    mBBQueryTotal->setVisibilityFlags(RV_OcclusionQuery);
     mBBNodeReal->attachObject(mBBQueryTotal);
 
     mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
@@ -73,6 +74,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
     mBBQueryVisible->createBillboard(Vector3::ZERO);
     mBBQueryVisible->setMaterialName("QueryVisiblePixels");
     mBBQueryVisible->setRenderQueueGroup(RQG_OcclusionQuery+1);
+    mBBQueryVisible->setVisibilityFlags(RV_OcclusionQuery);
     mBBNodeReal->attachObject(mBBQueryVisible);
 
     mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
@@ -82,6 +84,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
     mBBQuerySingleObject->createBillboard(Vector3::ZERO);
     mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
     mBBQuerySingleObject->setRenderQueueGroup(RQG_OcclusionQuery);
+    mBBQuerySingleObject->setVisibilityFlags(RV_OcclusionQuery);
     mObjectNode->attachObject(mBBQuerySingleObject);
 
     mRendering->getScene()->addRenderObjectListener(this);

From 934caf7a2b7efca4f69e2cc3040be41ffe5a42aa Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Thu, 19 Apr 2012 01:16:41 +0200
Subject: [PATCH 30/44] removed --report-focus which is now useless

---
 apps/openmw/engine.cpp | 51 ------------------------------------------
 apps/openmw/engine.hpp |  6 -----
 apps/openmw/main.cpp   |  4 ----
 readme.txt             |  1 -
 4 files changed, 62 deletions(-)

diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp
index 36a2cb645..77cb80b0d 100644
--- a/apps/openmw/engine.cpp
+++ b/apps/openmw/engine.cpp
@@ -72,47 +72,6 @@ void OMW::Engine::executeLocalScripts()
     localScripts.setIgnore (MWWorld::Ptr());
 }
 
-void OMW::Engine::updateFocusReport (float duration)
-{
-
-    if ((mFocusTDiff += duration)>0.25)
-    {
-        mFocusTDiff = 0;
-
-        std::string name;
-
-        std::string handle = mEnvironment.mWorld->getFacedHandle();
-
-        if (!handle.empty())
-        {
-            // the faced handle is not updated immediately, so on a cell change it might
-            // point to an object that doesn't exist anymore
-            // therefore, we are catching the "Unknown Ogre handle" exception that occurs in this case
-            try
-            {
-                MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle);
-
-                if (!ptr.isEmpty()){
-                    name = MWWorld::Class::get (ptr).getName (ptr);
-
-                }
-            }
-            catch (std::runtime_error& e)
-            {}
-        }
-
-        if (name!=mFocusName)
-        {
-            mFocusName = name;
-
-            if (mFocusName.empty())
-                std::cout << "Unfocus" << std::endl;
-            else
-                std::cout << "Focus: " << name << std::endl;
-        }
-    }
-}
-
 void OMW::Engine::setAnimationVerbose(bool animverbose){
     if(animverbose){
         NifOgre::NIFLoader::getSingletonPtr()->setOutputAnimFiles(true);
@@ -170,10 +129,6 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
                                                  window->getBatchCount());
 
         mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration);
-
-        // report focus object (for debugging)
-        if (mReportFocus)
-            updateFocusReport (mEnvironment.mFrameDuration);
     }
     catch (const std::exception& e)
     {
@@ -191,7 +146,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
   , mNewGame (false)
   , mUseSound (true)
   , mCompileAll (false)
-  , mReportFocus (false)
   , mFocusTDiff (0)
   , mScriptContext (0)
   , mFSStrict (false)
@@ -303,11 +257,6 @@ void OMW::Engine::setNewGame(bool newGame)
     mNewGame = newGame;
 }
 
-void OMW::Engine::setReportFocus (bool report)
-{
-    mReportFocus = report;
-}
-
 // Initialise and enter main loop.
 
 void OMW::Engine::go()
diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp
index 6eae20cc0..a95d4cb5c 100644
--- a/apps/openmw/engine.hpp
+++ b/apps/openmw/engine.hpp
@@ -73,7 +73,6 @@ namespace OMW
             bool mNewGame;
             bool mUseSound;
             bool mCompileAll;
-            bool mReportFocus;
             float mFocusTDiff;
             std::string mFocusName;
             std::map<std::string,std::string> mFallbackMap;
@@ -100,8 +99,6 @@ namespace OMW
 
             void executeLocalScripts();
 
-            void updateFocusReport (float duration);
-
             virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);
 
         public:
@@ -144,9 +141,6 @@ namespace OMW
             /// Start as a new game.
             void setNewGame(bool newGame);
 
-            /// Write name of focussed object to cout
-            void setReportFocus (bool report);
-
             /// Initialise and enter main loop.
             void go();
 
diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp
index df52faab1..68aa12fb3 100644
--- a/apps/openmw/main.cpp
+++ b/apps/openmw/main.cpp
@@ -155,9 +155,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
             "\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
             "\n\twin1252 - Western European (Latin) alphabet, used by default")
 
-        ("report-focus", bpo::value<bool>()->implicit_value(true)
-            ->default_value(false), "write name of focussed object to cout")
-
         ("fallback", bpo::value<FallbackMap>()->default_value(FallbackMap(), "")
             ->multitoken()->composing(), "fallback values")
 
@@ -265,7 +262,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
     engine.setSoundUsage(!variables["nosound"].as<bool>());
     engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
     engine.setCompileAll(variables["script-all"].as<bool>());
-    engine.setReportFocus(variables["report-focus"].as<bool>());
     engine.setAnimationVerbose(variables["anim-verbose"].as<bool>());
     engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap);
 
diff --git a/readme.txt b/readme.txt
index 52c4e11a2..53f4a4c59 100644
--- a/readme.txt
+++ b/readme.txt
@@ -87,7 +87,6 @@ Allowed options:
 
                                    win1252 - Western European (Latin) alphabet,
                                    used by default
-  --report-focus [=arg(=1)] (=0)   write name of focussed object to cout
   --fallback arg                   fallback values
 
 

From c6da3872b443572b5c686eae15d14f4ac35ab8c1 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Thu, 19 Apr 2012 20:59:57 +0200
Subject: [PATCH 31/44] light improvements

---
 apps/openmw/mwrender/objects.cpp          | 132 ++++++++++++----------
 apps/openmw/mwrender/objects.hpp          |  26 +++--
 apps/openmw/mwrender/renderingmanager.cpp |  11 ++
 apps/openmw/mwrender/renderingmanager.hpp |   3 +
 apps/openmw/mwrender/terrainmaterial.cpp  |   4 +-
 apps/openmw/mwworld/scene.cpp             |   5 +-
 6 files changed, 113 insertions(+), 68 deletions(-)

diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp
index eb7e440cb..a79d72989 100644
--- a/apps/openmw/mwrender/objects.cpp
+++ b/apps/openmw/mwrender/objects.cpp
@@ -8,20 +8,15 @@
 
 using namespace MWRender;
 
-bool Objects::lightConst = false;
-float Objects::lightConstValue = 0.0f;
-
-bool Objects::lightLinear = true;
-int Objects::lightLinearMethod = 1;
+// These are the Morrowind.ini defaults
 float Objects::lightLinearValue = 3;
 float Objects::lightLinearRadiusMult = 1;
 
-bool Objects::lightQuadratic = false;
-int Objects::lightQuadraticMethod = 2;
 float Objects::lightQuadraticValue = 16;
 float Objects::lightQuadraticRadiusMult = 1;
 
-bool Objects::lightOutQuadInLin = false;
+bool Objects::lightOutQuadInLin = true;
+bool Objects::lightQuadratic = false;
 
 int Objects::uniqueID = 0;
 
@@ -132,7 +127,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
         }
     }
 
-    if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects"))
+    if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent)
     {
         insert->attachObject(ent);
 
@@ -144,18 +139,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
     {
         Ogre::StaticGeometry* sg = 0;
 
-/*        if (transparent)
-        {
-            if( mStaticGeometryAlpha.find(ptr.getCell()) == mStaticGeometryAlpha.end())
-            {
-                uniqueID = uniqueID +1;
-                sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
-                mStaticGeometryAlpha[ptr.getCell()] = sg;
-            }
-            else
-                sg = mStaticGeometryAlpha[ptr.getCell()];
-        }
-        else*/ if (small)
+        if (small)
         {
             if( mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end())
             {
@@ -207,34 +191,35 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f
     assert(insert);
     Ogre::Light *light = mRenderer.getScene()->createLight();
     light->setDiffuseColour (r, g, b);
-    mLights.push_back(light->getName());
 
-    float cval=0.0f, lval=0.0f, qval=0.0f;
+    LightInfo info;
+    info.name = light->getName();
+    info.radius = radius;
+    info.colour = Ogre::ColourValue(r, g, b);
+    mLights.push_back(info);
 
-    if(lightConst)
-         cval = lightConstValue;
 
-    if(!lightOutQuadInLin)
+    bool quadratic = false;
+    if (!lightOutQuadInLin)
+        quadratic = lightQuadratic;
+    else
     {
-        if(lightLinear)
-            radius *= lightLinearRadiusMult;
-        if(lightQuadratic)
-            radius *= lightQuadraticRadiusMult;
+        quadratic = !mInterior;
+    }
 
-        if(lightLinear)
-            lval = lightLinearValue / pow(radius, lightLinearMethod);
-        if(lightQuadratic)
-            qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
+    if (!quadratic)
+    {
+        float r = radius * lightLinearRadiusMult;
+        float attenuation = lightLinearValue / r;
+        light->setAttenuation(r*10, 0, attenuation, 0);
     }
     else
     {
-        // FIXME:
-        // Do quadratic or linear, depending if we're in an exterior or interior
-        // cell, respectively. Ignore lightLinear and lightQuadratic.
+        float r = radius * lightQuadraticRadiusMult;
+        float attenuation = lightQuadraticValue / pow(r, 2);
+        light->setAttenuation(r*10, 0, 0, attenuation);
     }
 
-    light->setAttenuation(10*radius, cval, lval, qval);
-
     insert->attachObject(light);
 }
 
@@ -290,13 +275,6 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store)
         mRenderer.getScene()->destroyStaticGeometry (sg);
         sg = 0;
     }
-    /*if(mStaticGeometryAlpha.find(store) != mStaticGeometryAlpha.end())
-    {
-        Ogre::StaticGeometry* sg = mStaticGeometryAlpha[store];
-        mStaticGeometryAlpha.erase(store);
-        mRenderer.getScene()->destroyStaticGeometry (sg);
-        sg = 0;
-    }*/
 
     if(mBounds.find(store) != mBounds.end())
         mBounds.erase(store);
@@ -314,11 +292,6 @@ void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
         Ogre::StaticGeometry* sg = mStaticGeometrySmall[&cell];
         sg->build();
     }
-    /*if(mStaticGeometryAlpha.find(&cell) != mStaticGeometryAlpha.end())
-    {
-        Ogre::StaticGeometry* sg = mStaticGeometryAlpha[&cell];
-        sg->build();
-    }*/
 }
 
 Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
@@ -328,12 +301,12 @@ Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
 
 void Objects::enableLights()
 {
-    std::vector<std::string>::iterator it = mLights.begin();
+    std::vector<LightInfo>::iterator it = mLights.begin();
     while (it != mLights.end())
     {
-        if (mMwRoot->getCreator()->hasLight(*it))
+        if (mMwRoot->getCreator()->hasLight(it->name))
         {
-            mMwRoot->getCreator()->getLight(*it)->setVisible(true);
+            mMwRoot->getCreator()->getLight(it->name)->setVisible(true);
             ++it;
         }
         else
@@ -343,12 +316,12 @@ void Objects::enableLights()
 
 void Objects::disableLights()
 {
-    std::vector<std::string>::iterator it = mLights.begin();
+    std::vector<LightInfo>::iterator it = mLights.begin();
     while (it != mLights.end())
     {
-        if (mMwRoot->getCreator()->hasLight(*it))
+        if (mMwRoot->getCreator()->hasLight(it->name))
         {
-            mMwRoot->getCreator()->getLight(*it)->setVisible(false);
+            mMwRoot->getCreator()->getLight(it->name)->setVisible(false);
             ++it;
         }
         else
@@ -356,3 +329,48 @@ void Objects::disableLights()
     }
 }
 
+void Objects::setInterior(const bool interior)
+{
+    mInterior = interior;
+}
+
+void Objects::update(const float dt)
+{
+    // adjust the lights depending if we're in an interior or exterior cell
+    // quadratic means the light intensity falls off quite fast, resulting in a
+    // dark, atmospheric environment (perfect for exteriors)
+    // for interiors, we want more "warm" lights, so use linear attenuation.
+    std::vector<LightInfo>::iterator it = mLights.begin();
+    while (it != mLights.end())
+    {
+        if (mMwRoot->getCreator()->hasLight(it->name))
+        {
+            Ogre::Light* light = mMwRoot->getCreator()->getLight(it->name);
+
+            bool quadratic = false;
+            if (!lightOutQuadInLin)
+                quadratic = lightQuadratic;
+            else
+            {
+                quadratic = !mInterior;
+            }
+
+            if (!quadratic)
+            {
+                float radius = it->radius * lightLinearRadiusMult;
+                float attenuation = lightLinearValue / it->radius;
+                light->setAttenuation(radius*10, 0, attenuation, 0);
+            }
+            else
+            {
+                float radius = it->radius * lightQuadraticRadiusMult;
+                float attenuation = lightQuadraticValue / pow(it->radius, 2);
+                light->setAttenuation(radius*10, 0, 0, attenuation);
+            }
+
+            ++it;
+        }
+        else
+            it = mLights.erase(it);
+    }
+}
diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp
index 0c19f9f33..63e639ef7 100644
--- a/apps/openmw/mwrender/objects.hpp
+++ b/apps/openmw/mwrender/objects.hpp
@@ -10,37 +10,41 @@
 
 namespace MWRender{
 
+/// information about light needed for rendering
+struct LightInfo
+{
+    std::string name; // ogre handle
+    Ogre::ColourValue colour;
+    float radius;
+};
+
 class Objects{
     OEngine::Render::OgreRenderer &mRenderer;
     std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
     std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
     std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometrySmall;
-    //std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometryAlpha;
     std::map<MWWorld::Ptr::CellStore *, Ogre::AxisAlignedBox> mBounds;
-    std::vector<std::string> mLights;
+    std::vector<LightInfo> mLights;
     Ogre::SceneNode* mMwRoot;
     bool mIsStatic;
     static int uniqueID;
-    static bool lightConst;
-    static float lightConstValue;
 
-    static bool lightLinear;
-    static int lightLinearMethod;
     static float lightLinearValue;
     static float lightLinearRadiusMult;
 
     static bool lightQuadratic;
-    static int lightQuadraticMethod;
     static float lightQuadraticValue;
     static float lightQuadraticRadiusMult;
 
     static bool lightOutQuadInLin;
 
+    bool mInterior;
+
     void clearSceneNode (Ogre::SceneNode *node);
     ///< Remove all movable objects from \a node.
 
 public:
-    Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){}
+    Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer), mInterior(true) {}
     ~Objects(){}
     void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
     void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
@@ -49,6 +53,12 @@ public:
     void enableLights();
     void disableLights();
 
+    void update (const float dt);
+    ///< per-frame update
+
+    void setInterior(const bool interior);
+    ///< call this to switch from interior to exterior or vice versa
+
     Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*);
     ///< get a bounding box that encloses all objects in the specified cell
 
diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index 581973811..5232c5140 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -213,6 +213,7 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve
 void RenderingManager::update (float duration){
 
     mActors.update (duration);
+    mObjects.update (duration);
 
     mOcclusionQuery->update(duration);
 
@@ -508,4 +509,14 @@ Shadows* RenderingManager::getShadows()
     return mShadows;
 }
 
+void RenderingManager::switchToInterior()
+{
+    mObjects.setInterior(true);
+}
+
+void RenderingManager::switchToExterior()
+{
+    mObjects.setInterior(false);
+}
+
 } // namespace
diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp
index a563d78c6..cc3bc62b5 100644
--- a/apps/openmw/mwrender/renderingmanager.hpp
+++ b/apps/openmw/mwrender/renderingmanager.hpp
@@ -117,6 +117,9 @@ class RenderingManager: private RenderingInterface {
 
     Shadows* getShadows();
 
+    void switchToInterior();
+    void switchToExterior();
+
     void setGlare(bool glare);
     void skyEnable ();
     void skyDisable ();
diff --git a/apps/openmw/mwrender/terrainmaterial.cpp b/apps/openmw/mwrender/terrainmaterial.cpp
index 9785ec903..a3265b2a5 100644
--- a/apps/openmw/mwrender/terrainmaterial.cpp
+++ b/apps/openmw/mwrender/terrainmaterial.cpp
@@ -1149,8 +1149,8 @@ namespace Ogre
 				// simple per-pixel lighting with no normal mapping
                                 for (int i=0; i<prof->getNumberOfLightsSupported(); ++i)
                                 {
-                                        outStream << "	float3 halfAngle"<<i<<" = normalize(lightDir"<<i<<" + eyeDir);\n"
-                                                "	float4 litRes"<<i<<" = lit(dot(normalize(lightDir"<<i<<"), normal), dot(halfAngle"<<i<<", normal), scaleBiasSpecular.z);\n";
+                                        outStream <<
+                                            "	float4 litRes"<<i<<" = lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, scaleBiasSpecular.z);\n";
 
                                     if (i > 0)
                                         outStream <<
diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp
index 2123b4799..c8b20b8b1 100644
--- a/apps/openmw/mwworld/scene.cpp
+++ b/apps/openmw/mwworld/scene.cpp
@@ -203,6 +203,8 @@ namespace MWWorld
         // Sky system
         mWorld->adjustSky();
 
+        mRendering.switchToExterior();
+
         mCellChanged = true;
     }
 
@@ -248,8 +250,9 @@ namespace MWWorld
         // adjust player
         mCurrentCell = cell;
         playerCellChange (cell, position);
-        
+
         // adjust fog
+        mRendering.switchToInterior();
         mRendering.configureFog(*cell);
 
         // Sky system

From 7400b7f313d8cbc7141ca89d926be3dc42dca9be Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Thu, 19 Apr 2012 23:25:58 +0200
Subject: [PATCH 32/44] fix underwater effect staying active when teleporting
 from underwater to a cell that doesn't have water

---
 apps/openmw/mwrender/renderingmanager.cpp | 2 ++
 apps/openmw/mwrender/water.cpp            | 7 ++++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index 5232c5140..3f1bb924f 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -512,11 +512,13 @@ Shadows* RenderingManager::getShadows()
 void RenderingManager::switchToInterior()
 {
     mObjects.setInterior(true);
+    mRendering.getScene()->setCameraRelativeRendering(false);
 }
 
 void RenderingManager::switchToExterior()
 {
     mObjects.setInterior(false);
+    mRendering.getScene()->setCameraRelativeRendering(true);
 }
 
 } // namespace
diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp
index 445677808..c81f23f54 100644
--- a/apps/openmw/mwrender/water.cpp
+++ b/apps/openmw/mwrender/water.cpp
@@ -176,7 +176,12 @@ void Water::toggle()
 
 void Water::checkUnderwater(float y)
 {
-    if (!mActive) return;
+    if (!mActive)
+    {
+        CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false);
+        return;
+    }
+
     if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID)
     {
         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false);

From f4428097f951d0c021bb46753e78cf8700c5aa27 Mon Sep 17 00:00:00 2001
From: Marc Zinnschlag <marc@zpages.de>
Date: Mon, 23 Apr 2012 15:37:38 +0200
Subject: [PATCH 33/44] removing more cout spam

---
 apps/openmw/mwclass/npc.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp
index c053ad130..afb904f51 100644
--- a/apps/openmw/mwclass/npc.cpp
+++ b/apps/openmw/mwclass/npc.cpp
@@ -105,10 +105,10 @@ 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, MWWorld::Environment& environment) const
@@ -296,7 +296,6 @@ namespace MWClass
     void Npc::registerSelf()
     {
         boost::shared_ptr<Class> instance (new Npc);
-        std::cout << "class npc:" << typeid (ESM::NPC).name();
         registerClass (typeid (ESM::NPC).name(), instance);
     }
 }

From d5e52e46ea58fb10bbe1cc9171f9aef428947b3f Mon Sep 17 00:00:00 2001
From: Marc Zinnschlag <marc@zpages.de>
Date: Tue, 24 Apr 2012 09:19:41 +0200
Subject: [PATCH 34/44] removing even more cout spam (thanks to scrawl for
 finding this one)

---
 apps/openmw/mwworld/player.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp
index d24780ec1..5ed9aeaff 100644
--- a/apps/openmw/mwworld/player.cpp
+++ b/apps/openmw/mwworld/player.cpp
@@ -24,8 +24,6 @@ namespace MWWorld
         float* playerPos = mPlayer.mData.getPosition().pos;
         playerPos[0] = playerPos[1] = playerPos[2] = 0;
 
-        std::cout << renderer->getHandle();
-
         mPlayer.mData.setBaseNode(renderer->getNode());
         /// \todo Do not make a copy of classes defined in esm/p records.
         mClass = new ESM::Class (*world.getStore().classes.find (player->cls));

From 4ce83badc9860cc965cbdf79c7d859517d16cc96 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sat, 28 Apr 2012 20:42:53 +0200
Subject: [PATCH 35/44] flickering lights

---
 apps/openmw/mwrender/objects.cpp          | 121 +++++++++++++++++-----
 apps/openmw/mwrender/objects.hpp          |  33 ++++--
 apps/openmw/mwrender/renderingmanager.cpp |   2 -
 apps/openmw/mwworld/weather.cpp           |   1 -
 components/esm/loadligh.hpp               |   2 +-
 5 files changed, 122 insertions(+), 37 deletions(-)

diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp
index a79d72989..86a845a27 100644
--- a/apps/openmw/mwrender/objects.cpp
+++ b/apps/openmw/mwrender/objects.cpp
@@ -192,19 +192,43 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f
     Ogre::Light *light = mRenderer.getScene()->createLight();
     light->setDiffuseColour (r, g, b);
 
+    ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
+        ptr.get<ESM::Light>();
+
     LightInfo info;
     info.name = light->getName();
     info.radius = radius;
     info.colour = Ogre::ColourValue(r, g, b);
-    mLights.push_back(info);
 
+    if (ref->base->data.flags & ESM::Light::Negative)
+        info.colour *= -1;
 
+    info.interior = (ptr.getCell()->cell->data.flags & ESM::Cell::Interior);
+
+    if (ref->base->data.flags & ESM::Light::Flicker)
+        info.type = LT_Flicker;
+    else if (ref->base->data.flags & ESM::Light::FlickerSlow)
+        info.type = LT_FlickerSlow;
+    else if (ref->base->data.flags & ESM::Light::Pulse)
+        info.type = LT_Pulse;
+    else if (ref->base->data.flags & ESM::Light::PulseSlow)
+        info.type = LT_PulseSlow;
+    else
+        info.type = LT_Normal;
+
+    // random starting phase for the animation
+    info.time = Ogre::Math::RangeRandom(0, 2 * M_PI);
+
+    // adjust the lights depending if we're in an interior or exterior cell
+    // quadratic means the light intensity falls off quite fast, resulting in a
+    // dark, atmospheric environment (perfect for exteriors)
+    // for interiors, we want more "warm" lights, so use linear attenuation.
     bool quadratic = false;
     if (!lightOutQuadInLin)
         quadratic = lightQuadratic;
     else
     {
-        quadratic = !mInterior;
+        quadratic = !info.interior;
     }
 
     if (!quadratic)
@@ -221,6 +245,7 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f
     }
 
     insert->attachObject(light);
+    mLights.push_back(info);
 }
 
 bool Objects::deleteObject (const MWWorld::Ptr& ptr)
@@ -329,17 +354,8 @@ void Objects::disableLights()
     }
 }
 
-void Objects::setInterior(const bool interior)
-{
-    mInterior = interior;
-}
-
 void Objects::update(const float dt)
 {
-    // adjust the lights depending if we're in an interior or exterior cell
-    // quadratic means the light intensity falls off quite fast, resulting in a
-    // dark, atmospheric environment (perfect for exteriors)
-    // for interiors, we want more "warm" lights, so use linear attenuation.
     std::vector<LightInfo>::iterator it = mLights.begin();
     while (it != mLights.end())
     {
@@ -347,26 +363,77 @@ void Objects::update(const float dt)
         {
             Ogre::Light* light = mMwRoot->getCreator()->getLight(it->name);
 
-            bool quadratic = false;
-            if (!lightOutQuadInLin)
-                quadratic = lightQuadratic;
-            else
-            {
-                quadratic = !mInterior;
-            }
+            // Light animation (pulse & flicker)
+            it->time += dt;
+            const float phase = std::fmod(it->time, (32 * 2 * M_PI)) * 20;
+            float pulseConstant;
 
-            if (!quadratic)
+            // These formulas are just guesswork, but they work pretty well
+            if (it->type == LT_Normal)
             {
-                float radius = it->radius * lightLinearRadiusMult;
-                float attenuation = lightLinearValue / it->radius;
-                light->setAttenuation(radius*10, 0, attenuation, 0);
+                // Less than 1/255 light modifier for a constant light:
+                pulseConstant = (const float)(1.0 + sin(phase) / 255.0 );
+            }
+            else if (it->type == LT_Flicker)
+            {
+                // Let's do a 50% -> 100% sine wave pulse over 1 second:
+                // This is 75% +/- 25%
+                pulseConstant = (const float)(0.75 + sin(phase) * 0.25);
+
+                // Then add a 25% flicker variation:
+                it->resetTime -= dt;
+                if (it->resetTime < 0)
+                {
+                    it->flickerVariation = (rand() % 1000) / 1000 * 0.25;
+                    it->resetTime = 0.5;
+                }
+                if (it->resetTime > 0.25)
+                {
+                    pulseConstant = (pulseConstant+it->flickerVariation) * (1-it->resetTime * 2.0f) + pulseConstant * it->resetTime * 2.0f;
+                }
+                else
+                {
+                    pulseConstant = (pulseConstant+it->flickerVariation) * (it->resetTime * 2.0f) + pulseConstant * (1-it->resetTime * 2.0f);
+                }
+            }
+            else if (it->type == LT_FlickerSlow)
+            {
+                // Let's do a 50% -> 100% sine wave pulse over 1 second:
+                // This is 75% +/- 25%
+                pulseConstant = (const float)(0.75 + sin(phase / 4.0) * 0.25);
+
+                // Then add a 25% flicker variation:
+                it->resetTime -= dt;
+                if (it->resetTime < 0)
+                {
+                    it->flickerVariation = (rand() % 1000) / 1000 * 0.25;
+                    it->resetTime = 0.5;
+                }
+                if (it->resetTime > 0.5)
+                {
+                    pulseConstant = (pulseConstant+it->flickerVariation) * (1-it->resetTime) + pulseConstant * it->resetTime;
+                }
+                else
+                {
+                    pulseConstant = (pulseConstant+it->flickerVariation) * (it->resetTime) + pulseConstant * (1-it->resetTime);
+                }
+            }
+            else if (it->type == LT_Pulse)
+            {
+                // Let's do a 75% -> 125% sine wave pulse over 1 second:
+                // This is 100% +/- 25%
+                pulseConstant = (const float)(1.0 + sin(phase) * 0.25);
+            }
+            else if (it->type == LT_PulseSlow)
+            {
+                // Let's do a 75% -> 125% sine wave pulse over 1 second:
+                // This is 100% +/- 25%
+                pulseConstant = (const float)(1.0 + sin(phase / 4.0) * 0.25);
             }
             else
-            {
-                float radius = it->radius * lightQuadraticRadiusMult;
-                float attenuation = lightQuadraticValue / pow(it->radius, 2);
-                light->setAttenuation(radius*10, 0, 0, attenuation);
-            }
+                assert(0 && "Invalid light type");
+
+            light->setDiffuseColour( it->colour * pulseConstant );
 
             ++it;
         }
diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp
index 63e639ef7..fb26808b9 100644
--- a/apps/openmw/mwrender/objects.hpp
+++ b/apps/openmw/mwrender/objects.hpp
@@ -11,11 +11,37 @@
 namespace MWRender{
 
 /// information about light needed for rendering
+enum LightType
+{
+    // These are all mutually exclusive
+    LT_Normal=0,
+    LT_Flicker=1,
+    LT_FlickerSlow=2,
+    LT_Pulse=3,
+    LT_PulseSlow=4
+};
+
 struct LightInfo
 {
+    // Constants
     std::string name; // ogre handle
     Ogre::ColourValue colour;
     float radius;
+    bool interior; // Does this light belong to an interior or exterior cell
+    LightType type;
+
+    // Runtime variables
+	float flickerVariation; // 25% flicker variation, reset once every 0.5 seconds
+	float flickerSlowVariation; // 25% flicker variation, reset once every 1.0 seconds
+	float resetTime;
+    long double time;
+
+
+    LightInfo() :
+        flickerVariation(0), resetTime(0.5),
+        flickerSlowVariation(0), time(0), interior(true)
+    {
+    }
 };
 
 class Objects{
@@ -38,13 +64,11 @@ class Objects{
 
     static bool lightOutQuadInLin;
 
-    bool mInterior;
-
     void clearSceneNode (Ogre::SceneNode *node);
     ///< Remove all movable objects from \a node.
 
 public:
-    Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer), mInterior(true) {}
+    Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer) {}
     ~Objects(){}
     void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
     void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
@@ -56,9 +80,6 @@ public:
     void update (const float dt);
     ///< per-frame update
 
-    void setInterior(const bool interior);
-    ///< call this to switch from interior to exterior or vice versa
-
     Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*);
     ///< get a bounding box that encloses all objects in the specified cell
 
diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index 6f6503a2e..a95a179c6 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -510,13 +510,11 @@ Shadows* RenderingManager::getShadows()
 
 void RenderingManager::switchToInterior()
 {
-    mObjects.setInterior(true);
     mRendering.getScene()->setCameraRelativeRendering(false);
 }
 
 void RenderingManager::switchToExterior()
 {
-    mObjects.setInterior(false);
     mRendering.getScene()->setCameraRelativeRendering(true);
 }
 
diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp
index 803fce1e1..bcbb96eec 100644
--- a/apps/openmw/mwworld/weather.cpp
+++ b/apps/openmw/mwworld/weather.cpp
@@ -522,7 +522,6 @@ void WeatherManager::update(float duration)
                 // re-scale to 100 percent
                 const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight;//+snow+blizzard;
 
-                srand(time(NULL));
                 float random = ((rand()%100)/100.f) * total;
 
                 //if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
diff --git a/components/esm/loadligh.hpp b/components/esm/loadligh.hpp
index 178258a05..9e7934b15 100644
--- a/components/esm/loadligh.hpp
+++ b/components/esm/loadligh.hpp
@@ -17,7 +17,7 @@ struct Light
     {
         Dynamic = 0x001,
         Carry = 0x002, // Can be carried
-        Negative = 0x004, // Negative light?
+        Negative = 0x004, // Negative light - i.e. darkness
         Flicker = 0x008,
         Fire = 0x010,
         OffDefault = 0x020, // Off by default

From d1d21c8a0e48ac393883376d166cf6a5f190bb6c Mon Sep 17 00:00:00 2001
From: Marc Zinnschlag <marc@zpages.de>
Date: Sat, 28 Apr 2012 21:21:40 +0200
Subject: [PATCH 36/44] compile fix

---
 apps/openmw/mwrender/objects.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp
index 86a845a27..5922086a0 100644
--- a/apps/openmw/mwrender/objects.cpp
+++ b/apps/openmw/mwrender/objects.cpp
@@ -365,7 +365,7 @@ void Objects::update(const float dt)
 
             // Light animation (pulse & flicker)
             it->time += dt;
-            const float phase = std::fmod(it->time, (32 * 2 * M_PI)) * 20;
+            const float phase = std::fmod(static_cast<double> (it->time), (32 * 2 * M_PI)) * 20;
             float pulseConstant;
 
             // These formulas are just guesswork, but they work pretty well

From af3ccd85e313d3d5e26b50a3ce9b745df6c3d894 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sat, 28 Apr 2012 21:23:24 +0200
Subject: [PATCH 37/44] determine shield weight (tested with some
 light/medium/heavy shields)

---
 apps/openmw/mwclass/armor.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp
index 3a3403261..d4dab13d4 100644
--- a/apps/openmw/mwclass/armor.cpp
+++ b/apps/openmw/mwclass/armor.cpp
@@ -138,8 +138,7 @@ namespace MWClass
             case ESM::Armor::Boots: typeGmst = "iBootsWeight"; break;
             case ESM::Armor::LGauntlet:
             case ESM::Armor::RGauntlet: typeGmst = "iGauntletWeight"; break;
-/// \todo how to determine if shield light, medium or heavy?
-//            case ESM::Armor::Shield:
+            case ESM::Armor::Shield: typeGmst = "iShieldWeight"; break;
             case ESM::Armor::LBracer:
             case ESM::Armor::RBracer: typeGmst = "iGauntletWeight"; break;
         }

From cca39978d413205e83e548ac2e2050fbb9cbbc09 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sun, 29 Apr 2012 17:46:09 +0200
Subject: [PATCH 38/44] changed messagebox text colors

---
 files/mygui/openmw_interactive_messagebox_layout.xml | 2 +-
 files/mygui/openmw_messagebox_layout.xml             | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/files/mygui/openmw_interactive_messagebox_layout.xml b/files/mygui/openmw_interactive_messagebox_layout.xml
index 744f21227..b8a71c670 100644
--- a/files/mygui/openmw_interactive_messagebox_layout.xml
+++ b/files/mygui/openmw_interactive_messagebox_layout.xml
@@ -5,7 +5,7 @@
         <Widget type="EditBox" skin="MW_TextEditClient" position="10 10 490 20" align="ALIGN_LEFT ALIGN_TOP STRETCH" name="message">
             <Property key="FontName" value = "Default" />
             <Property key="TextAlign" value="ALIGN_CENTER" />
-            <Property key="TextColour" value = "0.7 0.7 0.7" />
+            <Property key="TextColour" value = "0.75 0.6 0.35" />
             <Property key="Static" value="true"/>
             <Property key="WordWrap" value="true"/>
             <Property key="MultiLine" value="1" />
diff --git a/files/mygui/openmw_messagebox_layout.xml b/files/mygui/openmw_messagebox_layout.xml
index 81d1c0a57..c99c00a49 100644
--- a/files/mygui/openmw_messagebox_layout.xml
+++ b/files/mygui/openmw_messagebox_layout.xml
@@ -8,7 +8,7 @@
         <Widget type="EditBox" skin="MW_TextEditClient" position="5 -5 0 0" name="message"  align="ALIGN_LEFT ALIGN_TOP STRETCH">
             <Property key="FontName" value = "Default" />
             <Property key="TextAlign" value="ALIGN_CENTER" />
-            <Property key="TextColour" value = "0.7 0.7 0.7" />
+            <Property key="TextColour" value = "0.75 0.6 0.35" />
             <Property key="Static" value="true"/>
             <Property key="WordWrap" value="true"/>
             <Property key="MultiLine" value="1" />

From eca18f3e1d5d73c44ee0e05f39ce0d733524c927 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sun, 29 Apr 2012 18:13:03 +0200
Subject: [PATCH 39/44] dialogue topic and choice sorting independent of case

---
 apps/openmw/mwdialogue/dialoguemanager.cpp | 20 +++++++++++++++++++-
 apps/openmw/mwgui/dialogue.cpp             |  2 +-
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp
index 24ee4ee7f..ac41244d1 100644
--- a/apps/openmw/mwdialogue/dialoguemanager.cpp
+++ b/apps/openmw/mwdialogue/dialoguemanager.cpp
@@ -54,6 +54,20 @@ namespace
         return lowerCase;
     }
 
+    bool stringCompareNoCase (std::string first, std::string second)
+    {
+        unsigned int i=0;
+        while ( (i<first.length()) && (i<second.length()) )
+        {
+            if (tolower(first[i])<tolower(second[i])) return true;
+            else if (tolower(first[i])>tolower(second[i])) return false;
+            ++i;
+        }
+        if (first.length()<second.length())
+            return true;
+        else
+            return false;
+    }
 
     template<typename T1, typename T2>
     bool selectCompare (char comp, T1 value1, T2 value2)
@@ -723,7 +737,11 @@ namespace MWDialogue
                 }
             }
         }
+
+        // sort again, because the previous sort was case-sensitive
+        keywordList.sort(stringCompareNoCase);
         win->setKeywords(keywordList);
+
         mChoice = choice;
     }
 
@@ -815,7 +833,7 @@ namespace MWDialogue
     {
         MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
         win->askQuestion(question);
-        mChoiceMap[question] = choice;
+        mChoiceMap[toLower(question)] = choice;
         mIsInChoice = true;
     }
 
diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp
index 2386cf9a3..960ead2ac 100644
--- a/apps/openmw/mwgui/dialogue.cpp
+++ b/apps/openmw/mwgui/dialogue.cpp
@@ -84,7 +84,7 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
         UString key = history->getColorTextAt(cursorPosition);
         if(color == "#686EBA") MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(key));
 
-        if(color == "#572D21") MWBase::Environment::get().getDialogueManager()->questionAnswered(key);
+        if(color == "#572D21") MWBase::Environment::get().getDialogueManager()->questionAnswered(lower_string(key));
     }
 }
 

From 397a97814510816284268ed3ef56714eace95324 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sun, 29 Apr 2012 18:57:26 +0200
Subject: [PATCH 40/44] DispositionEdit tweaks

---
 files/mygui/openmw_dialogue_window_layout.xml | 2 +-
 files/mygui/openmw_dialogue_window_skin.xml   | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/files/mygui/openmw_dialogue_window_layout.xml b/files/mygui/openmw_dialogue_window_layout.xml
index 29a3b511e..b0e437074 100644
--- a/files/mygui/openmw_dialogue_window_layout.xml
+++ b/files/mygui/openmw_dialogue_window_layout.xml
@@ -16,7 +16,7 @@
 		<!-- The disposition bar-->
         <Widget type="ProgressBar" skin="MW_EnergyBar_Blue" position="432 8 132 18"
             align="Right Top" name="Disposition">
-			<Widget type="EditBox" skin="MW_DispositionEdit" position_real = "0.25 0 0.5 1" name = "DispositionText"/>
+			<Widget type="EditBox" skin="MW_DispositionEdit" position_real = "0 0 1 1" align="Stretch" name = "DispositionText"/>
 		</Widget>
         <!-- The list of topics -->
         <Widget type="ListBox" skin="MW_List" position="432 31 132 328" name="TopicsList" align="Right VStretch">
diff --git a/files/mygui/openmw_dialogue_window_skin.xml b/files/mygui/openmw_dialogue_window_skin.xml
index ecdec8a5c..31ce626be 100644
--- a/files/mygui/openmw_dialogue_window_skin.xml
+++ b/files/mygui/openmw_dialogue_window_skin.xml
@@ -8,12 +8,12 @@
     </Skin>
 
     <Skin name="MW_DispositionEdit" size="0 0 50 50">
-        <Property key="FontName" value = "MonoFont" />
-        <Property key="TextAlign" value = "Left Top" />
+        <Property key="FontName" value = "Default" />
+        <Property key="TextAlign" value = "Center" />
         <Property key="Colour" value = "0000FF" />
         <Property key="Static" value="1" />
         <Property key="WordWrap" value = "true" />
-        <Child type="TextBox" skin="MW_DispEdit" offset="0 0 35 10" align = "ALIGN_STRETCH" name = "Client"/>
+        <Child type="TextBox" skin="MW_DispEdit" offset="0 0 0 -4" align = "ALIGN_STRETCH" name = "Client"/>
     </Skin>
     
 </MyGUI>

From f733382f749dc3d7755534adcb3f2db7bacee067 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 30 Apr 2012 00:57:41 +0200
Subject: [PATCH 41/44] tooltip now contains info about item enchantment

---
 apps/openmw/mwclass/armor.cpp        |  2 +
 apps/openmw/mwclass/book.cpp         |  2 +
 apps/openmw/mwclass/clothing.cpp     |  2 +
 apps/openmw/mwclass/weapon.cpp       | 30 +---------
 apps/openmw/mwgui/dialogue.cpp       | 10 +++-
 apps/openmw/mwgui/dialogue.hpp       |  1 +
 apps/openmw/mwgui/tooltips.cpp       | 83 +++++++++++++++++++++++++---
 apps/openmw/mwgui/tooltips.hpp       |  3 +-
 apps/openmw/mwgui/widgets.cpp        | 35 +++++++++++-
 apps/openmw/mwgui/widgets.hpp        | 21 ++++++-
 apps/openmw/mwgui/window_manager.cpp |  1 +
 files/mygui/openmw_text.skin.xml     |  5 ++
 12 files changed, 153 insertions(+), 42 deletions(-)

diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp
index a01b28a21..fb34e4c88 100644
--- a/apps/openmw/mwclass/armor.cpp
+++ b/apps/openmw/mwclass/armor.cpp
@@ -242,6 +242,8 @@ namespace MWClass
             text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
         }
 
+        info.enchant = ref->base->enchant;
+
         info.text = text;
 
         return info;
diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp
index aa87b009b..ab659b480 100644
--- a/apps/openmw/mwclass/book.cpp
+++ b/apps/openmw/mwclass/book.cpp
@@ -130,6 +130,8 @@ namespace MWClass
             text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
         }
 
+        info.enchant = ref->base->enchant;
+
         info.text = text;
 
         return info;
diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp
index 669407d84..620b664cc 100644
--- a/apps/openmw/mwclass/clothing.cpp
+++ b/apps/openmw/mwclass/clothing.cpp
@@ -195,6 +195,8 @@ namespace MWClass
             text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
         }
 
+        info.enchant = ref->base->enchant;
+
         info.text = text;
 
         return info;
diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp
index 1caedce62..fcfaebcb7 100644
--- a/apps/openmw/mwclass/weapon.cpp
+++ b/apps/openmw/mwclass/weapon.cpp
@@ -328,35 +328,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);
 
-        // this should be going into a custom mygui widget MWEnchantment
-        /*
-        // enchantments
-        if (ref->base->enchant != "")
-        {
-            const ESM::Enchantment* enchant = environment.mWorld->getStore().enchants.search(ref->base->enchant);
-            if (enchant->data.type == ESM::Enchantment::CastOnce)
-                text += "\n" + environment.mWorld->getStore().gameSettings.search("sItemCastOnce")->str;
-            else if (enchant->data.type == ESM::Enchantment::WhenStrikes)
-                text += "\n" + environment.mWorld->getStore().gameSettings.search("sItemCastWhenStrikes")->str;
-            else if (enchant->data.type == ESM::Enchantment::WhenUsed)
-                text += "\n" + environment.mWorld->getStore().gameSettings.search("sItemCastWhenUsed")->str;
-            else if (enchant->data.type == ESM::Enchantment::ConstantEffect)
-                text += "\n" + environment.mWorld->getStore().gameSettings.search("sItemCastConstant")->str;
-
-            if (enchant->data.type == ESM::Enchantment::WhenStrikes
-                || enchant->data.type == ESM::Enchantment::WhenUsed)
-            {
-                /// \todo store the current enchantment charge somewhere
-               // info.currentCharge = enchant->data.charge;
-                //info.totalCharge = enchant->data.charge;
-            }
-        }
-        */
-        if (ref->base->enchant != "")
-        {
-            const ESM::Enchantment* enchant = store.enchants.search(ref->base->enchant);
-            info.enchant = enchant;
-        }
+        info.enchant = ref->base->enchant;
 
         if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
             text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp
index 2386cf9a3..aec405f46 100644
--- a/apps/openmw/mwgui/dialogue.cpp
+++ b/apps/openmw/mwgui/dialogue.cpp
@@ -50,9 +50,9 @@ DialogueWindow::DialogueWindow(WindowManager& parWindowManager)
 
     //An EditBox cannot receive mouse click events, so we use an
     //invisible widget on top of the editbox to receive them
-    /// \todo scrolling the dialogue history with the mouse wheel doesn't work using this solution
     getWidget(eventbox, "EventBox");
     eventbox->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onHistoryClicked);
+    eventbox->eventMouseWheel += MyGUI::newDelegate(this, &DialogueWindow::onMouseWheel);
 
     //Topics list
     getWidget(topicsList, "TopicsList");
@@ -88,6 +88,14 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
     }
 }
 
+void DialogueWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel)
+{
+    if (history->getVScrollPosition() - _rel*0.3 < 0)
+        history->setVScrollPosition(0);
+    else
+        history->setVScrollPosition(history->getVScrollPosition() - _rel*0.3);
+}
+
 void DialogueWindow::open()
 {
     topicsList->removeAllItems();
diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp
index 61e8c124c..5921ca57a 100644
--- a/apps/openmw/mwgui/dialogue.hpp
+++ b/apps/openmw/mwgui/dialogue.hpp
@@ -45,6 +45,7 @@ namespace MWGui
         void onSelectTopic(MyGUI::ListBox* _sender, size_t _index);
         void onByeClicked(MyGUI::Widget* _sender);
         void onHistoryClicked(MyGUI::Widget* _sender);
+        void onMouseWheel(MyGUI::Widget* _sender, int _rel);
 
     private:
         void updateOptions();
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index ef30b88d7..f5b140ec1 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -1,7 +1,10 @@
 #include "tooltips.hpp"
-#include "window_manager.hpp"
 
+#include "window_manager.hpp"
+#include "widgets.hpp"
 #include "../mwworld/class.hpp"
+#include "../mwworld/world.hpp"
+#include "../mwbase/environment.hpp"
 
 #include <boost/lexical_cast.hpp>
 
@@ -177,6 +180,21 @@ IntSize ToolTips::createToolTip(const ToolTipInfo& info)
     if (text.size() > 0 && text[0] == '\n')
         text.erase(0, 1);
 
+    const ESM::Enchantment* enchant;
+    const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
+    if (info.enchant != "")
+    {
+        enchant = store.enchants.search(info.enchant);
+        if (enchant->data.type == ESM::Enchantment::CastOnce)
+            text += "\n" + store.gameSettings.search("sItemCastOnce")->str;
+        else if (enchant->data.type == ESM::Enchantment::WhenStrikes)
+            text += "\n" + store.gameSettings.search("sItemCastWhenStrikes")->str;
+        else if (enchant->data.type == ESM::Enchantment::WhenUsed)
+            text += "\n" + store.gameSettings.search("sItemCastWhenUsed")->str;
+        else if (enchant->data.type == ESM::Enchantment::ConstantEffect)
+            text += "\n" + store.gameSettings.search("sItemCastConstant")->str;
+    }
+
     // this the maximum width of the tooltip before it starts word-wrapping
     setCoord(0, 0, 300, 300);
 
@@ -207,13 +225,55 @@ IntSize ToolTips::createToolTip(const ToolTipInfo& info)
     IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),
         ((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
 
-    if (image != "")
+    if (info.enchant != "")
     {
-        ImageBox* imageWidget = mDynamicToolTipBox->createWidget<ImageBox>("ImageBox",
-            IntCoord((totalSize.width - captionSize.width - imageCaptionHPadding)/2, 0, imageSize, imageSize),
-            Align::Left | Align::Top, "ToolTipImage");
-        imageWidget->setImageTexture(realImage);
-        imageWidget->setPosition (imageWidget->getPosition() + padding);
+        Widget* enchantArea = mDynamicToolTipBox->createWidget<Widget>("",
+            IntCoord(0, totalSize.height, 300, 300-totalSize.height),
+            Align::Stretch, "ToolTipEnchantArea");
+
+        IntCoord coord(0, 6, totalSize.width, 24);
+
+        Widgets::MWEnchantmentPtr enchantWidget = enchantArea->createWidget<Widgets::MWEnchantment>
+            ("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget");
+        enchantWidget->setWindowManager(mWindowManager);
+        enchantWidget->setEnchantmentId(info.enchant);
+
+        std::vector<MyGUI::WidgetPtr> enchantEffectItems;
+        enchantWidget->createEffectWidgets(enchantEffectItems, enchantArea, coord, true, (enchant->data.type == ESM::Enchantment::ConstantEffect));
+        totalSize.height += coord.top-6;
+        totalSize.width = std::max(totalSize.width, coord.width);
+
+        if (enchant->data.type == ESM::Enchantment::WhenStrikes
+            || enchant->data.type == ESM::Enchantment::WhenUsed)
+        {
+            /// \todo store the current enchantment charge somewhere
+            int charge = enchant->data.charge;
+
+            const int chargeWidth = 204;
+
+            TextBox* chargeText = enchantArea->createWidget<TextBox>("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;
+            chargeText->setCoord((totalSize.width - chargeAndTextWidth)/2, coord.top+6, chargeTextWidth, 18);
+
+            IntCoord chargeCoord;
+            if (totalSize.width < chargeWidth)
+            {
+                totalSize.width = chargeWidth;
+                chargeCoord = IntCoord(0, coord.top+6, chargeWidth, 18);
+            }
+            else
+            {
+                chargeCoord = IntCoord((totalSize.width - chargeAndTextWidth)/2 + chargeTextWidth, coord.top+6, chargeWidth, 18);
+            }
+            Widgets::MWDynamicStatPtr chargeWidget = enchantArea->createWidget<Widgets::MWDynamicStat>
+                ("MW_ChargeBar", chargeCoord, Align::Default, "ToolTipEnchantCharge");
+            chargeWidget->setValue(charge, charge);
+            totalSize.height += 24;
+        }
     }
 
     captionWidget->setCoord( (totalSize.width - captionSize.width)/2 + imageSize,
@@ -224,6 +284,15 @@ IntSize ToolTips::createToolTip(const ToolTipInfo& info)
     captionWidget->setPosition (captionWidget->getPosition() + padding);
     textWidget->setPosition (textWidget->getPosition() + IntPoint(0, padding.top)); // only apply vertical padding, the horizontal works automatically due to Align::HCenter
 
+    if (image != "")
+    {
+        ImageBox* imageWidget = mDynamicToolTipBox->createWidget<ImageBox>("ImageBox",
+            IntCoord((totalSize.width - captionSize.width - imageCaptionHPadding)/2, 0, imageSize, imageSize),
+            Align::Left | Align::Top, "ToolTipImage");
+        imageWidget->setImageTexture(realImage);
+        imageWidget->setPosition (imageWidget->getPosition() + padding);
+    }
+
     totalSize += IntSize(padding.left*2, padding.top*2);
 
     return totalSize;
diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp
index c00faba86..fafe471a5 100644
--- a/apps/openmw/mwgui/tooltips.hpp
+++ b/apps/openmw/mwgui/tooltips.hpp
@@ -14,7 +14,6 @@ namespace MWGui
     {
     public:
         ToolTipInfo() :
-            enchant(0),
             effects(0)
         {
         };
@@ -24,7 +23,7 @@ namespace MWGui
         std::string icon;
 
         // enchantment (for cloth, armor, weapons)
-        const ESM::Enchantment* enchant;
+        std::string enchant;
 
         // effects (for potions, ingredients)
         const ESM::EffectList* effects;
diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp
index 58cfee991..769220f7b 100644
--- a/apps/openmw/mwgui/widgets.cpp
+++ b/apps/openmw/mwgui/widgets.cpp
@@ -238,6 +238,7 @@ void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI:
         effect->setSpellEffect(*it);
         effects.push_back(effect);
         coord.top += effect->getHeight();
+        coord.width = std::max(coord.width, effect->getRequestedWidth());
     }
 }
 
@@ -278,22 +279,49 @@ void MWEnchantment::setEnchantmentId(const std::string &enchantId)
     updateWidgets();
 }
 
-void MWEnchantment::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord)
+void MWEnchantment::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, bool constant)
 {
     const ESMS::ESMStore &store = mWindowManager->getStore();
     const ESM::Enchantment *enchant = store.enchants.search(id);
     MYGUI_ASSERT(enchant, "enchantment with id '" << id << "' not found");
 
+    // We don't know the width of all the elements beforehand, so we do it in
+    // 2 steps: first, create all widgets and check their width
     MWSpellEffectPtr effect = nullptr;
     std::vector<ESM::ENAMstruct>::const_iterator end = enchant->effects.list.end();
+    int maxwidth = coord.width;
     for (std::vector<ESM::ENAMstruct>::const_iterator it = enchant->effects.list.begin(); it != end; ++it)
     {
         effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
         effect->setWindowManager(mWindowManager);
         effect->setSpellEffect(*it);
+        effect->setConstant(constant);
         effects.push_back(effect);
+
+        if (effect->getRequestedWidth() > maxwidth)
+            maxwidth = effect->getRequestedWidth();
+
         coord.top += effect->getHeight();
     }
+
+    // then adjust the size for all widgets
+    for (std::vector<MyGUI::WidgetPtr>::iterator it = effects.begin(); it != effects.end(); ++it)
+    {
+        effect = static_cast<MWSpellEffectPtr>(*it);
+        bool needcenter = center && (maxwidth > effect->getRequestedWidth());
+        int diff = maxwidth - effect->getRequestedWidth();
+        if (needcenter)
+        {
+            effect->setCoord(diff/2, effect->getCoord().top, effect->getRequestedWidth(), effect->getCoord().height);
+        }
+        else
+        {
+            effect->setCoord(0, effect->getCoord().top, effect->getRequestedWidth(), effect->getCoord().height);
+        }
+    }
+
+    // inform the parent about width
+    coord.width = maxwidth;
 }
 
 void MWEnchantment::updateWidgets()
@@ -315,6 +343,8 @@ MWSpellEffect::MWSpellEffect()
     : mWindowManager(nullptr)
     , imageWidget(nullptr)
     , textWidget(nullptr)
+    , mRequestedWidth(0)
+    , mIsConstant(0)
 {
 }
 
@@ -366,7 +396,7 @@ void MWSpellEffect::updateWidgets()
                     spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " " + ((effect.magnMin == 1) ? pt : pts);
                 else
                 {
-                    spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + to + boost::lexical_cast<std::string>(effect.magnMin) + " " + pts;
+                    spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + to + boost::lexical_cast<std::string>(effect.magnMax) + " " + pts;
                 }
             }
 
@@ -388,6 +418,7 @@ void MWSpellEffect::updateWidgets()
             }
 
             static_cast<MyGUI::TextBox*>(textWidget)->setCaption(spellLine);
+            mRequestedWidth = textWidget->getTextSize().width + 24;
         }
         else
             static_cast<MyGUI::TextBox*>(textWidget)->setCaption("");
diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp
index 8ac27795d..b4915ac6a 100644
--- a/apps/openmw/mwgui/widgets.hpp
+++ b/apps/openmw/mwgui/widgets.hpp
@@ -119,6 +119,14 @@ namespace MWGui
 
             void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
             void setSpellId(const std::string &id);
+
+            /**
+             * @param vector to store the created effect widgets
+             * @param parent widget
+             * @param coordinates to use, will be expanded if more space is needed
+             * @param spell category, if this is 0, this means the spell effects are permanent and won't display e.g. duration
+             * @param center the effect widgets horizontally
+             */
             void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, const int category);
 
             const std::string &getSpellId() const { return id; }
@@ -147,7 +155,15 @@ namespace MWGui
 
             void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
             void setEnchantmentId(const std::string &enchantId);
-            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord);
+
+            /**
+             * @param vector to store the created effect widgets
+             * @param parent widget
+             * @param coordinates to use, will be expanded if more space is needed
+             * @param center the effect widgets horizontally
+             * @param are the effects of this enchantment constant?
+             */
+            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, bool constant);
 
             const std::string &getSpellId() const { return id; }
 
@@ -180,6 +196,8 @@ namespace MWGui
 
             const SpellEffectValue &getSpellEffect() const { return effect; }
 
+            int getRequestedWidth() const { return mRequestedWidth; }
+
         protected:
             virtual ~MWSpellEffect();
 
@@ -194,6 +212,7 @@ namespace MWGui
             bool mIsConstant; // constant effect
             MyGUI::ImageBox* imageWidget;
             MyGUI::TextBox* textWidget;
+            int mRequestedWidth;
         };
         typedef MWSpellEffect* MWSpellEffectPtr;
 
diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp
index a3e44f65b..ccf558de5 100644
--- a/apps/openmw/mwgui/window_manager.cpp
+++ b/apps/openmw/mwgui/window_manager.cpp
@@ -104,6 +104,7 @@ WindowManager::WindowManager(
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSkill>("Widget");
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWAttribute>("Widget");
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpell>("Widget");
+    MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEnchantment>("Widget");
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget");
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget");
 
diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml
index 9f87c93b3..36d97e153 100644
--- a/files/mygui/openmw_text.skin.xml
+++ b/files/mygui/openmw_text.skin.xml
@@ -93,6 +93,11 @@
         <Child type="TextBox" skin="SandText" offset = "24 0 176 20" align = "ALIGN_VCENTRE ALIGN_HSTRETCH" name = "Text" />
     </Skin>
 
+    <Skin name = "MW_ChargeBar" size = "204 18">
+        <Child type="ProgressBar" skin="MW_Progress_Red" offset = "0 0 204 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "Bar" />
+        <Child type="TextBox" skin="SandTextC" offset = "0 0 204 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "BarText" />
+    </Skin>
+
     <Skin name = "MW_DynamicStat_Red" size = "204 18">
         <Child type="TextBox" skin="SandText" offset = "0 0 100 18" align = "ALIGN_LEFT ALIGN_TOP" name = "Text" />
         <Child type="ProgressBar" skin="MW_Progress_Red" offset = "74 0 130 18" align = "ALIGN_RIGHT ALIGN_TOP" name = "Bar" />

From b82c39c8be6976e3386b413e4a49298dd6e49e3a Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 30 Apr 2012 01:08:10 +0200
Subject: [PATCH 42/44] renamed Widgets::MWEnchantment to Widgets::MWEffectList
 so it can be reused for potion effects

---
 apps/openmw/mwclass/potion.cpp       |  2 ++
 apps/openmw/mwgui/tooltips.cpp       |  2 +-
 apps/openmw/mwgui/widgets.cpp        | 14 +++++++-------
 apps/openmw/mwgui/widgets.hpp        | 10 +++++-----
 apps/openmw/mwgui/window_manager.cpp |  2 +-
 5 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp
index 12ce622ee..edf82cee4 100644
--- a/apps/openmw/mwclass/potion.cpp
+++ b/apps/openmw/mwclass/potion.cpp
@@ -124,6 +124,8 @@ 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);
 
+        ESM::EffectList list = ref->base->effects;
+
         if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
             text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
             text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index f5b140ec1..0cab26b2c 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -233,7 +233,7 @@ IntSize ToolTips::createToolTip(const ToolTipInfo& info)
 
         IntCoord coord(0, 6, totalSize.width, 24);
 
-        Widgets::MWEnchantmentPtr enchantWidget = enchantArea->createWidget<Widgets::MWEnchantment>
+        Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget<Widgets::MWEffectList>
             ("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget");
         enchantWidget->setWindowManager(mWindowManager);
         enchantWidget->setEnchantmentId(info.enchant);
diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp
index 769220f7b..f327a9c1e 100644
--- a/apps/openmw/mwgui/widgets.cpp
+++ b/apps/openmw/mwgui/widgets.cpp
@@ -266,20 +266,20 @@ MWSpell::~MWSpell()
 {
 }
 
-/* MWEnchantment */
+/* MWEffectList */
 
-MWEnchantment::MWEnchantment()
+MWEffectList::MWEffectList()
     : mWindowManager(nullptr)
 {
 }
 
-void MWEnchantment::setEnchantmentId(const std::string &enchantId)
+void MWEffectList::setEnchantmentId(const std::string &enchantId)
 {
     id = enchantId;
     updateWidgets();
 }
 
-void MWEnchantment::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, bool constant)
+void MWEffectList::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, bool constant)
 {
     const ESMS::ESMStore &store = mWindowManager->getStore();
     const ESM::Enchantment *enchant = store.enchants.search(id);
@@ -324,16 +324,16 @@ void MWEnchantment::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects,
     coord.width = maxwidth;
 }
 
-void MWEnchantment::updateWidgets()
+void MWEffectList::updateWidgets()
 {
 }
 
-void MWEnchantment::initialiseOverride()
+void MWEffectList::initialiseOverride()
 {
     Base::initialiseOverride();
 }
 
-MWEnchantment::~MWEnchantment()
+MWEffectList::~MWEffectList()
 {
 }
 
diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp
index b4915ac6a..51ad51678 100644
--- a/apps/openmw/mwgui/widgets.hpp
+++ b/apps/openmw/mwgui/widgets.hpp
@@ -145,11 +145,11 @@ namespace MWGui
         };
         typedef MWSpell* MWSpellPtr;
 
-        class MYGUI_EXPORT MWEnchantment : public Widget
+        class MYGUI_EXPORT MWEffectList : public Widget
         {
-            MYGUI_RTTI_DERIVED( MWEnchantment );
+            MYGUI_RTTI_DERIVED( MWEffectList );
         public:
-            MWEnchantment();
+            MWEffectList();
 
             typedef MWMechanics::Stat<int> EnchantmentValue;
 
@@ -168,7 +168,7 @@ namespace MWGui
             const std::string &getSpellId() const { return id; }
 
         protected:
-            virtual ~MWEnchantment();
+            virtual ~MWEffectList();
 
             virtual void initialiseOverride();
 
@@ -178,7 +178,7 @@ namespace MWGui
             WindowManager* mWindowManager;
             std::string id;
         };
-        typedef MWEnchantment* MWEnchantmentPtr;
+        typedef MWEffectList* MWEffectListPtr;
 
         class MYGUI_EXPORT MWSpellEffect : public Widget
         {
diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp
index ccf558de5..0f2df53e1 100644
--- a/apps/openmw/mwgui/window_manager.cpp
+++ b/apps/openmw/mwgui/window_manager.cpp
@@ -104,7 +104,7 @@ WindowManager::WindowManager(
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSkill>("Widget");
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWAttribute>("Widget");
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpell>("Widget");
-    MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEnchantment>("Widget");
+    MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEffectList>("Widget");
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget");
     MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget");
 

From 22f524f8d52408bbca31af711b745889ef32ad1f Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 30 Apr 2012 01:53:22 +0200
Subject: [PATCH 43/44] potion effects in tooltip

---
 apps/openmw/mwclass/potion.cpp |  2 +-
 apps/openmw/mwgui/birth.cpp    |  2 +-
 apps/openmw/mwgui/tooltips.cpp | 30 ++++++++++++++-
 apps/openmw/mwgui/widgets.cpp  | 70 ++++++++++++++++++++--------------
 apps/openmw/mwgui/widgets.hpp  | 20 ++++++----
 5 files changed, 84 insertions(+), 40 deletions(-)

diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp
index edf82cee4..07e7663b3 100644
--- a/apps/openmw/mwclass/potion.cpp
+++ b/apps/openmw/mwclass/potion.cpp
@@ -124,7 +124,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);
 
-        ESM::EffectList list = ref->base->effects;
+        info.effects = &ref->base->effects;
 
         if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
             text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");
diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp
index 046017204..cb15eaf15 100644
--- a/apps/openmw/mwgui/birth.cpp
+++ b/apps/openmw/mwgui/birth.cpp
@@ -202,7 +202,7 @@ void BirthDialog::updateSpells()
 
                 MyGUI::IntCoord spellCoord = coord;
                 spellCoord.height = 24; // TODO: This should be fetched from the skin somehow, or perhaps a widget in the layout as a template?
-                spellWidget->createEffectWidgets(spellItems, spellArea, spellCoord, category);
+                spellWidget->createEffectWidgets(spellItems, spellArea, spellCoord, (category == 0) ? MWEffectList::EF_Constant : 0);
                 coord.top = spellCoord.top;
 
                 ++i;
diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp
index 0cab26b2c..90b5baa67 100644
--- a/apps/openmw/mwgui/tooltips.cpp
+++ b/apps/openmw/mwgui/tooltips.cpp
@@ -225,6 +225,31 @@ IntSize ToolTips::createToolTip(const ToolTipInfo& info)
     IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),
         ((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
 
+    if (info.effects != 0)
+    {
+        Widget* effectArea = mDynamicToolTipBox->createWidget<Widget>("",
+            IntCoord(0, totalSize.height, 300, 300-totalSize.height),
+            Align::Stretch, "ToolTipEffectArea");
+
+        IntCoord coord(0, 6, totalSize.width, 24);
+
+        /**
+         * \todo
+         * the various potion effects should appear in the tooltip depending if the player 
+         * has enough skill in alchemy to know about the effects of this potion.
+         */
+
+        Widgets::MWEffectListPtr effectsWidget = effectArea->createWidget<Widgets::MWEffectList>
+            ("MW_StatName", coord, Align::Default, "ToolTipEffectsWidget");
+        effectsWidget->setWindowManager(mWindowManager);
+        effectsWidget->setEffectList(info.effects);
+
+        std::vector<MyGUI::WidgetPtr> effectItems;
+        effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, Widgets::MWEffectList::EF_Potion);
+        totalSize.height += coord.top-6;
+        totalSize.width = std::max(totalSize.width, coord.width);
+    }
+
     if (info.enchant != "")
     {
         Widget* enchantArea = mDynamicToolTipBox->createWidget<Widget>("",
@@ -236,10 +261,11 @@ IntSize ToolTips::createToolTip(const ToolTipInfo& info)
         Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget<Widgets::MWEffectList>
             ("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget");
         enchantWidget->setWindowManager(mWindowManager);
-        enchantWidget->setEnchantmentId(info.enchant);
+        enchantWidget->setEffectList(&enchant->effects);
 
         std::vector<MyGUI::WidgetPtr> enchantEffectItems;
-        enchantWidget->createEffectWidgets(enchantEffectItems, enchantArea, coord, true, (enchant->data.type == ESM::Enchantment::ConstantEffect));
+        int flag = (enchant->data.type == ESM::Enchantment::ConstantEffect) ? Widgets::MWEffectList::EF_Constant : 0;
+        enchantWidget->createEffectWidgets(enchantEffectItems, enchantArea, coord, true, flag);
         totalSize.height += coord.top-6;
         totalSize.width = std::max(totalSize.width, coord.width);
 
diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp
index f327a9c1e..2f5af6473 100644
--- a/apps/openmw/mwgui/widgets.cpp
+++ b/apps/openmw/mwgui/widgets.cpp
@@ -222,7 +222,7 @@ void MWSpell::setSpellId(const std::string &spellId)
     updateWidgets();
 }
 
-void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, const int category)
+void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, int flags)
 {
     const ESMS::ESMStore &store = mWindowManager->getStore();
     const ESM::Spell *spell = store.spells.search(id);
@@ -234,7 +234,7 @@ void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI:
     {
         effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
         effect->setWindowManager(mWindowManager);
-        effect->setConstant(category == 0);
+        effect->setFlags(flags);
         effect->setSpellEffect(*it);
         effects.push_back(effect);
         coord.top += effect->getHeight();
@@ -270,32 +270,29 @@ MWSpell::~MWSpell()
 
 MWEffectList::MWEffectList()
     : mWindowManager(nullptr)
+    , mEffectList(0)
 {
 }
 
-void MWEffectList::setEnchantmentId(const std::string &enchantId)
+void MWEffectList::setEffectList(const ESM::EffectList* list)
 {
-    id = enchantId;
+    mEffectList = list;
     updateWidgets();
 }
 
-void MWEffectList::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, bool constant)
+void MWEffectList::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags)
 {
-    const ESMS::ESMStore &store = mWindowManager->getStore();
-    const ESM::Enchantment *enchant = store.enchants.search(id);
-    MYGUI_ASSERT(enchant, "enchantment with id '" << id << "' not found");
-
     // We don't know the width of all the elements beforehand, so we do it in
     // 2 steps: first, create all widgets and check their width
     MWSpellEffectPtr effect = nullptr;
-    std::vector<ESM::ENAMstruct>::const_iterator end = enchant->effects.list.end();
+    std::vector<ESM::ENAMstruct>::const_iterator end = mEffectList->list.end();
     int maxwidth = coord.width;
-    for (std::vector<ESM::ENAMstruct>::const_iterator it = enchant->effects.list.begin(); it != end; ++it)
+    for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffectList->list.begin(); it != end; ++it)
     {
         effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
         effect->setWindowManager(mWindowManager);
+        effect->setFlags(flags);
         effect->setSpellEffect(*it);
-        effect->setConstant(constant);
         effects.push_back(effect);
 
         if (effect->getRequestedWidth() > maxwidth)
@@ -344,7 +341,7 @@ MWSpellEffect::MWSpellEffect()
     , imageWidget(nullptr)
     , textWidget(nullptr)
     , mRequestedWidth(0)
-    , mIsConstant(0)
+    , mFlags(0)
 {
 }
 
@@ -359,6 +356,18 @@ void MWSpellEffect::updateWidgets()
     if (!mWindowManager)
         return;
 
+    // lists effects that have no magnitude (e.g. invisiblity)
+    /// \todo this list is probably incomplete
+    std::vector<std::string> effectsWithoutMagnitude;
+    effectsWithoutMagnitude.push_back("sEffectInvisibility");
+    effectsWithoutMagnitude.push_back("sEffectStuntedMagicka");
+    effectsWithoutMagnitude.push_back("sEffectParalyze");
+
+    // lists effects that have no duration (e.g. open lock)
+    /// \todo this list is probably incomplete
+    std::vector<std::string> effectsWithoutDuration;
+    effectsWithoutDuration.push_back("sEffectOpen");
+
     const ESMS::ESMStore &store = mWindowManager->getStore();
     const ESM::MagicEffect *magicEffect = store.magicEffects.search(effect.effectID);
     if (textWidget)
@@ -371,7 +380,8 @@ void MWSpellEffect::updateWidgets()
             std::string sec =  " " + mWindowManager->getGameSettingString("ssecond", "");
             std::string secs =  " " + mWindowManager->getGameSettingString("sseconds", "");
 
-            std::string spellLine = effectIDToString(effect.effectID);
+            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], "");
@@ -390,7 +400,9 @@ void MWSpellEffect::updateWidgets()
                 };
                 spellLine += " " + mWindowManager->getGameSettingString(attributes[effect.attribute], "");
             }
-            if (effect.magnMin >= 0 || effect.magnMax >= 0)
+
+            bool hasMagnitude = (std::find(effectsWithoutMagnitude.begin(), effectsWithoutMagnitude.end(), effectIDStr) == effectsWithoutMagnitude.end());
+            if ((effect.magnMin >= 0 || effect.magnMax >= 0) && hasMagnitude)
             {
                 if (effect.magnMin == effect.magnMax)
                     spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " " + ((effect.magnMin == 1) ? pt : pts);
@@ -401,20 +413,25 @@ void MWSpellEffect::updateWidgets()
             }
 
             // constant effects have no duration and no target
-            if (!mIsConstant)
+            if (!(mFlags & MWEffectList::EF_Constant))
             {
-                if (effect.duration >= 0)
+                bool hasDuration = (std::find(effectsWithoutDuration.begin(), effectsWithoutDuration.end(), effectIDStr) == effectsWithoutDuration.end());
+                if (effect.duration >= 0 && hasDuration)
                 {
                     spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast<std::string>(effect.duration) + ((effect.duration == 1) ? sec : secs);
                 }
 
-                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", "");
+                // 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<MyGUI::TextBox*>(textWidget)->setCaption(spellLine);
@@ -574,11 +591,8 @@ std::string MWSpellEffect::effectIDToString(const short effectID)
     names[30] ="sEffectWeaknesstoShock";
 
     assert(names.find(effectID) != names.end() && "Unimplemented effect type");
-    std::string res = mWindowManager->getGameSettingString(names[effectID], "");
-    if (res == "")
-        std::cout << "Warning: Unknown effect name " << names[effectID] << std::endl;
 
-    return res;
+    return names[effectID];
 }
 
 MWSpellEffect::~MWSpellEffect()
diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp
index 51ad51678..a1caa3c94 100644
--- a/apps/openmw/mwgui/widgets.hpp
+++ b/apps/openmw/mwgui/widgets.hpp
@@ -153,19 +153,23 @@ namespace MWGui
 
             typedef MWMechanics::Stat<int> EnchantmentValue;
 
+            enum EffectFlags
+            {
+                EF_Potion = 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 setEnchantmentId(const std::string &enchantId);
+            void setEffectList(const ESM::EffectList* list);
 
             /**
              * @param vector to store the created effect widgets
              * @param parent widget
              * @param coordinates to use, will be expanded if more space is needed
              * @param center the effect widgets horizontally
-             * @param are the effects of this enchantment constant?
+             * @param various flags, see MWEffectList::EffectFlags
              */
-            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, bool constant);
-
-            const std::string &getSpellId() const { return id; }
+            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags);
 
         protected:
             virtual ~MWEffectList();
@@ -176,7 +180,7 @@ namespace MWGui
             void updateWidgets();
 
             WindowManager* mWindowManager;
-            std::string id;
+            const ESM::EffectList* mEffectList;
         };
         typedef MWEffectList* MWEffectListPtr;
 
@@ -190,7 +194,7 @@ namespace MWGui
 
             void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
             void setSpellEffect(SpellEffectValue value);
-            void setConstant(bool constant) { mIsConstant = constant; }
+            void setFlags(int flags) { mFlags = flags; }
 
             std::string effectIDToString(const short effectID);
 
@@ -209,7 +213,7 @@ namespace MWGui
 
             WindowManager* mWindowManager;
             SpellEffectValue effect;
-            bool mIsConstant; // constant effect
+            int mFlags;
             MyGUI::ImageBox* imageWidget;
             MyGUI::TextBox* textWidget;
             int mRequestedWidth;

From 2f0a69160cffefdba93a70eb9aa5f818e0237643 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Mon, 30 Apr 2012 02:10:55 +0200
Subject: [PATCH 44/44] small fix

---
 apps/openmw/mwgui/widgets.hpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp
index a1caa3c94..c0e62533d 100644
--- a/apps/openmw/mwgui/widgets.hpp
+++ b/apps/openmw/mwgui/widgets.hpp
@@ -125,9 +125,9 @@ namespace MWGui
              * @param parent widget
              * @param coordinates to use, will be expanded if more space is needed
              * @param spell category, if this is 0, this means the spell effects are permanent and won't display e.g. duration
-             * @param center the effect widgets horizontally
+             * @param various flags, see MWEffectList::EffectFlags
              */
-            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, const int category);
+            void createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, int flags);
 
             const std::string &getSpellId() const { return id; }