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_quad.h"
23 #include "nel/gui/interface_group.h"
24 #include "nel/gui/widget_manager.h"
25 #include "nel/misc/polygon.h"
27 using namespace NLMISC
;
36 // *********************************************************************************
37 CCtrlQuad::CCtrlQuad( const TCtorParam
¶m
) : CCtrlBase( param
), _Color(CRGBA::White
),
44 setQuad(CQuad(CVector::Null
, CVector::Null
, CVector::Null
, CVector::Null
));
45 // preset uvs for real quad
46 _RealQuad
.Uv0
.set(0.f
, 0.f
);
47 _RealQuad
.Uv1
.set(1.f
, 0.f
);
48 _RealQuad
.Uv2
.set(1.f
, 1.f
);
49 _RealQuad
.Uv3
.set(0.f
, 1.f
);
52 // *********************************************************************************
53 bool CCtrlQuad::parse(xmlNodePtr
/* cur */, CInterfaceGroup
* /* parentGroup */)
55 nlassert(0); // NOT IMPLEMENTED (only created dynamically at this time)
59 // *********************************************************************************
60 void CCtrlQuad::updateCoords()
62 H_AUTO(Rz_CCtrlQuad_updateCoords
)
63 CViewBase::updateCoords();
65 // don't use _XReal && _YReal, because coords are given relative to parent
66 CVector
delta((float) _Parent
->getXReal(), (float) _Parent
->getYReal(), 0.f
);
67 _RealQuad
.set(_Quad
.V0
+ delta
, _Quad
.V1
+ delta
, _Quad
.V2
+ delta
, _Quad
.V3
+ delta
);
70 // *********************************************************************************
71 void CCtrlQuad::draw()
73 H_AUTO(Rz_CCtrlQuad_draw
)
75 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
78 if(getModulateGlobalColor())
80 col
.modulateFromColor (_Color
, CWidgetManager::getInstance()->getGlobalColorForContent());
85 col
.A
= (uint8
)(((sint32
)col
.A
*((sint32
)CWidgetManager::getInstance()->getGlobalColorForContent().A
+1))>>8);
88 /*if (_InheritGCAlpha)
90 // search a parent container
91 CInterfaceGroup *gr = getParent();
94 if (gr->isGroupContainer())
96 CGroupContainer *gc = static_cast<CGroupContainer *>(gr);
97 col.A = (uint8)(((sint32)col.A*((sint32)gc->getCurrentContainerAlpha()+1))>>8);
100 gr = gr->getParent();
103 if (_UMin
== 0.f
&& _UMax
== 1.f
&& _WrapMode
!= CustomUVs
)
105 // no pattern applied, can draw the quad in a single piece
106 rVR
.drawQuad(_RenderLayer
, _RealQuad
, _TextureId
, col
, _Additif
, _Filtered
);
111 if (_WrapMode
== Repeat
)
115 (CQuad
&) quv
= _RealQuad
; // copy CQuad part
116 float u
= fmodf(_UMin
, 1.f
);
121 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
125 // reverse corners if needed to handle case where _UVMin < _UVmax
126 NLMISC::CQuad srcQuad
;
132 srcQuad
.V0
= _RealQuad
.V1
;
133 srcQuad
.V1
= _RealQuad
.V0
;
134 srcQuad
.V2
= _RealQuad
.V3
;
135 srcQuad
.V3
= _RealQuad
.V2
;
145 float unitRatio
= 1.f
/ fabsf(umax
- umin
); // ratio of the real quad delta x in screen for du = 1
146 // texture is stretched, mutiple parts needed
147 float ceilUMin
= ceilf(umin
);
148 float firstDeltaU
= ceilUMin
- umin
;
149 if (firstDeltaU
!= 0.f
)
154 quv
.V1
= blend(srcQuad
.V0
, srcQuad
.V1
, std::min(1.f
, (firstDeltaU
* unitRatio
)));
155 quv
.V2
= blend(srcQuad
.V3
, srcQuad
.V2
, std::min(1.f
, (firstDeltaU
* unitRatio
)));
157 float lastU
= std::min(umax
+ 1.f
- ceilUMin
, 1.f
);
158 quv
.Uv0
.set(1.f
- firstDeltaU
, 0.f
);
159 quv
.Uv1
.set(lastU
, 0.f
);
160 quv
.Uv2
.set(lastU
, 1.f
);
161 quv
.Uv3
.set(1.f
- firstDeltaU
, 1.f
);
162 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
164 if (firstDeltaU
* unitRatio
>= 1.f
) return;
167 // TODO optim: reuse of previous uv & pos ... (prb is that they are not always computed)
169 // intermediate quads
170 sint numQuads
= (sint
) (floorf(umax
) - ceilf(umin
));
172 for(sint k
= 0; k
< numQuads
; ++k
)
174 float deltaU
= firstDeltaU
+ k
;
176 quv
.V0
= blend(srcQuad
.V0
, srcQuad
.V1
, deltaU
* unitRatio
);
177 quv
.V1
= blend(srcQuad
.V0
, srcQuad
.V1
, (deltaU
+ 1.f
) * unitRatio
);
178 quv
.V2
= blend(srcQuad
.V3
, srcQuad
.V2
, (deltaU
+ 1.f
) * unitRatio
);
179 quv
.V3
= blend(srcQuad
.V3
, srcQuad
.V2
, deltaU
* unitRatio
);
180 quv
.Uv0
.set(0.f
, 0.f
);
181 quv
.Uv1
.set(1.f
, 0.f
);
182 quv
.Uv2
.set(1.f
, 1.f
);
183 quv
.Uv3
.set(0.f
, 1.f
);
184 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
187 float lastDeltaU
= umax
- floorf(umax
);
188 if (lastDeltaU
!= 0.f
)
192 quv
.V0
= blend(srcQuad
.V1
, srcQuad
.V0
, lastDeltaU
* unitRatio
);
195 quv
.V3
= blend(srcQuad
.V2
, srcQuad
.V3
, lastDeltaU
* unitRatio
);
196 quv
.Uv0
.set(0.f
, 0.f
);
197 quv
.Uv1
.set(lastDeltaU
, 0.f
);
198 quv
.Uv2
.set(lastDeltaU
, 1.f
);
199 quv
.Uv3
.set(0.f
, 1.f
);
200 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
205 else if (_WrapMode
== Clamp
)
209 (CQuad
&) quv
= _RealQuad
; // copy CQuad part
217 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
221 NLMISC::CQuad srcQuad
;
227 srcQuad
.V0
= _RealQuad
.V1
;
228 srcQuad
.V1
= _RealQuad
.V0
;
229 srcQuad
.V2
= _RealQuad
.V3
;
230 srcQuad
.V3
= _RealQuad
.V2
;
238 float startRatio
= - umin
/ (umax
- umin
); // start of unclamped u (actually (0.f - umin) / (umax - umin) )
242 quv
.V1
= blend(srcQuad
.V0
, srcQuad
.V1
, std::min(1.f
,startRatio
));
243 quv
.V2
= blend(srcQuad
.V3
, srcQuad
.V2
, std::min(1.f
,startRatio
));
245 // draw first clamped part
246 quv
.Uv0
.set(0.f
, 0.f
);
247 quv
.Uv1
.set(0.f
, 0.f
);
248 quv
.Uv2
.set(0.f
, 1.f
);
249 quv
.Uv3
.set(0.f
, 1.f
);
250 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
252 if (startRatio
>= 1.f
) return;
253 float endRatio
= (1.f
- umin
) / (umax
- umin
);
256 // draw middle part if visible
257 // TODO optim: reuse of previous uv & pos ... (prb is that they are not always computed)
258 quv
.V0
= blend(srcQuad
.V0
, srcQuad
.V1
, std::max(0.f
, startRatio
));
259 quv
.V1
= blend(srcQuad
.V0
, srcQuad
.V1
, std::min(1.f
, endRatio
));
260 quv
.V2
= blend(srcQuad
.V3
, srcQuad
.V2
, std::min(1.f
, endRatio
));
261 quv
.V3
= blend(srcQuad
.V3
, srcQuad
.V2
, std::max(0.f
, startRatio
));
262 // draw first clamped part
263 quv
.Uv0
.set(std::max(0.f
, umin
), 0.f
);
264 quv
.Uv1
.set(std::min(1.f
, umax
), 0.f
);
265 quv
.Uv2
.set(std::min(1.f
, umax
), 1.f
);
266 quv
.Uv3
.set(std::max(0.f
, umin
), 1.f
);
267 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
269 if (endRatio
>= 1.f
) return;
271 quv
.V0
= blend(srcQuad
.V0
, srcQuad
.V1
, std::max(0.f
, endRatio
));
274 quv
.V3
= blend(srcQuad
.V3
, srcQuad
.V2
, std::max(0.f
, endRatio
));
275 // draw end clamped part
276 quv
.Uv0
.set(1.f
, 0.f
);
277 quv
.Uv1
.set(1.f
, 0.f
);
278 quv
.Uv2
.set(1.f
, 1.f
);
279 quv
.Uv3
.set(1.f
, 1.f
);
280 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
285 nlassert(_WrapMode
== CustomUVs
);
286 quv
.V0
= _RealQuad
.V0
;
287 quv
.V1
= _RealQuad
.V1
;
288 quv
.V2
= _RealQuad
.V2
;
289 quv
.V3
= _RealQuad
.V3
;
290 quv
.Uv0
= _CustomUVs
[0];
291 quv
.Uv1
= _CustomUVs
[1];
292 quv
.Uv2
= _CustomUVs
[2];
293 quv
.Uv3
= _CustomUVs
[3];
294 rVR
.drawQuad(_RenderLayer
, quv
, _TextureId
, col
, _Additif
, _Filtered
);
299 // *********************************************************************************
300 void CCtrlQuad::setAlpha(sint32 a
)
302 H_AUTO(Rz_CCtrlQuad_setAlpha
)
303 _Color
.A
= (uint8
) a
;
306 // *********************************************************************************
307 void CCtrlQuad::setTexture(const std::string
&texName
)
309 H_AUTO(Rz_CCtrlQuad_setTexture
)
310 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
311 // CViewRenderer &rVR = *CViewRenderer::getInstance();
312 _TextureId
.setTexture(texName
.c_str());
315 // *********************************************************************************
316 std::string
CCtrlQuad::getTexture() const
318 H_AUTO(Rz_CCtrlQuad_getTexture
)
319 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
320 return rVR
.getTextureNameFromId (_TextureId
);
323 // *********************************************************************************
324 void CCtrlQuad::setQuad(const CQuad
&quad
)
326 H_AUTO(Rz_CCtrlQuad_setQuad
)
327 float qXMin
= minof(quad
.V0
.x
, quad
.V1
.x
, quad
.V2
.x
, quad
.V3
.x
);
328 float qXMax
= maxof(quad
.V0
.x
, quad
.V1
.x
, quad
.V2
.x
, quad
.V3
.x
);
329 float qYMin
= minof(quad
.V0
.y
, quad
.V1
.y
, quad
.V2
.y
, quad
.V3
.y
);
330 float qYMax
= maxof(quad
.V0
.y
, quad
.V1
.y
, quad
.V2
.y
, quad
.V3
.y
);
331 setPosRef(Hotspot_BL
);
332 setX((sint32
) floorf(qXMin
));
333 setY((sint32
) floorf(qYMin
));
334 setW((sint32
) ceilf(qXMax
) - getX());
335 setH((sint32
) ceilf(qYMax
) - getY());
339 // *********************************************************************************
340 void CCtrlQuad::setQuad(const NLMISC::CVector
&start
, const NLMISC::CVector
&end
, float thickness
)
342 H_AUTO(Rz_CCtrlQuad_setQuad
)
343 CVector right
= end
- start
;
344 CVector
up(-right
.y
, right
.x
, 0.f
);
345 up
= thickness
* up
.normed();
346 setQuad(CQuad(start
+ up
, end
+ up
, end
- up
, start
- up
));
349 // *********************************************************************************
350 void CCtrlQuad::setQuad(const NLMISC::CVector
&pos
, float radius
, float angle
/*=0.f*/)
352 H_AUTO(Rz_CCtrlQuad_setQuad
)
355 setQuad(pos
- radius
* CVector::I
, pos
+ radius
* CVector::I
, radius
);
359 CVector
right(radius
* cosf(angle
), radius
* sinf(angle
), 0.f
);
360 setQuad(pos
- right
, pos
+ right
, radius
);
364 // *********************************************************************************
365 void CCtrlQuad::setQuad(const std::string
&texName
, const NLMISC::CVector
&srcPos
, float angle
/*= 0.f*/, float offCenter
/* = 0.f*/)
367 H_AUTO(Rz_CCtrlQuad_setQuad
)
368 NLMISC::CVector pos
= srcPos
;
369 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
371 rVR
.getTextureSizeFromId(rVR
.getTextureIdFromName(texName
), w
, h
);
374 if (offCenter
!= 0.f
)
378 setQuad(pos
- 0.5f
* w
* CVector::I
, pos
+ 0.5f
* w
* CVector::I
, 0.5f
* h
);
382 CVector
unitRadius(cosf(angle
), sinf(angle
), 0.f
);
383 CVector radius
= 0.5f
* w
* unitRadius
;
384 pos
+= offCenter
* unitRadius
;
385 setQuad(pos
- radius
, pos
+ radius
, 0.5f
* h
);
389 // *********************************************************************************
390 void CCtrlQuad::setAdditif(bool additif
)
392 H_AUTO(Rz_CCtrlQuad_setAdditif
)
396 // *********************************************************************************
397 void CCtrlQuad::setFiltered(bool filtered
)
399 H_AUTO(Rz_CCtrlQuad_setFiltered
)
400 _Filtered
= filtered
;
403 // *********************************************************************************
404 void CCtrlQuad::setPattern(float umin
, float umax
, TWrapMode wrapMode
)
406 H_AUTO(Rz_CCtrlQuad_setPattern
)
407 nlassert((uint
) wrapMode
< CustomUVs
);
410 _WrapMode
= wrapMode
;
413 // *********************************************************************************
414 void CCtrlQuad::setCustomUVs(const CUV uvs
[4])
416 H_AUTO(Rz_CCtrlQuad_setCustomUVs
)
417 std::copy(uvs
, uvs
+ 4, _CustomUVs
);
418 _WrapMode
= CustomUVs
;
421 // *********************************************************************************
422 bool CCtrlQuad::handleEvent(const NLGUI::CEventDescriptor
&/* event */)
424 H_AUTO(Rz_CCtrlQuad_handleEvent
)
428 // *********************************************************************************
429 bool CCtrlQuad::contains(const NLMISC::CVector2f
&pos
) const
431 H_AUTO(Rz_CCtrlQuad_contains
)
432 static NLMISC::CPolygon2D poly
;
433 poly
.Vertices
.resize(4);
434 poly
.Vertices
[0] = _Quad
.V0
;
435 poly
.Vertices
[1] = _Quad
.V1
;
436 poly
.Vertices
[2] = _Quad
.V2
;
437 poly
.Vertices
[3] = _Quad
.V3
;
438 return poly
.contains(pos
, false);