Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / gui / ctrl_polygon.cpp
blob2adf96f52367d87b7d8e542048e3969b4489e63e
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 //
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/>.
21 #include "stdpch.h"
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;
29 #ifdef DEBUG_NEW
30 #define new DEBUG_NEW
31 #endif
33 namespace NLGUI
36 // *********************************************************************************
37 CCtrlPolygon::CCtrlPolygon( const TCtorParam &param ) : CCtrlBase( param )
39 // Construct
40 _Color = CRGBA::White;
41 //_Matrix = CMatrix::Identity;
42 _Valid = true;
45 // *********************************************************************************
46 void CCtrlPolygon::updateBoudingRect()
48 H_AUTO(Rz_CCtrlPolygon_updateBoudingRect)
49 if (_Poly.Vertices.empty())
51 setX(0);
52 setY(0);
53 setW(0);
54 setH(0);
55 return;
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));
74 setX(xmin);
75 setY(ymin);
76 setW(xmax - xmin);
77 setH(ymax - ymin);
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;
99 _Tris.clear();
100 std::list<CPolygon> polys;
101 bool splitDone = _Poly.toConvexPolygons(polys, NLMISC::CMatrix::Identity);
102 if (!splitDone)
104 polys.clear();
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());
110 _Tris.clear();
111 if (splitDone)
113 for(std::list<CPolygon>::iterator it = polys.begin(); it != polys.end(); ++it)
115 it->toTriFan(_Tris);
118 _Touched = true;
119 updateBoudingRect();
120 _Valid = splitDone;
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...
150 _Matrix = mat;
151 updateBoudingRect();
152 _Touched = true;
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();
163 if (_Touched)
165 _RealTris.clear();
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;*/
179 CVector2f result;
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
188 _RealTris.clear();
189 sint32 cx, cy, cw, ch;
190 vr.getClipWindow(cx, cy, cw, ch);
191 // per tri clip
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]);
203 else
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;
216 sint count = 3;
218 if ((sint32) minCorner.x < cx)
220 // clip left
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)
227 // clip right
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)
235 // clip bottom
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)
242 // clip top
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);
248 if (count >= 3)
250 for(uint k = 0; k < (uint) (count - 2); ++k)
252 _RealTris.push_back(NLMISC::CTriangle(pPos0[0], pPos0[k + 1], pPos0[k + 2]));
257 _Touched = false;
259 if (_RealTris.empty()) return;
260 CRGBA col;
261 if(getModulateGlobalColor())
263 col.modulateFromColor (_Color, CWidgetManager::getInstance()->getGlobalColorForContent());
265 else
267 col= _Color;
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();
278 updateBoudingRect();
279 // assume that clipping will have to be done again, real update of triangle will be done at render time
280 _Touched = true;
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)
294 return false;
297 // *********************************************************************************
298 // TMP TMP
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 // *********************************************************************************
306 // TMP TMP
307 void CCtrlPolygon::touch()
309 H_AUTO(Rz_CCtrlPolygon_touch)
310 updateBoudingRect();
311 _Touched = true;