mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 10:23:56 +00:00
better floating object label positioning.
This commit is contained in:
parent
d3e162ec83
commit
933a40de14
7 changed files with 82 additions and 6 deletions
|
@ -17,6 +17,8 @@ ToolTips::ToolTips(WindowManager* windowManager) :
|
|||
, mWindowManager(windowManager)
|
||||
, mFullHelp(false)
|
||||
, mEnabled(true)
|
||||
, mFocusToolTipX(0.0)
|
||||
, mFocusToolTipY(0.0)
|
||||
{
|
||||
getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
|
||||
|
||||
|
@ -118,11 +120,8 @@ void ToolTips::onFrame(float frameDuration)
|
|||
{
|
||||
IntSize tooltipSize = getToolTipViaPtr();
|
||||
|
||||
// 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)
|
||||
/// relevant link: http://www.ogre3d.org/tikiwiki/ObjectTextDisplay
|
||||
setCoord(std::max(0, viewSize.width/2 - (tooltipSize.width)/2),
|
||||
std::max(0, viewSize.height/2 - (tooltipSize.height) - 32),
|
||||
setCoord(viewSize.width/2 - tooltipSize.width/2,
|
||||
std::max(0, int(mFocusToolTipY*viewSize.height - tooltipSize.height)),
|
||||
tooltipSize.width,
|
||||
tooltipSize.height);
|
||||
}
|
||||
|
@ -387,3 +386,9 @@ bool ToolTips::getFullHelp() const
|
|||
{
|
||||
return mFullHelp;
|
||||
}
|
||||
|
||||
void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y)
|
||||
{
|
||||
mFocusToolTipX = (min_x + max_x) / 2;
|
||||
mFocusToolTipY = min_y;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@ namespace MWGui
|
|||
bool getFullHelp() const;
|
||||
|
||||
void setFocusObject(const MWWorld::Ptr& focus);
|
||||
void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y);
|
||||
///< set the screen-space position of the tooltip for focused object
|
||||
|
||||
static std::string getValueString(const int value, const std::string& prefix);
|
||||
///< @return "prefix: value" or "" if value is 0
|
||||
|
@ -73,6 +75,9 @@ namespace MWGui
|
|||
MyGUI::IntSize createToolTip(const ToolTipInfo& info);
|
||||
///< @return requested tooltip size
|
||||
|
||||
float mFocusToolTipX;
|
||||
float mFocusToolTipY;
|
||||
|
||||
bool mGameMode;
|
||||
|
||||
bool mEnabled;
|
||||
|
|
|
@ -540,6 +540,11 @@ void WindowManager::setFocusObject(const MWWorld::Ptr& focus)
|
|||
mToolTips->setFocusObject(focus);
|
||||
}
|
||||
|
||||
void WindowManager::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y)
|
||||
{
|
||||
mToolTips->setFocusObjectScreenCoords(min_x, min_y, max_x, max_y);
|
||||
}
|
||||
|
||||
void WindowManager::toggleFullHelp()
|
||||
{
|
||||
mToolTips->toggleFullHelp();
|
||||
|
|
|
@ -165,6 +165,7 @@ namespace MWGui
|
|||
void setPlayerDir(const float x, const float y); ///< set player view direction in map space
|
||||
|
||||
void setFocusObject(const MWWorld::Ptr& focus);
|
||||
void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y);
|
||||
|
||||
void setMouseVisible(bool visible);
|
||||
void setDragDrop(bool dragDrop);
|
||||
|
|
|
@ -518,4 +518,43 @@ void RenderingManager::switchToExterior()
|
|||
mRendering.getScene()->setCameraRelativeRendering(true);
|
||||
}
|
||||
|
||||
Ogre::Vector4 RenderingManager::boundingBoxToScreen(Ogre::AxisAlignedBox bounds)
|
||||
{
|
||||
Ogre::Matrix4 mat = mRendering.getCamera()->getViewMatrix();
|
||||
|
||||
const Ogre::Vector3* corners = bounds.getAllCorners();
|
||||
|
||||
float min_x = 1.0f, max_x = 0.0f, min_y = 1.0f, max_y = 0.0f;
|
||||
|
||||
// expand the screen-space bounding-box so that it completely encloses
|
||||
// the object's AABB
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
Ogre::Vector3 corner = corners[i];
|
||||
|
||||
// multiply the AABB corner vertex by the view matrix to
|
||||
// get a camera-space vertex
|
||||
corner = mat * corner;
|
||||
|
||||
// make 2D relative/normalized coords from the view-space vertex
|
||||
// by dividing out the Z (depth) factor -- this is an approximation
|
||||
float x = corner.x / corner.z + 0.5;
|
||||
float y = corner.y / corner.z + 0.5;
|
||||
|
||||
if (x < min_x)
|
||||
min_x = x;
|
||||
|
||||
if (x > max_x)
|
||||
max_x = x;
|
||||
|
||||
if (y < min_y)
|
||||
min_y = y;
|
||||
|
||||
if (y > max_y)
|
||||
max_y = y;
|
||||
}
|
||||
|
||||
return Vector4(min_x, min_y, max_x, max_y);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -151,6 +151,10 @@ class RenderingManager: private RenderingInterface {
|
|||
///< Skip the animation for the given MW-reference for one frame. Calls to this function for
|
||||
/// references that are currently not in the rendered scene should be ignored.
|
||||
|
||||
Ogre::Vector4 boundingBoxToScreen(Ogre::AxisAlignedBox bounds);
|
||||
///< transform the specified bounding box (in world coordinates) into screen coordinates.
|
||||
/// @return packed vector4 (min_x, min_y, max_x, max_y)
|
||||
|
||||
private:
|
||||
|
||||
void setAmbientMode();
|
||||
|
|
|
@ -768,7 +768,24 @@ namespace MWWorld
|
|||
// inform the GUI about focused object
|
||||
try
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->setFocusObject(getPtrViaHandle(mFacedHandle));
|
||||
MWWorld::Ptr object = getPtrViaHandle(mFacedHandle);
|
||||
MWBase::Environment::get().getWindowManager()->setFocusObject(object);
|
||||
|
||||
// retrieve object dimensions so we know where to place the floating label
|
||||
Ogre::SceneNode* node = object.getRefData().getBaseNode();
|
||||
Ogre::AxisAlignedBox bounds;
|
||||
int i;
|
||||
for (i=0; i<node->numAttachedObjects(); ++i)
|
||||
{
|
||||
Ogre::MovableObject* ob = node->getAttachedObject(i);
|
||||
bounds.merge(ob->getWorldBoundingBox());
|
||||
}
|
||||
if (bounds.isFinite())
|
||||
{
|
||||
Vector4 screenCoords = mRendering->boundingBoxToScreen(bounds);
|
||||
MWBase::Environment::get().getWindowManager()->setFocusObjectScreenCoords(
|
||||
screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]);
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error&)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue