Merge branch '138-toggle-free-look-with-hotkey' into 'main/atys-live'
[ryzomcore.git] / nel / src / gui / view_pointer.cpp
blob198c16c7cd2c09a7fb862ae239c940dbd6f22b44
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 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
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 "stdpch.h"
23 #include "nel/gui/view_pointer.h"
24 #include "nel/gui/widget_manager.h"
25 #include "nel/gui/view_renderer.h"
26 #include "nel/gui/group_paragraph.h"
27 #include "nel/gui/group_container.h"
28 #include "nel/misc/xml_auto_ptr.h"
29 #include "nel/misc/algo.h"
31 using namespace std;
32 using namespace NLMISC;
34 #ifdef DEBUG_NEW
35 #define new DEBUG_NEW
36 #endif
38 NLMISC_REGISTER_OBJECT(CViewBase, CViewPointer, std::string, "generic_pointer");
40 namespace NLGUI
43 bool CViewPointer::hwMouse = true;
45 // --------------------------------------------------------------------------------------------------------------------
46 CViewPointer::CViewPointer (const TCtorParam &param)
47 : CViewPointerBase(param)
49 _TxIdDefault = -2;
50 _TxIdMoveWindow = -2;
51 _TxIdResizeBRTL = -2;
52 _TxIdResizeBLTR = -2;
53 _TxIdResizeTB = -2;
54 _TxIdResizeLR = -2;
55 _TxIdRotate = -2;
56 _TxIdScale = -2;
57 _TxIdColPick = -2;
58 _TxIdPan = -2;
59 _TxIdCanPan = -2;
60 _TxIdPanR2 = -2;
61 _TxIdCanPanR2 = -2;
63 _OffsetX = 0;
64 _OffsetY = 0;
66 // The pointer must be draw over ALL layers
67 _RenderLayer= VR_LAYER_MAX;
68 _Color = CRGBA(255,255,255,255);
69 _LastHightLight = NULL;
70 _StringMode = false;
71 _ForceStringMode = false;
72 _StringCursor = NULL;
73 _StringCursorHardware = NULL;
76 void CViewPointer::forceLink()
81 // +++ VIEW SPECIFIC +++
83 // --------------------------------------------------------------------------------------------------------------------
84 bool CViewPointer::parse (xmlNodePtr cur,CInterfaceGroup * parentGroup)
86 CXMLAutoPtr prop;
88 if (! CViewBase::parse(cur, parentGroup) )
89 return false;
91 _OffsetX = getX();
92 _OffsetY = getY();
94 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_default");
95 if (prop) _TxDefault = NLMISC::toLowerAscii ((const char *) prop);
97 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_move_window");
98 if (prop) _TxMoveWindow = NLMISC::toLowerAscii ((const char *) prop);
100 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_resize_BR_TL");
101 if (prop) _TxResizeBRTL = NLMISC::toLowerAscii ((const char *) prop);
103 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_resize_BL_TR");
104 if (prop) _TxResizeBLTR = NLMISC::toLowerAscii ((const char *) prop);
106 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_resize_TB");
107 if (prop) _TxResizeTB = NLMISC::toLowerAscii ((const char *) prop);
109 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_resize_LR");
110 if (prop) _TxResizeLR = NLMISC::toLowerAscii ((const char *) prop);
112 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_rotate");
113 if (prop) _TxRotate = NLMISC::toLowerAscii ((const char *) prop);
115 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_scale");
116 if (prop) _TxScale = NLMISC::toLowerAscii ((const char *) prop);
118 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_colpick");
119 if (prop) _TxColPick = NLMISC::toLowerAscii ((const char *) prop);
121 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_pan");
122 if (prop) _TxPan = NLMISC::toLowerAscii ((const char *) prop);
124 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_can_pan");
125 if (prop) _TxCanPan = NLMISC::toLowerAscii ((const char *) prop);
127 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_pan_r2");
128 if (prop) _TxPanR2 = NLMISC::toLowerAscii ((const char *) prop);
130 prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_can_pan_r2");
131 if (prop) _TxCanPanR2 = NLMISC::toLowerAscii ((const char *) prop);
133 prop = (char*) xmlGetProp (cur, (xmlChar*)"color");
134 if (prop) _Color = convertColor(prop);
136 return true;
139 // --------------------------------------------------------------------------------------------------------------------
140 class CCtrlDepthEntry
142 public:
143 CCtrlBase *Ctrl;
144 uint Depth;
145 bool operator<(const CCtrlDepthEntry &o) const
147 // Inverse Test => descending order
148 return Depth>o.Depth;
152 // --------------------------------------------------------------------------------------------------------------------
153 void CViewPointer::draw ()
155 // Do not display the pointer if not visible.
156 if(!_PointerVisible)
157 return;
159 CViewRenderer &rVR = *CViewRenderer::getInstance();
161 if ( CWidgetManager::getInstance()->isIngame() )
162 if (!_StringCursor)
164 // Create the string cursor instance
165 std::vector<std::pair<std::string,std::string> > templateParams;
166 templateParams.push_back (std::pair<std::string,std::string>("id", "string_cursor"));
168 _StringCursor = CWidgetManager::getInstance()->getParser()->createGroupInstance("string_cursor", "", templateParams);
169 if (_StringCursor)
170 _StringCursor->setParentPos(CWidgetManager::getInstance()->getElementFromId("ui:interface"));
172 templateParams.clear();
173 templateParams.push_back (std::pair<std::string,std::string>("id", "string_cursor_hardware"));
174 _StringCursorHardware = CWidgetManager::getInstance()->getParser()->createGroupInstance("string_cursor_hardware", "", templateParams);
175 if (_StringCursorHardware)
176 _StringCursorHardware->setParentPos(CWidgetManager::getInstance()->getElementFromId("ui:interface"));
179 CRGBA col;
180 if(getModulateGlobalColor())
181 col.modulateFromColor (_Color, CWidgetManager::getInstance()->getGlobalColor());
182 else
183 col= _Color;
185 //col.A = (uint8)(((sint32)col.A*((sint32)pIM->getGlobalColor().A+1))>>8);
186 col.A = _Color.A;
188 if (_LastHightLight != NULL)
190 _LastHightLight->setHighLighted(false,0);
191 _LastHightLight = NULL;
194 if ( CWidgetManager::getInstance()->getCapturePointerLeft() != NULL && CWidgetManager::getInstance()->isMouseHandlingEnabled())
196 CCtrlMover *pCM = dynamic_cast<CCtrlMover*>( CWidgetManager::getInstance()->getCapturePointerLeft());
197 if ((pCM != NULL) && (pCM->canMove() == true))
199 CGroupContainer *pGC = dynamic_cast<CGroupContainer *>(pCM->getParent());
200 if (pGC != NULL && !pGC->isLocked())
202 pGC->setHighLighted(true, 255);
203 _LastHightLight = pGC;
208 if (_TxIdDefault == -2)
210 _TxIdDefault = rVR.getTextureIdFromName(_TxDefault);
212 if (_TxIdMoveWindow == -2)
214 _TxIdMoveWindow = rVR.getTextureIdFromName (_TxMoveWindow);
215 _TxIdResizeBRTL = rVR.getTextureIdFromName (_TxResizeBRTL);
216 _TxIdResizeBLTR = rVR.getTextureIdFromName (_TxResizeBLTR);
217 _TxIdResizeTB = rVR.getTextureIdFromName (_TxResizeTB);
218 _TxIdResizeLR = rVR.getTextureIdFromName (_TxResizeLR);
219 _TxIdRotate = rVR.getTextureIdFromName (_TxRotate);
220 _TxIdScale = rVR.getTextureIdFromName (_TxScale);
221 _TxIdColPick = rVR.getTextureIdFromName (_TxColPick);
222 _TxIdPan = rVR.getTextureIdFromName (_TxPan);
223 _TxIdCanPan = rVR.getTextureIdFromName (_TxCanPan);
224 _TxIdPanR2 = rVR.getTextureIdFromName (_TxPanR2);
225 _TxIdCanPanR2 = rVR.getTextureIdFromName (_TxCanPanR2);
229 const vector<CCtrlBase *> &rICL = CWidgetManager::getInstance()->getCtrlsUnderPointer ();
232 // Draw the captured cursor
233 CCtrlBase *pCB = CWidgetManager::getInstance()->getCapturePointerLeft();
234 if (pCB != NULL)
236 if (drawResizer(pCB,col)) return;
237 if (drawColorPicker(pCB,col)) return;
238 if (drawRotate(pCB,col)) return;
239 if (drawPan(pCB,col)) return;
240 if (drawCustom(pCB)) return;
241 drawCursor(_TxIdDefault, col, 0);
242 return;
245 const vector<CViewBase *> &vUP = CWidgetManager::getInstance()->getViewsUnderPointer ();
247 for(uint i=0;i<vUP.size();i++)
249 CViewLink *vLink = dynamic_cast<CViewLink*>(vUP[i]);
250 if (vLink != NULL)
252 string tooltip;
253 uint8 rot;
255 if (vLink->getMouseOverShape(tooltip, rot, col))
257 setString(tooltip);
258 sint32 texId = rVR.getTextureIdFromName ("curs_pick.tga");
260 CInterfaceGroup *stringCursor = hwMouse ? _StringCursorHardware : _StringCursor;
261 if (stringCursor)
263 stringCursor->setX(_PointerX);
264 stringCursor->setY(_PointerY);
265 stringCursor->updateCoords();
266 stringCursor->draw();
267 // if in hardware mode, force to draw the default cursor no matter what..
268 if ( hwMouse )
269 drawCursor(texId, col, 0);
271 else
273 drawCursor(texId, col, 0);
275 return;
280 // Draw if capture right
281 pCB = CWidgetManager::getInstance()->getCapturePointerRight();
282 if (pCB != NULL)
284 // Is it a 3d scene ?
285 if (drawScale(pCB,col)) return;
286 drawCursor(_TxIdDefault, col, 0);
287 return;
290 bool overModalWindow = false;
293 // is the cursor currently over a modal window ?
294 CInterfaceGroup *currModal = CWidgetManager::getInstance()->getModalWindow();
295 if (currModal)
297 sint32 xPos = _XReal + _OffsetX;
298 sint32 yPos = _YReal + _OffsetY;
299 overModalWindow = currModal->isIn(xPos, yPos, _WReal, _HReal);
302 // Draw the cursor type that are under the pointer
303 if (CWidgetManager::getInstance()->isMouseHandlingEnabled())
305 // Sorts the controls according to their depth, to approximate as best the CapturePointerLeft algo.
306 // Especially important so that Resizers controls get the precedence over the move control (else could randomly bug like in chat group)
307 static vector<CCtrlDepthEntry> sortedControls;
308 sortedControls.clear();
309 for(uint i=0;i<rICL.size();i++)
311 CCtrlDepthEntry cde;
312 cde.Ctrl= rICL[i];
313 // NB: not the exact CInterfaceManager getDepth test here, but should work fine
314 cde.Depth= cde.Ctrl->getParentDepth() + cde.Ctrl->getDeltaDepth();
315 sortedControls.push_back(cde);
317 std::sort(sortedControls.begin(), sortedControls.end());
319 // Then draw the correct cursor
320 for (uint32 i = 0; i < sortedControls.size(); ++i)
322 CCtrlBase *pCB = sortedControls[i].Ctrl;
324 if (overModalWindow)
326 if (!pCB->isSonOf(currModal)) continue;
329 if (drawBrowse(pCB, col)) return;
330 if (drawResizer(pCB,col)) return;
331 if (drawColorPicker(pCB,col)) return;
332 if (drawLink (pCB, col)) return;
333 if (drawCustom(pCB)) return;
335 // test for move highlight
336 if (_LastHightLight == NULL)
338 CCtrlMover *pCM = dynamic_cast<CCtrlMover*>(pCB);
339 if ( (pCM != NULL) && (pCM->canMove() == true) )
341 CGroupContainer *pGC = dynamic_cast<CGroupContainer *>(pCM->getParent());
342 if (pGC != NULL && !pGC->isLocked())
344 if (CWidgetManager::getInstance()->getCapturePointerLeft() != pCM)
345 pGC->setHighLighted(true, 128);
346 else
347 pGC->setHighLighted(true, 255);
348 _LastHightLight = pGC;
349 break;
356 if (CWidgetManager::getInstance()->isMouseHandlingEnabled())
358 if (rICL.empty())
360 const vector<CInterfaceGroup *> &rIGL = CWidgetManager::getInstance()->getGroupsUnderPointer ();
361 for (uint32 i = 0; i < rIGL.size(); ++i)
363 CInterfaceGroup *pG = rIGL[i];
364 if (overModalWindow)
366 if (!pG->isSonOf(currModal)) continue;
368 if (drawPan (pG, col)) return;
369 if (drawBrowse(pG, col)) return;
374 if (_StringMode && CWidgetManager::getInstance()->isMouseHandlingEnabled())
376 CInterfaceGroup *stringCursor = hwMouse ? _StringCursorHardware : _StringCursor;
377 if (stringCursor)
379 stringCursor->setX(_PointerX);
380 stringCursor->setY(_PointerY);
381 stringCursor->updateCoords();
382 stringCursor->draw();
383 // if in hardware mode, force to draw the default cursor no matter what..
384 if ( hwMouse )
386 drawCursor(_TxIdDefault, col, 0);
390 else
392 // Draw the default cursor
393 drawCursor(_TxIdDefault, col, 0);
397 // --------------------------------------------------------------------------------------------------------------------
398 bool CViewPointer::drawCustom(CCtrlBase* pCB)
400 string texName;
401 uint8 rot;
402 NLMISC::CRGBA col;
403 if (pCB->getMouseOverShape(texName, rot, col))
405 if (texName[0] == '@')
407 const string &tooltipInfos = texName.substr(1);
408 string tooltip;
409 vector<string> tooltipInfosList;
410 splitString(tooltipInfos, "@", tooltipInfosList);
411 texName = tooltipInfosList[0];
412 tooltip = tooltipInfosList[1];
413 setString(tooltip);
414 CViewRenderer &rVR = *CViewRenderer::getInstance();
415 sint32 texId = rVR.getTextureIdFromName (texName);
417 CInterfaceGroup *stringCursor = hwMouse ? _StringCursorHardware : _StringCursor;
418 if (stringCursor)
420 stringCursor->setX(_PointerX);
421 stringCursor->setY(_PointerY);
422 stringCursor->updateCoords();
423 stringCursor->draw();
424 // if in hardware mode, force to draw the default cursor no matter what..
425 if ( hwMouse )
426 drawCursor(texId, col, 0);
428 else
430 drawCursor(texId, col, 0);
432 return true;
434 else
436 CViewRenderer &rVR = *CViewRenderer::getInstance();
437 sint32 texId = rVR.getTextureIdFromName (texName);
438 drawCursor(texId, col, 0);
439 return true;
442 return false;
446 // +++ SET +++
449 // --------------------------------------------------------------------------------------------------------------------
450 void CViewPointer::setStringMode (bool stringCursor)
452 _StringMode = stringCursor;
455 // --------------------------------------------------------------------------------------------------------------------
456 void CViewPointer::setString(const std::string &str, CInterfaceGroup *target)
458 if (target)
460 CInterfaceElement *element = target->getView ("fake_txt");
461 if (element)
463 CViewText *text = dynamic_cast<CViewText*> (element);
464 if (text)
465 text->setText(str);
467 element = target->getView ("real_txt");
468 if (element)
470 CViewText *text = dynamic_cast<CViewText*> (element);
471 if (text)
472 text->setText(str);
474 target->updateCoords();
475 target->updateCoords();
476 _ContextString = str;
481 // --------------------------------------------------------------------------------------------------------------------
482 void CViewPointer::setString (const std::string &str)
484 if (_ContextString != str)
486 setString(str, _StringCursor);
487 setString(str, _StringCursorHardware);
491 // --------------------------------------------------------------------------------------------------------------------
492 void CViewPointer::drawCursor(sint32 texId, NLMISC::CRGBA col, uint8 rot)
494 CViewRenderer &rVR = *CViewRenderer::getInstance();
495 sint32 xPos = _XReal + _OffsetX;
496 sint32 yPos = _YReal + _OffsetY;
497 if ( !hwMouse )
499 rVR.draw11RotFlipBitmap (_RenderLayer, xPos, yPos, rot, false, texId, col);
501 else
503 // set new cursor for the hardware mouse
504 std::string name = rVR.getTextureNameFromId(texId);
505 rVR.getDriver()->setCursor(name, col, rot, (uint32) std::max(getX() - xPos, (sint32) 0), (uint32) std::max(getY() - yPos, (sint32) 0));