Implement ScalingLayer, for layouting of widgets in screen-relative coordinates

openmw-37
scrawl 9 years ago
parent 08a55febc8
commit 59aee04ddb

@ -115,7 +115,7 @@ add_component_dir (loadinglistener
) )
add_component_dir (myguiplatform add_component_dir (myguiplatform
myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer scalinglayer
) )
add_component_dir (widgets add_component_dir (widgets

@ -0,0 +1,138 @@
#include "scalinglayer.hpp"
#include <MyGUI_RenderManager.h>
namespace osgMyGUI
{
/// @brief the ProxyRenderTarget allows to adjust the pixel scale and offset for a "source" render target.
class ProxyRenderTarget : public MyGUI::IRenderTarget
{
public:
/// @param target The target to render to.
/// @param viewSize The size of the underlying layer node to render.
/// @param hoffset The horizontal rendering offset, specified as an offset from the left screen edge in range 0-1.
/// @param voffset The vertical rendering offset, specified as an offset from the top screen edge in range 0-1.
ProxyRenderTarget(MyGUI::IRenderTarget* target, MyGUI::IntSize viewSize, float hoffset, float voffset)
: mTarget(target)
, mViewSize(viewSize)
, mHOffset(hoffset)
, mVOffset(voffset)
{
}
virtual void begin()
{
mTarget->begin();
}
virtual void end()
{
mTarget->end();
}
virtual void doRender(MyGUI::IVertexBuffer* _buffer, MyGUI::ITexture* _texture, size_t _count)
{
mTarget->doRender(_buffer, _texture, _count);
}
virtual const MyGUI::RenderTargetInfo& getInfo()
{
mInfo = mTarget->getInfo();
mInfo.hOffset = mHOffset;
mInfo.vOffset = mVOffset;
mInfo.pixScaleX = 1.f / mViewSize.width;
mInfo.pixScaleY = 1.f / mViewSize.height;
return mInfo;
}
private:
MyGUI::IRenderTarget* mTarget;
MyGUI::IntSize mViewSize;
float mHOffset, mVOffset;
MyGUI::RenderTargetInfo mInfo;
};
MyGUI::ILayerItem *ScalingLayer::getLayerItemByPoint(int _left, int _top) const
{
screenToLayerCoords(_left, _top);
return OverlappedLayer::getLayerItemByPoint(_left, _top);
}
void ScalingLayer::screenToLayerCoords(int& _left, int& _top) const
{
float scale = getScaleFactor();
if (scale <= 0.f)
return;
MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize();
_left -= globalViewSize.width/2;
_top -= globalViewSize.height/2;
_left /= scale;
_top /= scale;
_left += mViewSize.width/2;
_top += mViewSize.height/2;
}
float ScalingLayer::getScaleFactor() const
{
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
float w = viewSize.width;
float h = viewSize.height;
float heightScale = (h / mViewSize.height);
float widthScale = (w / mViewSize.width);
return std::min(widthScale, heightScale);
}
MyGUI::IntPoint ScalingLayer::getPosition(int _left, int _top) const
{
screenToLayerCoords(_left, _top);
return MyGUI::IntPoint(_left, _top);
}
void ScalingLayer::renderToTarget(MyGUI::IRenderTarget *_target, bool _update)
{
MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntSize viewSize = globalViewSize;
viewSize.width /= getScaleFactor();
viewSize.height /= getScaleFactor();
float hoffset = (globalViewSize.width - mViewSize.width*getScaleFactor())/2.f / static_cast<float>(globalViewSize.width);
float voffset = (globalViewSize.height - mViewSize.height*getScaleFactor())/2.f / static_cast<float>(globalViewSize.height);
ProxyRenderTarget proxy(_target, viewSize, hoffset, voffset);
MyGUI::OverlappedLayer::renderToTarget(&proxy, _update);
}
void ScalingLayer::resizeView(const MyGUI::IntSize &_viewSize)
{
// do nothing
}
void ScalingLayer::deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version)
{
MyGUI::OverlappedLayer::deserialization(_node, _version);
MyGUI::xml::ElementEnumerator info = _node->getElementEnumerator();
while (info.next())
{
if (info->getName() == "Property")
{
const std::string& key = info->findAttribute("key");
const std::string& value = info->findAttribute("value");
if (key == "Size")
{
mViewSize = MyGUI::IntSize::parse(value);
}
}
}
}
}

@ -0,0 +1,31 @@
#ifndef OPENMW_COMPONENTS_MYGUIPLATFORM_SCALINGLAYER
#define OPENMW_COMPONENTS_MYGUIPLATFORM_SCALINGLAYER
#include <MyGUI_OverlappedLayer.h>
namespace osgMyGUI
{
///@brief A Layer that lays out and renders widgets in screen-relative coordinates. The "Size" property determines the size of the virtual screen,
/// which is then upscaled to the real screen size during rendering. The aspect ratio is kept intact, adding blanks to the sides when necessary.
class ScalingLayer : public MyGUI::OverlappedLayer
{
public:
MYGUI_RTTI_DERIVED(ScalingLayer)
virtual void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version);
virtual MyGUI::ILayerItem* getLayerItemByPoint(int _left, int _top) const;
virtual MyGUI::IntPoint getPosition(int _left, int _top) const;
virtual void renderToTarget(MyGUI::IRenderTarget* _target, bool _update);
virtual void resizeView(const MyGUI::IntSize& _viewSize);
private:
void screenToLayerCoords(int& _left, int& _top) const;
float getScaleFactor() const;
};
}
#endif
Loading…
Cancel
Save