1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "nel/gui/ctrl_polygon.h"
23 #include "nel/gui/widget_manager.h"
24 #include "nel/gui/view_renderer.h"
25 #include "nel/gui/interface_group.h"
27 using namespace NLMISC
;
36 // *********************************************************************************
37 CCtrlPolygon::CCtrlPolygon( const TCtorParam
¶m
) : CCtrlBase( param
)
40 _Color
= CRGBA::White
;
41 //_Matrix = CMatrix::Identity;
45 // *********************************************************************************
46 void CCtrlPolygon::updateBoudingRect()
48 H_AUTO(Rz_CCtrlPolygon_updateBoudingRect
)
49 if (_Poly
.Vertices
.empty())
58 sint32 xmin
= INT_MAX
;
59 sint32 ymin
= INT_MAX
;
60 sint32 xmax
= INT_MIN
;
61 sint32 ymax
= INT_MIN
;
62 uint numVerts
= (uint
)_Poly
.Vertices
.size();
63 _XFormPoly
.Vertices
.resize(numVerts
);
64 for(uint k
= 0; k
< numVerts
; ++k
)
66 CVector2f
&finalPos
= _XFormPoly
.Vertices
[k
];
67 //finalPos = _Matrix * _Poly.Vertices[k];
68 computeScaledVertex(finalPos
, CVector2f(_Poly
.Vertices
[k
].x
, _Poly
.Vertices
[k
].y
));
69 xmin
= std::min(xmin
, (sint32
) floorf(finalPos
.x
));
70 xmax
= std::max(xmax
, (sint32
) ceilf(finalPos
.x
));
71 ymin
= std::min(ymin
, (sint32
) floorf(finalPos
.y
));
72 ymax
= std::max(ymax
, (sint32
) ceilf(finalPos
.y
));
80 // *********************************************************************************
81 bool CCtrlPolygon::contains(const CVector2f
&pos
) const
83 H_AUTO(Rz_CCtrlPolygon_contains
)
84 if (!_Valid
) return false;
85 return _XFormPoly
.contains(pos
, false);
88 // *********************************************************************************
89 void CCtrlPolygon::setVertices(const std::vector
<NLMISC::CVector
> &vertices
)
91 H_AUTO(Rz_CCtrlPolygon_setVertices
)
92 if (vertices
.size() == _Poly
.Vertices
.size() &&
93 std::equal(vertices
.begin(), vertices
.end(), _Poly
.Vertices
.begin())) return; // remains unchanged
96 //TTicks startTime = CTime::getPerformanceTime();
98 _Poly
.Vertices
= vertices
;
100 std::list
<CPolygon
> polys
;
101 bool splitDone
= _Poly
.toConvexPolygons(polys
, NLMISC::CMatrix::Identity
);
105 // maybe wrong orientation
106 std::reverse(_Poly
.Vertices
.begin(), _Poly
.Vertices
.end());
107 splitDone
= _Poly
.toConvexPolygons(polys
, NLMISC::CMatrix::Identity
);
108 std::reverse(_Poly
.Vertices
.begin(), _Poly
.Vertices
.end());
113 for(std::list
<CPolygon
>::iterator it
= polys
.begin(); it
!= polys
.end(); ++it
)
122 //TTicks endTime = CTime::getPerformanceTime();
123 //nlinfo("%d ms for CCtrlPolygon::setVertices", (int) (1000 * CTime::ticksToSecond(endTime - startTime)));
127 static inline bool totallyInside(const CVector
&minCorner
, const CVector
&maxCorner
, sint32 cx
, sint32 cy
, sint32 cw
, sint32 ch
)
129 return (sint32
) maxCorner
.x
< (cx
+ cw
) &&
130 (sint32
) minCorner
.x
>= cx
&&
131 (sint32
) maxCorner
.y
< (cy
+ ch
) &&
132 (sint32
) minCorner
.y
>= cy
;
135 static inline bool totallyOutside(const CVector
&minCorner
, const CVector
&maxCorner
, sint32 cx
, sint32 cy
, sint32 cw
, sint32 ch
)
137 return (sint32
) minCorner
.x
>= (cx
+ cw
) ||
138 (sint32
) maxCorner
.x
< cx
||
139 (sint32
) minCorner
.y
>= (cy
+ ch
) ||
140 (sint32
) maxCorner
.y
< cy
;
144 // *********************************************************************************
145 /*void CCtrlPolygon::setMatrix(const NLMISC::CMatrix &mat)
147 const float *lhs = mat.get();
148 const float *rhs = _Matrix.get();
149 if (std::equal(lhs, lhs + 16, rhs)) return; // unmodified...
156 // *********************************************************************************
157 void CCtrlPolygon::draw()
159 H_AUTO(Rz_CCtrlPolygon_draw
)
160 if (_Tris
.empty()) return;
161 if (!_Parent
) return;
162 CViewRenderer
&vr
= *CViewRenderer::getInstance();
166 uint numTris
= (uint
)_Tris
.size();
167 sint32 cornerX
, cornerY
;
168 static std::vector
<NLMISC::CTriangle
> winTris
;
169 winTris
.resize(numTris
);
170 _Parent
->getCorner(cornerX
, cornerY
, _ParentPosRef
);
171 /*CMatrix m = _Matrix;
172 m.setPos(m.getPos() + CVector((float) cornerX, (float) cornerY, 0.f));*/
173 for(uint k
= 0; k
< numTris
; ++k
)
175 /*winTris[k].V0 = m * _Tris[k].V0;
176 winTris[k].V1 = m * _Tris[k].V1;
177 winTris[k].V2 = m * _Tris[k].V2;*/
180 computeScaledVertex(result
, _Tris
[k
].V0
);
181 winTris
[k
].V0
.set(result
.x
+ cornerX
, result
.y
+ cornerY
, 0.f
);
182 computeScaledVertex(result
, _Tris
[k
].V1
);
183 winTris
[k
].V1
.set(result
.x
+ cornerX
, result
.y
+ cornerY
, 0.f
);
184 computeScaledVertex(result
, _Tris
[k
].V2
);
185 winTris
[k
].V2
.set(result
.x
+ cornerX
, result
.y
+ cornerY
, 0.f
);
187 // recompute & reclip poly
189 sint32 cx
, cy
, cw
, ch
;
190 vr
.getClipWindow(cx
, cy
, cw
, ch
);
192 NLMISC::CVector minCorner
;
193 NLMISC::CVector maxCorner
;
194 for(uint k
= 0; k
< numTris
; ++k
)
196 winTris
[k
].getMinCorner(minCorner
);
197 winTris
[k
].getMaxCorner(maxCorner
);
198 if (totallyOutside(minCorner
, maxCorner
, cx
, cy
, cw
, ch
)) continue;
199 if (totallyInside(minCorner
, maxCorner
, cx
, cy
, cw
, ch
))
201 _RealTris
.push_back(winTris
[k
]);
205 const uint maxNumCorners
= 8;
206 static CVector outPos0
[maxNumCorners
];
207 static CVector outPos1
[maxNumCorners
];
209 outPos0
[0] = winTris
[k
].V0
;
210 outPos0
[1] = winTris
[k
].V1
;
211 outPos0
[2] = winTris
[k
].V2
;
213 CVector
*pPos0
= outPos0
;
214 CVector
*pPos1
= outPos1
;
218 if ((sint32
) minCorner
.x
< cx
)
221 CPlane
clipper(-1.f
, 0.f
, 0.f
, (float) cx
);
222 count
= clipper
.clipPolygonBack(pPos0
, pPos1
, count
);
223 std::swap(pPos0
, pPos1
);
225 if ((sint32
) maxCorner
.x
> cx
+ cw
)
228 CPlane
clipper(1.f
, 0.f
, 0.f
, - (float) (cx
+ cw
));
229 count
= clipper
.clipPolygonBack(pPos0
, pPos1
, count
);
230 std::swap(pPos0
, pPos1
);
233 if ((sint32
) minCorner
.y
< cy
)
236 CPlane
clipper(0.f
, -1.f
, 0.f
, (float) cy
);
237 count
= clipper
.clipPolygonBack(pPos0
, pPos1
, count
);
238 std::swap(pPos0
, pPos1
);
240 if ((sint32
) maxCorner
.y
> cy
+ ch
)
243 CPlane
clipper(0.f
, 1.f
, 0.f
, - (float) (cy
+ ch
));
244 count
= clipper
.clipPolygonBack(pPos0
, pPos1
, count
);
245 std::swap(pPos0
, pPos1
);
247 nlassert(count
<= 8);
250 for(uint k
= 0; k
< (uint
) (count
- 2); ++k
)
252 _RealTris
.push_back(NLMISC::CTriangle(pPos0
[0], pPos0
[k
+ 1], pPos0
[k
+ 2]));
259 if (_RealTris
.empty()) return;
261 if(getModulateGlobalColor())
263 col
.modulateFromColor (_Color
, CWidgetManager::getInstance()->getGlobalColorForContent());
268 col
.A
= (uint8
)(((sint32
)col
.A
*((sint32
)CWidgetManager::getInstance()->getGlobalColorForContent().A
+1))>>8);
270 vr
.drawUnclippedTriangles(_RenderLayer
, _RealTris
, col
);
273 // *********************************************************************************
274 void CCtrlPolygon::updateCoords()
276 H_AUTO(Rz_CCtrlPolygon_updateCoords
)
277 CCtrlBase::updateCoords();
279 // assume that clipping will have to be done again, real update of triangle will be done at render time
283 // *********************************************************************************
284 void CCtrlPolygon::setAlpha(sint32 a
)
286 H_AUTO(Rz_CCtrlPolygon_setAlpha
)
287 _Color
.A
= (uint8
) a
;
290 // *********************************************************************************
291 bool CCtrlPolygon::handleEvent(const NLGUI::CEventDescriptor
&/* event */)
293 H_AUTO(Rz_CCtrlPolygon_handleEvent
)
297 // *********************************************************************************
299 void CCtrlPolygon::computeScaledVertex(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
)
301 H_AUTO(Rz_CCtrlPolygon_computeScaledVertex
)
302 dest
.set(src
.x
, src
.y
);
305 // *********************************************************************************
307 void CCtrlPolygon::touch()
309 H_AUTO(Rz_CCtrlPolygon_touch
)