1 #include "scalinglayer.hpp"
2 
3 #include <MyGUI_RenderManager.h>
4 #include <algorithm>
5 
6 #include "myguicompat.h"
7 
8 namespace osgMyGUI
9 {
10 
11     /// @brief the ProxyRenderTarget allows to adjust the pixel scale and offset for a "source" render target.
12     class ProxyRenderTarget : public MyGUI::IRenderTarget
13     {
14     public:
15         /// @param target The target to render to.
16         /// @param viewSize The size of the underlying layer node to render.
17         /// @param hoffset The horizontal rendering offset, specified as an offset from the left screen edge in range 0-1.
18         /// @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)19         ProxyRenderTarget(MyGUI::IRenderTarget* target, MyGUI::IntSize viewSize, float hoffset, float voffset)
20             : mTarget(target)
21             , mViewSize(viewSize)
22             , mHOffset(hoffset)
23             , mVOffset(voffset)
24         {
25         }
26 
begin()27         void begin() override
28         {
29             mTarget->begin();
30         }
31 
end()32         void end() override
33         {
34             mTarget->end();
35         }
36 
doRender(MyGUI::IVertexBuffer * _buffer,MyGUI::ITexture * _texture,size_t _count)37         void doRender(MyGUI::IVertexBuffer* _buffer, MyGUI::ITexture* _texture, size_t _count) override
38         {
39             mTarget->doRender(_buffer, _texture, _count);
40         }
41 
getInfo()42         const MyGUI::RenderTargetInfo& getInfo() OPENMW_MYGUI_CONST_GETTER_3_4_1 override
43         {
44             mInfo = mTarget->getInfo();
45             mInfo.hOffset = mHOffset;
46             mInfo.vOffset = mVOffset;
47             mInfo.pixScaleX = 1.f / mViewSize.width;
48             mInfo.pixScaleY = 1.f / mViewSize.height;
49             return mInfo;
50         }
51 
52     private:
53         MyGUI::IRenderTarget* mTarget;
54         MyGUI::IntSize mViewSize;
55         float mHOffset, mVOffset;
56         mutable MyGUI::RenderTargetInfo mInfo;
57     };
58 
getLayerItemByPoint(int _left,int _top) const59     MyGUI::ILayerItem *ScalingLayer::getLayerItemByPoint(int _left, int _top) const
60     {
61         screenToLayerCoords(_left, _top);
62 
63         return OverlappedLayer::getLayerItemByPoint(_left, _top);
64     }
65 
screenToLayerCoords(int & _left,int & _top) const66     void ScalingLayer::screenToLayerCoords(int& _left, int& _top) const
67     {
68         float scale = getScaleFactor();
69         if (scale <= 0.f)
70             return;
71 
72         MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize();
73 
74         _left -= globalViewSize.width/2;
75         _top -= globalViewSize.height/2;
76 
77         _left = static_cast<int>(_left/scale);
78         _top = static_cast<int>(_top/scale);
79 
80         _left += mViewSize.width/2;
81         _top += mViewSize.height/2;
82     }
83 
getScaleFactor() const84     float ScalingLayer::getScaleFactor() const
85     {
86         MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
87         float w = static_cast<float>(viewSize.width);
88         float h = static_cast<float>(viewSize.height);
89 
90         float heightScale = (h / mViewSize.height);
91         float widthScale = (w / mViewSize.width);
92         return std::min(widthScale, heightScale);
93     }
94 
getPosition(int _left,int _top) const95     MyGUI::IntPoint ScalingLayer::getPosition(int _left, int _top) const
96     {
97         screenToLayerCoords(_left, _top);
98         return MyGUI::IntPoint(_left, _top);
99     }
100 
renderToTarget(MyGUI::IRenderTarget * _target,bool _update)101     void ScalingLayer::renderToTarget(MyGUI::IRenderTarget *_target, bool _update)
102     {
103         MyGUI::IntSize globalViewSize = MyGUI::RenderManager::getInstance().getViewSize();
104         MyGUI::IntSize viewSize = globalViewSize;
105         float scale = getScaleFactor();
106         viewSize.width = static_cast<int>(viewSize.width / scale);
107         viewSize.height = static_cast<int>(viewSize.height / scale);
108 
109         float hoffset = (globalViewSize.width - mViewSize.width*getScaleFactor())/2.f / static_cast<float>(globalViewSize.width);
110         float voffset = (globalViewSize.height - mViewSize.height*getScaleFactor())/2.f / static_cast<float>(globalViewSize.height);
111 
112         ProxyRenderTarget proxy(_target, viewSize, hoffset, voffset);
113 
114         MyGUI::OverlappedLayer::renderToTarget(&proxy, _update);
115     }
116 
resizeView(const MyGUI::IntSize & _viewSize)117     void ScalingLayer::resizeView(const MyGUI::IntSize &_viewSize)
118     {
119         // do nothing
120     }
121 
deserialization(MyGUI::xml::ElementPtr _node,MyGUI::Version _version)122     void ScalingLayer::deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version)
123     {
124         MyGUI::OverlappedLayer::deserialization(_node, _version);
125 
126         MyGUI::xml::ElementEnumerator info = _node->getElementEnumerator();
127         while (info.next())
128         {
129             if (info->getName() == "Property")
130             {
131                 const std::string& key = info->findAttribute("key");
132                 const std::string& value = info->findAttribute("value");
133 
134                 if (key == "Size")
135                 {
136                     mViewSize = MyGUI::IntSize::parse(value);
137                 }
138             }
139         }
140     }
141 
142 }
143