diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index bf80a77b2f..c9ba752e94 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -240,7 +240,7 @@ namespace MWGui { try { - ConsoleInterpreterContext interpreterContext (*this, MWWorld::Ptr()); + ConsoleInterpreterContext interpreterContext (*this, mPtr); Interpreter::Interpreter interpreter; MWScript::installOpcodes (interpreter); std::vector code; @@ -375,4 +375,14 @@ namespace MWGui { setCoord(10,10, width-10, height/2); } + + void Console::setSelectedObject(const MWWorld::Ptr& object) + { + mPtr = object; + } + + void Console::onReferenceUnavailable() + { + mPtr = MWWorld::Ptr(); + } } diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 1172858473..eadf4aa4ea 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -16,9 +16,11 @@ #include "../mwscript/compilercontext.hpp" #include "../mwscript/interpretercontext.hpp" +#include "referenceinterface.hpp" + namespace MWGui { - class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler + class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler, public ReferenceInterface { private: @@ -39,7 +41,17 @@ namespace MWGui /// \note The list may contain duplicates (if a name is a keyword and an identifier at the same /// time). - public: + public: + + void setSelectedObject(const MWWorld::Ptr& object); + ///< Set the implicit object for script execution + + protected: + + virtual void onReferenceUnavailable(); + + + public: MyGUI::EditPtr command; MyGUI::EditPtr history; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 14212c2f9d..2f275cd330 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -14,6 +14,7 @@ #include "window_manager.hpp" #include "container.hpp" +#include "console.hpp" using namespace MWGui; @@ -46,6 +47,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) , mMapVisible(true) , mWeaponVisible(true) , mSpellVisible(true) + , mWorldMouseOver(false) { setCoord(0,0, width, height); @@ -265,12 +267,39 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) MWBase::Environment::get().getWindowManager()->setDragDrop(false); } + else + { + GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode(); + + if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) ) + return; + + std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); + MWWorld::Ptr object; + try + { + object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); + } + catch (std::exception& e) + { + return; + } + + if (mode == GM_Console) + MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object); + else if (mode == GM_Console || GM_Inventory) + { + // pick up object + } + } } void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) { if (mDragAndDrop->mIsOnDragAndDrop) { + mWorldMouseOver = false; + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition(); float mouseX = cursorPosition.left / float(viewSize.width); @@ -290,13 +319,14 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) else { MyGUI::PointerManager::getInstance().setPointer("arrow"); - /// \todo make it possible to pick up objects with the mouse, if inventory or container window is open + mWorldMouseOver = true; } } void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) { MyGUI::PointerManager::getInstance().setPointer("arrow"); + mWorldMouseOver = false; } void HUD::onHMSClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 47bd93eef7..0bfe5c20f2 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -33,6 +33,8 @@ namespace MWGui void setCellName(const std::string& cellName); + bool getWorldMouseOver() { return mWorldMouseOver; } + MyGUI::ProgressPtr health, magicka, stamina; MyGUI::Widget* mHealthFrame; MyGUI::Widget *weapBox, *spellBox; @@ -70,6 +72,8 @@ namespace MWGui bool mWeaponVisible; bool mSpellVisible; + bool mWorldMouseOver; + void onWorldClicked(MyGUI::Widget* _sender); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 0f68921905..1f614d56b3 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -67,158 +67,193 @@ void ToolTips::onFrame(float frameDuration) if (!mGameMode) { const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); - const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); - if (mousePos == lastPressed) // mouseclick makes tooltip disappear - return; - - if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) + if (mWindowManager->getWorldMouseOver() && ((mWindowManager->getMode() == GM_Console) + || (mWindowManager->getMode() == GM_Container) + || (mWindowManager->getMode() == GM_Inventory))) { - mRemainingDelay -= frameDuration; + std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); + try + { + mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); + } + catch (std::exception& e) + { + return; + } + + MyGUI::IntSize tooltipSize = getToolTipViaPtr(true); + + IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + + // make the tooltip stay completely in the viewport + if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) + { + tooltipPosition.left = viewSize.width - tooltipSize.width; + } + if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) + { + tooltipPosition.top = viewSize.height - tooltipSize.height; + } + + setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); } + else { - mRemainingDelay = mDelay; - } - mLastMouseX = mousePos.left; - mLastMouseY = mousePos.top; + const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); - if (mRemainingDelay > 0) - return; - - Widget* focus = InputManager::getInstance().getMouseFocusWidget(); - if (focus == 0) - { - return; - } - - IntSize tooltipSize; - - // try to go 1 level up until there is a widget that has tooltip - // this is necessary because some skin elements are actually separate widgets - int i=0; - while (!focus->isUserString("ToolTipType")) - { - focus = focus->getParent(); - if (!focus) + if (mousePos == lastPressed) // mouseclick makes tooltip disappear return; - ++i; - } - std::string type = focus->getUserString("ToolTipType"); - std::string text = focus->getUserString("ToolTipText"); - - ToolTipInfo info; - if (type == "") - { - return; - } - else if (type == "ItemPtr") - { - mFocusObject = *focus->getUserData(); - tooltipSize = getToolTipViaPtr(false); - } - else if (type == "Spell") - { - ToolTipInfo info; - const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); - info.caption = spell->name; - Widgets::SpellEffectList effects; - std::vector::const_iterator end = spell->effects.list.end(); - for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY) { - Widgets::SpellEffectParams params; - params.mEffectID = it->effectID; - params.mSkill = it->skill; - params.mAttribute = it->attribute; - params.mDuration = it->duration; - params.mMagnMin = it->magnMin; - params.mMagnMax = it->magnMax; - params.mRange = it->range; - params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); - effects.push_back(params); - } - info.effects = effects; - tooltipSize = createToolTip(info); - } - else if (type == "Layout") - { - // tooltip defined in the layout - MyGUI::Widget* tooltip; - getWidget(tooltip, focus->getUserString("ToolTipLayout")); - - tooltip->setVisible(true); - if (!tooltip->isUserString("DontResize")) - { - tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping - - tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); + mRemainingDelay -= frameDuration; } else - tooltipSize = tooltip->getSize(); - - std::map userStrings = focus->getUserStrings(); - for (std::map::iterator it = userStrings.begin(); - it != userStrings.end(); ++it) { - if (it->first == "ToolTipType" - || it->first == "ToolTipLayout") - continue; + mRemainingDelay = mDelay; + } + mLastMouseX = mousePos.left; + mLastMouseY = mousePos.top; + if (mRemainingDelay > 0) + return; - size_t underscorePos = it->first.find("_"); - std::string propertyKey = it->first.substr(0, underscorePos); - std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1)); - - MyGUI::Widget* w; - getWidget(w, widgetName); - w->setProperty(propertyKey, it->second); + Widget* focus = InputManager::getInstance().getMouseFocusWidget(); + if (focus == 0) + { + return; } - for (unsigned int i=0; igetChildCount(); ++i) + IntSize tooltipSize; + + // try to go 1 level up until there is a widget that has tooltip + // this is necessary because some skin elements are actually separate widgets + int i=0; + while (!focus->isUserString("ToolTipType")) { - MyGUI::Widget* w = tooltip->getChildAt(i); - - if (w->isUserString("AutoResizeHorizontal")) - { - MyGUI::TextBox* text = w->castType(); - tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); - } - else if (!tooltip->isUserString("DontResize")) - tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8); - - if (w->isUserString("AutoResizeVertical")) - { - MyGUI::TextBox* text = w->castType(); - int height = text->getTextSize().height; - if (height > w->getHeight()) - { - tooltipSize += MyGUI::IntSize(0, height - w->getHeight()); - } - if (height < w->getHeight()) - { - tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height); - } - } + focus = focus->getParent(); + if (!focus) + return; + ++i; } - tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); - } - else - throw std::runtime_error ("unknown tooltip type"); - IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + std::string type = focus->getUserString("ToolTipType"); + std::string text = focus->getUserString("ToolTipText"); - // make the tooltip stay completely in the viewport - if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) - { - tooltipPosition.left = viewSize.width - tooltipSize.width; - } - if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) - { - tooltipPosition.top = viewSize.height - tooltipSize.height; - } + ToolTipInfo info; + if (type == "") + { + return; + } + else if (type == "ItemPtr") + { + mFocusObject = *focus->getUserData(); + tooltipSize = getToolTipViaPtr(false); + } + else if (type == "Spell") + { + ToolTipInfo info; + const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell")); + info.caption = spell->name; + Widgets::SpellEffectList effects; + std::vector::const_iterator end = spell->effects.list.end(); + for (std::vector::const_iterator it = spell->effects.list.begin(); it != end; ++it) + { + Widgets::SpellEffectParams params; + params.mEffectID = it->effectID; + params.mSkill = it->skill; + params.mAttribute = it->attribute; + params.mDuration = it->duration; + params.mMagnMin = it->magnMin; + params.mMagnMax = it->magnMax; + params.mRange = it->range; + params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability); + effects.push_back(params); + } + info.effects = effects; + tooltipSize = createToolTip(info); + } + else if (type == "Layout") + { + // tooltip defined in the layout + MyGUI::Widget* tooltip; + getWidget(tooltip, focus->getUserString("ToolTipLayout")); - setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); + tooltip->setVisible(true); + if (!tooltip->isUserString("DontResize")) + { + tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping + + tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height); + } + else + tooltipSize = tooltip->getSize(); + + std::map userStrings = focus->getUserStrings(); + for (std::map::iterator it = userStrings.begin(); + it != userStrings.end(); ++it) + { + if (it->first == "ToolTipType" + || it->first == "ToolTipLayout") + continue; + + + size_t underscorePos = it->first.find("_"); + std::string propertyKey = it->first.substr(0, underscorePos); + std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1)); + + MyGUI::Widget* w; + getWidget(w, widgetName); + w->setProperty(propertyKey, it->second); + } + + for (unsigned int i=0; igetChildCount(); ++i) + { + MyGUI::Widget* w = tooltip->getChildAt(i); + + if (w->isUserString("AutoResizeHorizontal")) + { + MyGUI::TextBox* text = w->castType(); + tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8); + } + else if (!tooltip->isUserString("DontResize")) + tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8); + + if (w->isUserString("AutoResizeVertical")) + { + MyGUI::TextBox* text = w->castType(); + int height = text->getTextSize().height; + if (height > w->getHeight()) + { + tooltipSize += MyGUI::IntSize(0, height - w->getHeight()); + } + if (height < w->getHeight()) + { + tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height); + } + } + } + tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height); + } + else + throw std::runtime_error ("unknown tooltip type"); + + IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); + + // make the tooltip stay completely in the viewport + if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) + { + tooltipPosition.left = viewSize.width - tooltipSize.width; + } + if ((tooltipPosition.top + tooltipSize.height) > viewSize.height) + { + tooltipPosition.top = viewSize.height - tooltipSize.height; + } + + setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); + } } else { diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 8ddbfe9298..5275ae19d9 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -487,6 +487,7 @@ void WindowManager::onFrame (float frameDuration) mDialogueWindow->checkReferenceAvailable(); mTradeWindow->checkReferenceAvailable(); mContainerWindow->checkReferenceAvailable(); + console->checkReferenceAvailable(); } const ESMS::ESMStore& WindowManager::getStore() const @@ -708,3 +709,25 @@ void WindowManager::unsetSelectedWeapon() hud->unsetSelectedWeapon(); mInventoryWindow->setTitle("#{sSkillHandtohand}"); } + +void WindowManager::getMousePosition(int &x, int &y) +{ + const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); + x = pos.left; + y = pos.top; +} + +void WindowManager::getMousePosition(float &x, float &y) +{ + const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); + x = pos.left; + y = pos.top; + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + x /= viewSize.width; + y /= viewSize.height; +} + +bool WindowManager::getWorldMouseOver() +{ + return hud->getWorldMouseOver(); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 037022b42b..19ad7702a4 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -155,6 +155,7 @@ namespace MWGui MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;} MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} MWGui::SpellWindow* getSpellWindow() {return mSpellWindow;} + MWGui::Console* getConsole() {return console;} MyGUI::Gui* getGui() const { return gui; } @@ -188,7 +189,10 @@ namespace MWGui void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); void setMouseVisible(bool visible); + void getMousePosition(int &x, int &y); + void getMousePosition(float &x, float &y); void setDragDrop(bool dragDrop); + bool getWorldMouseOver(); void toggleFogOfWar(); void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 808c712a07..5598ff3c0b 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -66,7 +66,23 @@ namespace MWWorld return mEngine->rayTest2(from,to); } - void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight){ + + std::vector < std::pair > PhysicsSystem::getFacedObjects (float mouseX, float mouseY) + { + Ray ray = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); + Ogre::Vector3 from = ray.getOrigin(); + Ogre::Vector3 to = ray.getPoint(500); /// \todo make this distance (ray length) configurable + + btVector3 _from, _to; + // OGRE to MW coordinates + _from = btVector3(from.x, -from.z, from.y); + _to = btVector3(to.x, -to.z, to.y); + + return mEngine->rayTest2(_from,_to); + } + + void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight) + { playerphysics->hasWater = hasWater; if(hasWater){ playerphysics->waterHeight = waterHeight; @@ -84,6 +100,14 @@ namespace MWWorld return result; } + btVector3 PhysicsSystem::getRayPoint(float extent, float mouseX, float mouseY) + { + //get a ray pointing to the center of the viewport + Ray centerRay = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); + btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable + return result; + } + bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) { btVector3 _from, _to; diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 9b03d2124f..1a8bd87ae4 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -47,9 +47,12 @@ namespace MWWorld std::pair getFacedHandle (MWWorld::World& world); btVector3 getRayPoint(float extent); + btVector3 getRayPoint(float extent, float mouseX, float mouseY); std::vector < std::pair > getFacedObjects (); + std::vector < std::pair > getFacedObjects (float mouseX, float mouseY); + // cast ray, return true if it hit something bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 6802d5cc12..e8d555689d 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -818,7 +818,15 @@ namespace MWWorld // send new query // figure out which object we want to test against - std::vector < std::pair < float, std::string > > results = mPhysics->getFacedObjects(); + std::vector < std::pair < float, std::string > > results; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + results = mPhysics->getFacedObjects(x, y); + } + else + results = mPhysics->getFacedObjects(); // ignore the player and other things we're not interested in std::vector < std::pair < float, std::string > >::iterator it = results.begin(); @@ -843,7 +851,15 @@ namespace MWWorld mFaced1Name = results.front().second; mNumFacing = 1; - btVector3 p = mPhysics->getRayPoint(results.front().first); + btVector3 p; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + p = mPhysics->getRayPoint(results.front().first, x, y); + } + else + p = mPhysics->getRayPoint(results.front().first); Ogre::Vector3 pos(p.x(), p.z(), -p.y()); Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode(); @@ -860,7 +876,15 @@ namespace MWWorld mFaced2 = getPtrViaHandle(results[1].second); mNumFacing = 2; - btVector3 p = mPhysics->getRayPoint(results[1].first); + btVector3 p; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + p = mPhysics->getRayPoint(results[1].first, x, y); + } + else + p = mPhysics->getRayPoint(results[1].first); Ogre::Vector3 pos(p.x(), p.z(), -p.y()); Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode(); Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode();