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>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "prim_render.h"
24 #include "r2_config.h"
26 #include "nel/misc/vector_2f.h"
27 #include "nel/misc/time_nl.h"
29 #include "nel/gui/view_bitmap.h"
30 #include "nel/gui/ctrl_quad.h"
31 #include "nel/gui/ctrl_polygon.h"
32 #include "../interface_v3/interface_manager.h"
33 #include "nel/gui/view_renderer.h"
34 #include "../interface_v3/group_map.h"
41 using namespace NLMISC
;
46 // helper function for lua init
47 void readFromLua(const CLuaObject
&table
, const char *key
, float &dest
)
49 if (table
[key
].isNumber()) dest
= (float) table
[key
].toNumber();
51 void readFromLua(const CLuaObject
&table
, const char *key
, uint
&dest
)
53 if (table
[key
].isInteger()) dest
= (uint
) table
[key
].toInteger();
55 void readFromLua(const CLuaObject
&table
, const char *key
, std::string
&dest
)
57 if (table
[key
].isString()) dest
= table
[key
].toString();
60 void readFromLua(const CLuaObject
&table
, const char *key
, CStringShared
&dest
)
62 if (table
[key
].isString()) dest
= table
[key
].toString();
65 void readFromLua(const CLuaObject
&table
, const char *key
, bool &dest
)
67 if (table
[key
].isBoolean()) dest
= table
[key
].toBoolean();
69 void readFromLua(const CLuaObject
&table
, const char *key
, CRGBA
&dest
)
71 if (table
[key
].isRGBA()) dest
= table
[key
].toRGBA();
74 #define READ_FROM_LUA(dest) readFromLua(params, #dest, dest);
76 // *********************************************************
77 void CVertexLook::init(const CLuaObject
¶ms
)
79 //H_AUTO(R2_CVertexLook_init)
80 READ_FROM_LUA(DecalTexture
);
81 READ_FROM_LUA(DecalSize
);
82 READ_FROM_LUA(DecalColor
);
83 READ_FROM_LUA(DecalDistToEdgeDecal
);
84 READ_FROM_LUA(WorldMapTexture
);
85 READ_FROM_LUA(WorldMapColor
);
89 // *********************************************************
90 void CEdgeLook::init(const CLuaObject
¶ms
)
92 //H_AUTO(R2_CEdgeLook_init)
93 READ_FROM_LUA(ShapeName
);
94 READ_FROM_LUA(ShapeScale
);
95 READ_FROM_LUA(DecalTexture
);
96 READ_FROM_LUA(DecalUScale
);
97 READ_FROM_LUA(DecalWidth
);
98 READ_FROM_LUA(DecalColor
);
99 READ_FROM_LUA(DecalFiltered
);
100 READ_FROM_LUA(WorldMapTexture
);
101 READ_FROM_LUA(WorldMapWidth
);
102 READ_FROM_LUA(WorldMapColor
);
103 READ_FROM_LUA(WorldMapUScale
);
104 READ_FROM_LUA(WorldMapFiltered
);
105 uint decalWrapMode
= Repeat
;
106 readFromLua(params
, "DecalWrapMode", decalWrapMode
);
107 if (decalWrapMode
< WrapModeCount
) DecalWrapMode
= (TWrapMode
) decalWrapMode
;
108 uint worldMapWrapMode
= Scaled
;
109 readFromLua(params
, "WorldMapWrapMode", worldMapWrapMode
);
110 if (worldMapWrapMode
< WrapModeCount
) WorldMapWrapMode
= (TWrapMode
) worldMapWrapMode
;
113 // *********************************************************
114 bool operator ==(const CPrimLook
&lhs
, const CPrimLook
&rhs
)
116 return lhs
.Shape
== rhs
.Shape
&&
117 lhs
.VertexShapeName
== rhs
.VertexShapeName
&&
118 lhs
.VertexShapeScale
== rhs
.VertexShapeScale
&&
119 lhs
.VertexLook
== rhs
.VertexLook
&&
120 lhs
.FirstVertexLook
== rhs
.FirstVertexLook
&&
121 lhs
.EdgeLook
== rhs
.EdgeLook
&&
122 lhs
.LastEdgeIsValid
== rhs
.LastEdgeIsValid
&&
123 lhs
.ClipDownFacing
== rhs
.ClipDownFacing
;
127 // *********************************************************
128 void CPrimLook::init(const CLuaObject
¶ms
)
130 //H_AUTO(R2_CPrimLook_init)
131 if (!params
.isTable())
133 nlwarning("<CPrimLook::init> parameters are not a table");
137 READ_FROM_LUA(VertexShapeName
);
138 READ_FROM_LUA(VertexShapeScale
);
139 VertexLook
.init(params
["VertexLook"]);
140 if (!params
["FirstVertexLook"].isNil())
142 FirstVertexLook
.init(params
["FirstVertexLook"]);
146 FirstVertexLook
= VertexLook
;
148 EdgeLook
.init(params
["EdgeLook"]);
149 READ_FROM_LUA(LastEdgeIsValid
);
150 READ_FROM_LUA(ClipDownFacing
);
153 readFromLua(params
, "Shape", shape
);
154 if (shape
< ShapeCount
) Shape
= (TShape
) shape
;
158 // *********************************************************
159 void CPrimRender::setLook(const CPrimLook
&look
)
161 //H_AUTO(R2_CPrimRender_setLook)
162 if (look
== _Look
) return;
164 if (!look
.EdgeLook
.WorldMapTexture
.empty())
166 CInterfaceManager
*im
= CInterfaceManager::getInstance();
167 CViewRenderer
&vr
= *CViewRenderer::getInstance();
168 sint32 width
, height
;
169 sint32 id
= vr
.getTextureIdFromName(look
.EdgeLook
.WorldMapTexture
);
170 vr
.getTextureSizeFromId(id
, width
, height
);
171 _InvWorldTextureWidth
= width
> 0 ? 1.f
/ width
: 0.f
;
176 // *********************************************************
177 CPrimRender::~CPrimRender()
179 if (_AddedToWorldMap
)
181 CGroupMap
*gm
= CTool::getWorldMap();
187 nlassert(_WorldMapVertices
.empty());
188 nlassert(_WorldMapEdges
.empty());
192 // *********************************************************
193 CCtrlPolygon
*CPrimRender::newCtrlPolygon() const
195 //H_AUTO(R2_CPrimRender_newCtrlPolygon)
196 class CCtrlMapPolygon
: public CCtrlPolygon
199 CCtrlMapPolygon( CViewBase::TCtorParam
¶m
) : CCtrlPolygon( param
){}
202 void computeScaledVertex(NLMISC::CVector2f
&dest
, const NLMISC::CVector2f
&src
)
204 CGroupMap
*gm
= CTool::getWorldMap();
205 if (!gm
) dest
= CVector::Null
;
206 else gm
->worldToWindow(dest
, src
);
209 CViewBase::TCtorParam param
;
210 return new CCtrlMapPolygon( param
);
213 // *********************************************************
214 CCtrlQuad
*CPrimRender::newCtrlQuad(uint
/* edgeIndex */) const
216 //H_AUTO(R2_CPrimRender_newCtrlQuad)
217 CViewBase::TCtorParam param
;
218 return new CCtrlQuad( param
);
221 // *********************************************************
222 bool CPrimRender::contains(const NLMISC::CVector2f
&pos
) const
224 //H_AUTO(R2_CPrimRender_contains)
225 for(uint k
= 0; k
< _VertexDecals
.size(); ++k
)
227 if (_VertexDecals
[k
]->contains(pos
)) return true;
229 for(uint k
= 0; k
< _EdgeDecals
.size(); ++k
)
231 if (_EdgeDecals
[k
]->contains(pos
)) return true;
236 // *********************************************************
237 sint
CPrimRender::isOnEdge(const NLMISC::CVector2f
&pos
) const
239 //H_AUTO(R2_CPrimRender_isOnEdge)
240 for(uint k
= 0; k
< _EdgeDecals
.size(); ++k
)
242 if (_EdgeDecals
[k
]->contains(pos
)) return (sint
) k
;
247 // *********************************************************
248 CPrimRender::CPrimRender()
250 _Emissive
= CRGBA::Black
;
252 _AddedToWorldMap
= false;
253 _WorldMapPoly
= NULL
;
254 _InvWorldTextureWidth
= 0.f
;
258 // *********************************************************
259 void CPrimRender::clear()
261 //H_AUTO(R2_CPrimRender_clear)
262 setVertices(std::vector
<NLMISC::CVector
>());
265 // *********************************************************
266 void CPrimRender::setVertices(const std::vector
<NLMISC::CVector
> &vertices
)
268 //H_AUTO(R2_CPrimRender_setVertices)
269 if (_Vertices
.size() == vertices
.size())
271 if (std::equal(vertices
.begin(), vertices
.end(), _Vertices
.begin()))
277 _Vertices
= vertices
;
282 _Vertices
= vertices
;
286 // *********************************************************
287 void CPrimRender::setVertices(const std::vector
<NLMISC::CVector2f
> &vertices
)
289 //H_AUTO(R2_CPrimRender_setVertices)
290 std::vector
<CVector
> vertices3D(vertices
.size());
291 for(uint k
= 0; k
< vertices
.size(); ++k
)
293 vertices3D
[k
] = vertices
[k
];
295 setVertices(vertices3D
);
298 // *********************************************************
299 void CPrimRender::setCustomWorldMapEdgeUVMatrix(bool on
, const NLMISC::CMatrix
&matrix
)
301 //H_AUTO(R2_CPrimRender_setCustomWorldMapEdgeUVMatrix)
302 if (_CustomWorldMapEdgeUVMatrix
.set(on
, matrix
))
308 // *********************************************************
309 void CPrimRender::setCustomDecalEdgeUVMatrix(bool on
, const NLMISC::CMatrix
&matrix
)
311 //H_AUTO(R2_CPrimRender_setCustomDecalEdgeUVMatrix)
312 if (_CustomDecalEdgeUVMatrix
.set(on
, matrix
))
318 // *********************************************************
319 void CPrimRender::setEmissive(NLMISC::CRGBA color
)
321 //H_AUTO(R2_CPrimRender_setEmissive)
322 if (color
== _Emissive
) return;
323 forceSetEmissive(color
);
326 // *********************************************************
327 void CPrimRender::forceSetEmissive(NLMISC::CRGBA emissive
)
329 //H_AUTO(R2_CPrimRender_forceSetEmissive)
330 _Emissive
= emissive
;
331 _VertexShapeInstances
.setEmissive(emissive
);
332 _EdgeShapeInstances
.setEmissive(emissive
);
333 for(uint k
= 0; k
< _VertexDecals
.size(); ++k
)
335 _VertexDecals
[k
]->setEmissive(emissive
);
337 for(uint k
= 0; k
< _EdgeDecals
.size(); ++k
)
339 _EdgeDecals
[k
]->setEmissive(emissive
);
343 // *********************************************************
344 void CPrimRender::update()
346 //H_AUTO(R2_CPrimRender_update)
352 _VertexShapeInstances
.clear();
353 if (!_Look
.VertexShapeName
.empty())
355 _VertexShapeInstances
.setShapeName(_Look
.VertexShapeName
);
356 _VertexShapeInstances
.resize((uint
)_Vertices
.size());
360 _VertexShapeInstances
.clear();
363 _VertexDecals
.clear();
364 if (!_Look
.VertexLook
.DecalTexture
.empty())
366 _VertexDecals
.resize(_Vertices
.size());
367 for(uint k
= 0; k
< _Vertices
.size(); ++k
)
369 _VertexDecals
[k
] = new CDecal
;
370 _VertexDecals
[k
]->setClipDownFacing(_Look
.ClipDownFacing
);
371 if (k
== 0 && !_Look
.FirstVertexLook
.DecalTexture
.empty())
373 _VertexDecals
[k
]->setTexture(_Look
.FirstVertexLook
.DecalTexture
, true);
374 _VertexDecals
[k
]->setDiffuse(_Look
.FirstVertexLook
.DecalColor
);
378 _VertexDecals
[k
]->setTexture(_Look
.VertexLook
.DecalTexture
);
379 _VertexDecals
[k
]->setDiffuse(_Look
.VertexLook
.DecalColor
);
386 case CPrimLook::Star
:
387 _NumEdges
= _Vertices
.size() <= 1 ? 0 : (sint
)_Vertices
.size() - 1;
389 case CPrimLook::PolyLine
:
390 _NumEdges
= _Vertices
.size() <= 1 ? 0 : (sint
)_Vertices
.size() - 1;
391 if (!_Look
.LastEdgeIsValid
&& _NumEdges
!= 0) -- _NumEdges
;
393 case CPrimLook::ClosedPolyLine
:
394 _NumEdges
= _Vertices
.size() >= 3 ? (sint
)_Vertices
.size() : std::max((sint
) 0, (sint
) (_Vertices
.size() - 1));
395 if (!_Look
.LastEdgeIsValid
&& _NumEdges
!= 0) -- _NumEdges
;
402 nlassert(_NumEdges
>= 0);
404 _EdgeShapeInstances
.clear();
405 if (!_Look
.EdgeLook
.ShapeName
.empty())
407 _EdgeShapeInstances
.setShapeName(_Look
.EdgeLook
.ShapeName
);
408 _EdgeShapeInstances
.resize(_NumEdges
);
412 _EdgeShapeInstances
.clear();
416 if (!_Look
.EdgeLook
.DecalTexture
.empty())
418 _EdgeDecals
.resize(_NumEdges
);
419 for(sint k
= 0; k
< _NumEdges
; ++k
)
421 _EdgeDecals
[k
] = new CDecal
;
422 _EdgeDecals
[k
]->setClipDownFacing(_Look
.ClipDownFacing
);
423 _EdgeDecals
[k
]->setTexture(_Look
.EdgeLook
.DecalTexture
, _Look
.EdgeLook
.DecalWrapMode
== CEdgeLook::Centered
, true, _Look
.EdgeLook
.DecalFiltered
);
424 _EdgeDecals
[k
]->setDiffuse(_Look
.EdgeLook
.DecalColor
);
425 _EdgeDecals
[k
]->setCustomUVMatrix(_CustomDecalEdgeUVMatrix
.On
, _CustomDecalEdgeUVMatrix
.Matrix
);
433 forceSetEmissive(_Emissive
);
436 TTime endTime = CTime::getLocalTime();
437 nlinfo("%.2f seconds for : CPrimRender::update", (endTime - _StartTime) / 1000.f);
442 // *********************************************************
443 void CPrimRender::updatePos()
445 //H_AUTO(R2_CPrimRender_updatePos)
447 if (_AddedToWorldMap
)
449 setWorldMapNumVertices(_Look
.VertexLook
.WorldMapTexture
.empty() ? 0 : (uint
)_Vertices
.size());
450 setWorldMapNumEdges(_Look
.EdgeLook
.WorldMapTexture
.empty() ? 0 : _NumEdges
);
453 if (!_Vertices
.empty())
458 case CPrimLook::Star
:
460 CVector centerPos
= _Vertices
[0];
461 for(uint k
= 1; k
< _Vertices
.size(); ++k
)
464 if (!_EdgeShapeInstances
.empty())
466 updateEdge(_EdgeShapeInstances
[k
- 1], centerPos
, _Vertices
[k
]);
468 if (!_EdgeDecals
.empty())
470 updateEdgeDecal(*(_EdgeDecals
[k
- 1]), centerPos
, _Vertices
[k
], _Look
.FirstVertexLook
.DecalDistToEdgeDecal
, _Look
.VertexLook
.DecalDistToEdgeDecal
);
475 case CPrimLook::PolyLine
:
476 case CPrimLook::ClosedPolyLine
:
478 for(sint k
= 0; k
< _NumEdges
; ++k
)
481 if (!_EdgeShapeInstances
.empty())
483 updateEdge(_EdgeShapeInstances
[k
], _Vertices
[k
], _Vertices
[(k
+ 1) % _Vertices
.size()]);
485 if (!_EdgeDecals
.empty())
487 updateEdgeDecal(*(_EdgeDecals
[k
]), _Vertices
[k
], _Vertices
[(k
+ 1) % _Vertices
.size()],
488 k
== 0 ? _Look
.VertexLook
.DecalDistToEdgeDecal
: _Look
.FirstVertexLook
.DecalDistToEdgeDecal
,
489 _Look
.VertexLook
.DecalDistToEdgeDecal
501 for(uint k
= 0; k
< _Vertices
.size(); ++k
)
503 if (!_Look
.VertexShapeName
.empty())
505 if (!_VertexShapeInstances
[k
].empty())
508 vertexMat
.setScale(_Look
.VertexShapeScale
);
509 vertexMat
.setPos(_Vertices
[k
]);
510 _VertexShapeInstances
[k
].setTransformMode(UTransform::DirectMatrix
);
511 _VertexShapeInstances
[k
].setMatrix(vertexMat
);
514 if (!_VertexDecals
.empty())
516 _VertexDecals
[k
]->setWorldMatrixForSpot(CVector2f(_Vertices
[k
].x
, _Vertices
[k
].y
), k
== 0 ? _Look
.FirstVertexLook
.DecalSize
: _Look
.VertexLook
.DecalSize
);
520 if (_AddedToWorldMap
)
522 updateWorldMapDisplay();
526 // *********************************************************
527 void CPrimRender::updateEdge(NL3D::UInstance edge
,const NLMISC::CVector
&start
, const NLMISC::CVector
&end
)
529 //H_AUTO(R2_CPrimRender_updateEdge)
530 CVector I
= end
- start
;
531 CVector INormed
= I
.normed();
532 CVector K
= (CVector::K
- (CVector::K
* INormed
) * INormed
).normed();
533 CVector J
= K
^ INormed
;
534 CMatrix connectorMat
;
535 static volatile float scale
=0.5f
;
536 connectorMat
.setRot(I
, scale
* J
, scale
* K
);
537 connectorMat
.setPos(start
);
538 edge
.setTransformMode(UTransform::DirectMatrix
);
539 edge
.setMatrix(connectorMat
);
543 // *********************************************************
544 void CPrimRender::updateEdgeDecal(CDecal
&edgeDecal
, const NLMISC::CVector
&start
, const NLMISC::CVector
&end
, float distToStartVertex
, float distToEndVertex
)
546 //H_AUTO(R2_CPrimRender_updateEdgeDecal)
547 CVector2f
start2f(start
.x
, start
.y
);
548 CVector2f
end2f(end
.x
, end
.y
);
549 // compute real start coordinate that is at 'startRadius' dist from the 'start' pos
550 float length
= (end2f
- start2f
).norm();
551 if ((distToStartVertex
+ distToEndVertex
) >= length
)
554 nullMat
.setScale(0.f
);
556 edgeDecal
.setWorldMatrix(nullMat
);
559 CVector dirNormed
= (end2f
- start2f
) / length
;
560 start2f
= start2f
+ distToStartVertex
* dirNormed
;
561 end2f
= end2f
- distToEndVertex
* dirNormed
;
562 edgeDecal
.setWorldMatrixForArrow(start2f
, end2f
, _Look
.EdgeLook
.DecalWidth
);
564 float uScale
= _Look
.EdgeLook
.DecalUScale
* (length
- (distToStartVertex
+ distToEndVertex
));
565 uvMatrix
.setScale(CVector(uScale
, 1.f
, 1.f
));
566 switch(_Look
.EdgeLook
.DecalWrapMode
)
568 case CEdgeLook::Scaled
:
569 case CEdgeLook::Repeat
:
571 case CEdgeLook::Centered
:
572 uvMatrix
.setPos(CVector(0.5f
* (1.f
- uScale
), 0.f
, 0.f
));
578 edgeDecal
.setTextureMatrix(uvMatrix
);
581 // *********************************************************
582 void CPrimRender::addDecalsToRenderList()
584 //H_AUTO(R2_CPrimRender_addDecalsToRenderList)
585 if (!_Active
) return;
586 for(uint k
= 0; k
< _VertexDecals
.size(); ++k
)
588 _VertexDecals
[k
]->addToRenderList();
590 for(uint k
= 0; k
< _EdgeDecals
.size(); ++k
)
592 _EdgeDecals
[k
]->addToRenderList();
596 // *********************************************************
597 void CPrimRender::setWorldMapNumVertices(uint count
)
599 //H_AUTO(R2_CPrimRender_setWorldMapNumVertices)
600 nlassert(_AddedToWorldMap
);
601 CGroupMap
*gm
= CTool::getWorldMap();
603 if (count
< _WorldMapVertices
.size())
605 for(uint k
= count
; k
< _WorldMapVertices
.size(); ++k
)
607 gm
->delView(_WorldMapVertices
[k
]);
612 uint left
= count
- (uint
)_WorldMapVertices
.size();
615 CViewBitmap
*bm
= new CViewBitmap(CViewBase::TCtorParam());
616 bm
->setModulateGlobalColor(false);
617 bm
->setPosRef(Hotspot_MM
);
618 bm
->setParentPosRef(Hotspot_BL
);
619 bm
->setActive(_Active
);
622 bm
->setRenderLayer(2);
623 _WorldMapVertices
.push_back(bm
);
626 _WorldMapVertices
.resize(count
);
627 for(uint k
= 0; k
< count
; ++k
)
629 const CVertexLook
&look
= k
== 0 ? _Look
.VertexLook
: _Look
.FirstVertexLook
;
630 _WorldMapVertices
[k
]->setTexture(look
.WorldMapTexture
);
631 _WorldMapVertices
[k
]->setColor(look
.WorldMapColor
);
632 _WorldMapVertices
[k
]->fitTexture();
636 // *********************************************************
637 void CPrimRender::setWorldMapNumEdges(uint count
)
639 //H_AUTO(R2_CPrimRender_setWorldMapNumEdges)
640 nlassert(_AddedToWorldMap
);
641 CGroupMap
*gm
= CTool::getWorldMap();
643 if (count
< _WorldMapEdges
.size())
645 for(uint k
= count
; k
< _WorldMapEdges
.size(); ++k
)
647 gm
->delCtrl(_WorldMapEdges
[k
]);
652 uint left
= count
- (uint
)_WorldMapEdges
.size();
655 CCtrlQuad
*cq
= newCtrlQuad((uint
)_WorldMapEdges
.size());
656 cq
->setModulateGlobalColor(false);
657 cq
->setActive(_Active
);
660 cq
->setRenderLayer(1);
661 _WorldMapEdges
.push_back(cq
);
664 cq
->setId(_WorldMapPoly
->getId() + toString("_e%d", _WorldMapEdges
.size() - 1));
668 _WorldMapEdges
.resize(count
);
669 for(uint k
= 0; k
< count
; ++k
)
671 _WorldMapEdges
[k
]->setTexture(_Look
.EdgeLook
.WorldMapTexture
);
672 _WorldMapEdges
[k
]->setColorRGBA(_Look
.EdgeLook
.WorldMapColor
);
676 // *********************************************************
677 void CPrimRender::updateWorldMapDisplay()
679 //H_AUTO(R2_CPrimRender_updateWorldMapDisplay)
680 nlassert(_AddedToWorldMap
);
681 CGroupMap
*gm
= CTool::getWorldMap();
686 // *********************************************************
687 void CPrimRender::onAdd(CGroupMap
&owner
)
689 //H_AUTO(R2_CPrimRender_onAdd)
690 nlassert(!_AddedToWorldMap
);
691 _AddedToWorldMap
= true;
692 _WorldMapPoly
= newCtrlPolygon(); // TODO: create only if needed
693 _WorldMapPoly
->setParent(&owner
);
694 owner
.addCtrl(_WorldMapPoly
);
695 _WorldMapPoly
->setActive(false);
696 _WorldMapPoly
->setId(owner
.getId() + ":" + _WorldMapPoly
->getId());
697 for(uint k
= 0; k
< _WorldMapEdges
.size(); ++k
)
699 _WorldMapEdges
[k
]->setId(_WorldMapPoly
->getId() + toString("_e%d", (int) k
));
703 // *********************************************************
704 void CPrimRender::onRemove(CGroupMap
&owner
)
706 //H_AUTO(R2_CPrimRender_onRemove)
707 nlassert(_AddedToWorldMap
);
708 setWorldMapNumVertices(0);
709 setWorldMapNumEdges(0);
712 owner
.delCtrl(_WorldMapPoly
);
713 _WorldMapPoly
= NULL
;
715 _AddedToWorldMap
= false;
718 // *********************************************************
719 void CPrimRender::onPreRender(CGroupMap
&/* owner */)
721 //H_AUTO(R2_CPrimRender_onPreRender)
725 // *********************************************************
726 void CPrimRender::onUpdate(CGroupMap
&worldMap
)
728 //H_AUTO(R2_CPrimRender_onUpdate)
729 nlassert(_AddedToWorldMap
);
730 if (!_Look
.VertexLook
.WorldMapTexture
.empty())
732 nlassert(_Vertices
.size() == _WorldMapVertices
.size());
734 static std::vector
<sint32
> px
;
735 static std::vector
<sint32
> py
;
736 px
.resize(_Vertices
.size());
737 py
.resize(_Vertices
.size());
738 for(uint k
= 0; k
< _Vertices
.size(); ++k
)
740 worldMap
.worldToWindowSnapped(px
[k
], py
[k
], _Vertices
[k
]);
741 if (!_WorldMapVertices
.empty())
743 _WorldMapVertices
[k
]->setX(px
[k
]);
744 _WorldMapVertices
[k
]->setY(py
[k
]);
745 _WorldMapVertices
[k
]->updateCoords();
750 if (_Look
.Shape
== CPrimLook::ClosedPolyLine
)
752 _WorldMapPoly
->setActive(_Active
);
754 /*static volatile bool test1 = false;
755 const CVector2f &origin = test1 ? worldMap.getWorldOffset() : CVector2f::Null;
757 CVector2f ref0(0.f, 0.f);
758 CVector2f ref1(1000.f, 1000.f);
761 worldMap.worldToWindow(ref0, ref0);
762 worldMap.worldToWindow(ref1, ref1);
765 float scaleX = (ref1.x - ref0.x) * 0.001f;
766 float scaleY = (ref1.y - ref0.y) * 0.001f;
767 polyMatrix.setRot(CVector(scaleX, 0.f, 0.f),
768 CVector(0.f, scaleY, 0.f),
770 polyMatrix.setPos(CVector(ref0.x - scaleX * origin.x, ref0.y - scaleY * origin.y, 0.f));
772 _WorldMapPoly
->setVertices(_Vertices
);
773 //_WorldMapPoly->setMatrix(polyMatrix);
774 //_WorldMapPoly->touch();
777 static volatile bool dumpPoly = false;
780 nlwarning("================");
781 const std::vector<CVector> &verts = _WorldMapPoly->getVertices();
782 for(uint k = 0; k < verts.size(); ++k)
784 CVector pos = _WorldMapPoly->getMatrix() * verts[k];
785 nlwarning("vert %d = (%.1f, %.1f, %.1f)", (int) k , pos.x, pos.y, pos.z);
792 _WorldMapPoly
->setActive(false);
795 for(uint k
= 0; k
< _WorldMapEdges
.size(); ++k
)
797 uint startIndex
= _Look
.Shape
== CPrimLook::Star
? 0 : k
;
798 CVector2f
start((float) px
[startIndex
], (float) py
[startIndex
]);
799 uint nextIndex
= (k
+ 1) % _Vertices
.size();
800 CVector2f
end((float) px
[nextIndex
], (float) py
[nextIndex
]);
801 _WorldMapEdges
[k
]->setQuad(start
, end
, _Look
.EdgeLook
.WorldMapWidth
);
802 _WorldMapEdges
[k
]->setFiltered(_Look
.EdgeLook
.WorldMapFiltered
);
803 _WorldMapEdges
[k
]->updateCoords();
805 float length
= (end
- start
).norm();
806 if (_CustomWorldMapEdgeUVMatrix
.On
)
809 CVector startUV
= _CustomWorldMapEdgeUVMatrix
.Matrix
* _Vertices
[startIndex
];
810 CVector endUV
= _CustomWorldMapEdgeUVMatrix
.Matrix
* _Vertices
[nextIndex
];
811 static uint index0
= 0;
812 static uint index1
= 3;
813 static uint index2
= 2;
814 static uint index3
= 1;
815 uvs
[index0
] = uvs
[index1
] = CUV(startUV
.x
, startUV
.y
);
816 uvs
[index2
] = uvs
[index3
] = CUV(endUV
.x
, endUV
.y
);
817 _WorldMapEdges
[k
]->setCustomUVs(uvs
);
821 switch(_Look
.EdgeLook
.WorldMapWrapMode
)
823 case CEdgeLook::Scaled
:
824 _WorldMapEdges
[k
]->setPattern(0.f
, 1.f
, CCtrlQuad::Repeat
);
826 case CEdgeLook::Repeat
:
827 _WorldMapEdges
[k
]->setPattern(0.f
, _InvWorldTextureWidth
* _Look
.EdgeLook
.WorldMapUScale
* length
, CCtrlQuad::Repeat
);
829 case CEdgeLook::Centered
:
830 _WorldMapEdges
[k
]->setPattern(0.5f
- 0.5f
* length
* _InvWorldTextureWidth
* _Look
.EdgeLook
.WorldMapUScale
,
831 0.5f
+ 0.5f
* length
* _InvWorldTextureWidth
* _Look
.EdgeLook
.WorldMapUScale
,
842 // *********************************************************
843 CViewBitmap
*CPrimRender::getWorldMapVertexView(uint index
) const
845 //H_AUTO(R2_CPrimRender_getWorldMapVertexView)
846 if(index
>= _WorldMapVertices
.size()) return NULL
;
847 return _WorldMapVertices
[index
];
850 // *********************************************************
851 void CPrimRender::setWorldMapPolyColor(NLMISC::CRGBA color
)
853 //H_AUTO(R2_CPrimRender_setWorldMapPolyColor)
854 if (_WorldMapPoly
) _WorldMapPoly
->setColorRGBA(color
);
857 // *********************************************************
858 void CPrimRender::setActive(bool active
)
860 //H_AUTO(R2_CPrimRender_setActive)
861 if (active
== _Active
) return;
862 for(uint k
= 0; k
< _WorldMapVertices
.size(); ++k
)
864 if (_WorldMapVertices
[k
]) _WorldMapVertices
[k
]->setActive(active
);
866 for(uint k
= 0; k
< _WorldMapEdges
.size(); ++k
)
868 if (_WorldMapEdges
[k
]) _WorldMapEdges
[k
]->setActive(active
);
870 if (_WorldMapPoly
) _WorldMapPoly
->setActive(active
);
871 _VertexShapeInstances
.setActive(active
);
872 _EdgeShapeInstances
.setActive(active
);