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; }