1
0
Fork 0
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:
scrawl 2012-05-14 21:37:43 +02:00
parent d3e162ec83
commit 933a40de14
7 changed files with 82 additions and 6 deletions

View file

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

View file

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

View file

@ -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();

View file

@ -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);

View file

@ -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

View file

@ -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();

View file

@ -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&)
{