Merge branch '138-toggle-free-look-with-hotkey' into main/gingo-test
[ryzomcore.git] / ryzom / client / src / interface_v3 / action_handler_ui.cpp
blob7495cfa7f50271c02decffec110fb4fc19d08f74
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) 2019 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/>.
24 #include "stdpch.h"
26 // Interface
27 #include "interface_manager.h"
28 #include "bot_chat_manager.h"
29 #include "nel/gui/action_handler.h"
30 #include "nel/gui/group_container.h"
31 #include "macrocmd_manager.h"
32 #include "chat_window.h"
33 #include "people_interraction.h"
34 #include "nel/gui/group_editbox.h"
35 #include "nel/gui/group_html.h"
36 #include "inventory_manager.h"
38 // Client Game
39 #include "../entities.h"
40 #include "../actions_client.h"
42 // Game share specific includes
43 #include "game_share/constants.h"
46 // ***************************************************************************
48 using namespace std;
49 using namespace NLMISC;
51 // ***************************************************************************
52 // ***************************************************************************
53 // ***************************************************************************
54 // CONTAINER ACTION HANDLERS
55 // ***************************************************************************
56 // ***************************************************************************
57 // ***************************************************************************
60 // test if a container is currently allowed to be displayed
61 static bool isContainerAuthorized(CGroupContainer *pGC)
63 nlassert(pGC);
64 CInterfaceManager *pIM = CInterfaceManager::getInstance();
65 std::string shortId = pGC->getShortId();
66 // special case to prevent opening the guild inventory window if there's
67 // no guild or not in guild hall.
68 if (shortId == "inv_guild")
70 if (NLGUI::CDBManager::getInstance()->getDbProp("SERVER:GUILD:NAME") == 0
71 || !getInventory().isInventoryPresent(INVENTORIES::guild))
73 return false; // can't open it right now
76 if (shortId == "inv_room")
78 if (!getInventory().isInventoryPresent(INVENTORIES::player_room))
80 return false;
83 return true;
86 // ***************************************************************************
87 // open
88 // Arg : a container name
89 // Open a container
90 // ***************************************************************************
91 class CAHUIOpen : public IActionHandler
93 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
95 CInterfaceManager *pIM = CInterfaceManager::getInstance();
96 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
97 if (pGC == NULL)
99 nlwarning("%s is not a container", Params.c_str());
100 return;
102 if (!isContainerAuthorized(pGC)) return;
103 pGC->open();
106 REGISTER_ACTION_HANDLER( CAHUIOpen, "open" );
108 // ***************************************************************************
109 // close
110 // Arg : a container name
111 // Close a container
112 // ***************************************************************************
113 class CAHUIClose : public IActionHandler
115 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
117 CInterfaceManager *pIM = CInterfaceManager::getInstance();
118 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
119 if (pGC == NULL)
121 nlwarning("%s is not a container", Params.c_str());
122 return;
124 pGC->close();
127 REGISTER_ACTION_HANDLER( CAHUIClose, "close" );
129 // ***************************************************************************
130 // open_close
131 // Arg : a container name
132 // Toggle - Close a container if opened and open it if closed
133 // ***************************************************************************
134 class CAHUIOpenClose : public IActionHandler
136 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
138 CInterfaceManager *pIM = CInterfaceManager::getInstance();
139 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
140 if (pGC == NULL)
142 nlwarning("%s is not a container", Params.c_str());
143 return;
145 if (!isContainerAuthorized(pGC)) return;
146 pGC->setOpen (!pGC->isOpen());
149 REGISTER_ACTION_HANDLER( CAHUIOpenClose, "open_close" );
151 // ***************************************************************************
152 // popup
153 // Arg : a container name
154 // Popup a container
155 // ***************************************************************************
156 class CAHUIPopup : public IActionHandler
158 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
160 CInterfaceManager *pIM = CInterfaceManager::getInstance();
161 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
162 if (pGC == NULL)
164 nlwarning("%s is not a container", Params.c_str());
165 return;
167 if (!pGC->isPopable())
169 nlwarning("%s cannot be popup", Params.c_str());
170 return;
172 if (!isContainerAuthorized(pGC)) return;
174 pGC->popup();
176 CWidgetManager::getInstance()->setCapturePointerLeft(NULL);
177 CWidgetManager::getInstance()->setCapturePointerRight(NULL);
180 REGISTER_ACTION_HANDLER( CAHUIPopup, "popup" );
182 // ***************************************************************************
183 // popin
184 // Arg : a container name
185 // Popin a container (restore it)
186 // ***************************************************************************
187 class CAHUIPopin : public IActionHandler
189 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
191 CInterfaceManager *pIM = CInterfaceManager::getInstance();
192 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
193 if (pGC == NULL)
195 nlwarning("%s is not a container", Params.c_str());
196 return;
198 if (!pGC->isPopable())
200 nlwarning("%s cannot be popin", Params.c_str());
201 return;
203 if (!isContainerAuthorized(pGC)) return;
204 // memorize popup position
205 pGC->setPopupX(pGC->getX());
206 pGC->setPopupY(pGC->getY());
207 pGC->setPopupW(pGC->getW());
208 pGC->setPopupH(pGC->getH());
210 pGC->popin();
211 CWidgetManager::getInstance()->setCapturePointerLeft(NULL);
212 CWidgetManager::getInstance()->setCapturePointerRight(NULL);
215 REGISTER_ACTION_HANDLER( CAHUIPopin, "popin" );
217 // ***************************************************************************
218 // popup_popin
219 // Arg : a container name
220 // Toggle Popup/Popin a container
221 // ***************************************************************************
222 class CAHUIPopupPopin : public IActionHandler
224 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
226 CInterfaceManager *pIM = CInterfaceManager::getInstance();
227 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
228 if (pGC == NULL)
230 nlwarning("%s is not a container", Params.c_str());
231 return;
233 if (!pGC->isPopable())
235 nlwarning("%s cannot be popup/popin", Params.c_str());
236 return;
238 if (!isContainerAuthorized(pGC)) return;
239 if (pGC->isPopuped())
240 CAHManager::getInstance()->runActionHandler("popin", NULL, Params);
241 else
242 CAHManager::getInstance()->runActionHandler("popup", NULL, Params);
245 REGISTER_ACTION_HANDLER( CAHUIPopupPopin, "popup_popin" );
247 // ***************************************************************************
248 // show_on_press
249 // Arg : a container name
250 // Show a container on a key down (else hide it)
251 // ***************************************************************************
252 class CAHUIShowOnPress : public IActionHandler
254 public:
255 CAHUIShowOnPress()
257 _FirstTime = true;
260 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
262 CInterfaceManager *pIM = CInterfaceManager::getInstance();
263 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
264 if (pGC == NULL)
266 nlwarning("%s is not a container", Params.c_str());
267 return;
269 if (!isContainerAuthorized(pGC)) return;
271 CActionsManager *pAM = &Actions;
273 // If key is up
274 if (!pAM->valide(CAction::CName("show_on_press",Params.c_str())))
276 pGC->setActive(false);
277 _FirstTime = true;
279 else // Key is down
281 // For the first time ?
282 /*if (_FirstTime)
284 _FirstTime = false;
286 else // Not the first time*/
288 // Show the container
289 pGC->setActive(true);
293 private:
294 bool _FirstTime;
296 REGISTER_ACTION_HANDLER( CAHUIShowOnPress, "show_on_press" );
299 // ***************************************************************************
300 // show
301 // Arg : a container name
302 // Show a container
303 // ***************************************************************************
304 class CAHUIShow : public IActionHandler
306 public:
307 CAHUIShow()
311 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
313 CInterfaceManager *pIM = CInterfaceManager::getInstance();
314 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
315 if (pGC == NULL)
317 nlwarning("%s is not a container", Params.c_str());
318 return;
320 if (!isContainerAuthorized(pGC)) return;
322 pGC->setActive(true);
323 CWidgetManager::getInstance()->setTopWindow(pGC);
326 REGISTER_ACTION_HANDLER( CAHUIShow, "show" );
328 static string currentWebApp;
330 // ***************************************************************************
331 // hide
332 // Arg : a container name
333 // Hide a container
334 // ***************************************************************************
335 class CAHUIHide : public IActionHandler
337 public:
338 CAHUIHide()
342 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
344 CInterfaceManager *pIM = CInterfaceManager::getInstance();
345 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", Params));
346 if (pGC == NULL)
348 nlwarning("%s is not a container", Params.c_str());
349 return;
351 if (!isContainerAuthorized(pGC)) return;
353 pGC->setActive(false);
356 REGISTER_ACTION_HANDLER( CAHUIHide, "hide" );
358 string urlencode(const string &param)
360 CSString str = param;
361 str = str.replace("+", toString("%%%2x", '+').c_str());
362 str = str.replace("'", toString("%%%2x", '\'').c_str());
363 str = str.replace("-", toString("%%%2x", '-').c_str());
364 str = str.replace("\"", toString("%%%2x", '"').c_str());
365 str = str.replace(" ", "+");
366 return str;
369 // ***************************************************************************
370 // show_hide
371 // Arg : a container name
372 // Toggle - Show a container if hidden and hide it if shown
373 // ***************************************************************************
374 class CAHUIShowHide : public IActionHandler
376 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
378 string webapp, window = Params;
379 vector<string> res;
380 explode(Params, string("|"), res);
381 if(res[0]=="webig" || res[0]=="mailbox" || res[0]=="guild_forum" || res[0]=="profile")
383 window = "webig";
384 if(res[0]=="mailbox")
385 webapp = "mail";
386 else if(res[0]=="guild_forum")
387 webapp = "forum";
388 else if(res[0]=="profile")
389 webapp = "profile&pname="+urlencode(getParam(Params,"pname"))+"&ptype="+getParam(Params,"ptype");
390 else
391 webapp = "web";
394 CInterfaceManager *pIM = CInterfaceManager::getInstance();
395 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface", window));
396 if (pGC == NULL)
398 nlwarning("%s is not a container", window.c_str());
399 return;
401 if (!isContainerAuthorized(pGC)) return;
403 if(window == "webig")
405 if(pGC->getActive() && currentWebApp == webapp)
407 pGC->setActive(false);
408 currentWebApp.clear();
410 else
412 pGC->setActive(true);
413 currentWebApp = webapp;
415 if(!webapp.empty() && pGC->getActive())
417 CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:webig:content:html"));
418 if (pGH == NULL)
420 nlwarning("%s is not a group html", window.c_str());
421 return;
423 pGH->setURL(ClientCfg.WebIgMainDomain + "/index.php?app=" + webapp);
426 else
428 // normal open/close swap
429 pGC->setActive(!pGC->getActive());
433 REGISTER_ACTION_HANDLER( CAHUIShowHide, "show_hide" );
435 // ***************************************************************************
436 // ***************************************************************************
437 // ***************************************************************************
438 // GAME ACTION HANDLERS
439 // ***************************************************************************
440 // ***************************************************************************
441 // ***************************************************************************
443 // ***************************************************************************
444 // next_sheath
445 // Arg : none
446 // Set the Next sheath
447 // ***************************************************************************
449 class CAHNextSheath : public IActionHandler
451 virtual void execute (CCtrlBase *pCaller, const string &Params)
453 CInterfaceManager *pIM = CInterfaceManager::getInstance();
454 CCDBNodeLeaf *pNLCurSetWrite = NLGUI::CDBManager::getInstance()->getDbProp(CWidgetManager::getInstance()->getParser()->getDefine("ui_set_active"));
455 CCDBNodeLeaf *pNLCurSetRead = NLGUI::CDBManager::getInstance()->getDbProp(CWidgetManager::getInstance()->getParser()->getDefine("set_active"));
456 CCDBNodeLeaf *pNLNbSet = NLGUI::CDBManager::getInstance()->getDbProp(CWidgetManager::getInstance()->getParser()->getDefine("set_nb"));
457 sint64 nVal = pNLCurSetRead->getValue64() - INVENTORIES::sheath1;
458 sint64 nMax = pNLNbSet->getValue64();
459 nVal++;
460 if (nVal >= nMax) nVal = 0;
461 nVal += INVENTORIES::sheath1;
462 pNLCurSetWrite->setValue64(nVal);
465 REGISTER_ACTION_HANDLER( CAHNextSheath, "next_sheath" );
467 // ***************************************************************************
468 // previous_sheath
469 // Arg : none
470 // Set the Previous sheath
471 // ***************************************************************************
473 class CAHPreviousSheath : public IActionHandler
475 virtual void execute (CCtrlBase *pCaller, const string &Params)
477 CInterfaceManager *pIM = CInterfaceManager::getInstance();
478 CCDBNodeLeaf *pNLCurSetWrite = NLGUI::CDBManager::getInstance()->getDbProp(CWidgetManager::getInstance()->getParser()->getDefine("ui_set_active"));
479 CCDBNodeLeaf *pNLCurSetRead = NLGUI::CDBManager::getInstance()->getDbProp(CWidgetManager::getInstance()->getParser()->getDefine("set_active"));
480 CCDBNodeLeaf *pNLNbSet = NLGUI::CDBManager::getInstance()->getDbProp(CWidgetManager::getInstance()->getParser()->getDefine("set_nb"));
481 sint64 nVal = pNLCurSetRead->getValue64() - INVENTORIES::sheath1;
482 sint64 nMax = pNLNbSet->getValue64();
483 if (nVal == 0) nVal = nMax;
484 nVal--;
485 nVal += INVENTORIES::sheath1;
486 pNLCurSetWrite->setValue64(nVal);
489 REGISTER_ACTION_HANDLER( CAHPreviousSheath, "previous_sheath" );
491 // ***************************************************************************
492 // set_sheath
493 // Arg : the sheath number (int)
494 // Set the sheath ##
495 // ***************************************************************************
497 class CAHSetSheath : public IActionHandler
499 virtual void execute (CCtrlBase *pCaller, const string &Params)
501 CInterfaceManager *pIM = CInterfaceManager::getInstance();
502 CCDBNodeLeaf *pNLCurSetWrite = NLGUI::CDBManager::getInstance()->getDbProp(CWidgetManager::getInstance()->getParser()->getDefine("ui_set_active"));
503 CCDBNodeLeaf *pNLNbSet = NLGUI::CDBManager::getInstance()->getDbProp(CWidgetManager::getInstance()->getParser()->getDefine("set_nb"));
504 sint64 nVal;
505 fromString(Params, nVal);
506 nVal -= INVENTORIES::sheath1;
507 sint64 nMax = pNLNbSet->getValue64();
508 if (nVal < 0) nVal = 0;
509 if (nVal >= nMax) nVal = nMax-1;
510 nVal += INVENTORIES::sheath1;
511 pNLCurSetWrite->setValue64(nVal);
514 REGISTER_ACTION_HANDLER( CAHSetSheath, "set_sheath" );
516 // ***************************************************************************
517 // talk_untalk
518 // Arg : none
519 // Talk or end dialog with the current target
520 // ***************************************************************************
521 class CAHTalkUntalk : public IActionHandler
523 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
525 /* CInterfaceManager *pIM = CInterfaceManager::getInstance();
526 if(pIM == NULL) return;
527 CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
529 if (selection && selection->Type == CEntityCL::Player)
531 if (!selection->getName().empty())
533 // popup the main window and set its target to be the player
534 CChatWindow *cw = PeopleInterraction.MainChat.Window;
535 if (cw && cw->getContainer())
537 cw->getContainer()->setActive(true);
538 cw->getContainer()->setOpen(true);
539 CInterfaceManager *im = CInterfaceManager::getInstance();
540 CWidgetManager::getInstance()->setTopWindow(cw->getContainer());
541 cw->enableBlink(1);
542 CWidgetManager::getInstance()->setCaptureKeyboard(cw->getEditBox());
543 PeopleInterraction.MainChat.Filter.setTargetPlayer(selection->getName());
547 else
549 CBotChatManager::getInstance()->setCurrPage(NULL);
551 if (UserEntity->mode()==MBEHAV::COMBAT
552 || UserEntity->mode()==MBEHAV::COMBAT_FLOAT)
554 return; // Cant talk
556 // Not in combat mode.
557 else
559 // talk ?
560 if ((UserEntity->selection() != UserEntity->slot()) &&
561 (selection) && (selection->properties().talkableTo()))
563 CVectorD vect1 = selection->pos();
564 CVectorD vect2 = UserEntity->pos();
565 double distanceSquare = pow(vect1.x-vect2.x,2) + pow(vect1.y-vect2.y,2);
566 if(distanceSquare <= MaxTalkingDistSquare)
568 CAHManager::getInstance()->runActionHandler("context_talk",NULL);
575 REGISTER_ACTION_HANDLER( CAHTalkUntalk, "talk_untalk" );
577 // ***************************************************************************
578 // mount_unmount
579 // Arg : none
580 // Mount or unseat if we can the current target
581 // ***************************************************************************
582 class CAHMountUnmount : public IActionHandler
584 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
586 CInterfaceManager *pIM = CInterfaceManager::getInstance();
587 if(pIM == NULL) return;
588 CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
590 // If mode Combat (no talk, no give, no mount)
591 if(UserEntity->mode()==MBEHAV::COMBAT
592 || UserEntity->mode()==MBEHAV::COMBAT_FLOAT)
594 return; // Cant mount
596 // Mount
597 else if(UserEntity->isRiding())
599 // We are currently mounted so unmount
600 CAHManager::getInstance()->runActionHandler("context_unseat",NULL);
602 // Not in combat mode.
603 else
605 // check if we can mount
606 if ((selection) && (selection->properties().mountable()))
608 CVectorD vect1 = selection->pos();
609 CVectorD vect2 = UserEntity->pos();
610 double distanceSquare = pow(vect1.x-vect2.x,2) + pow(vect1.y-vect2.y,2);
611 if(distanceSquare <= MaxTalkingDistSquare)
613 // Ok lets mount
614 CAHManager::getInstance()->runActionHandler("context_mount",NULL);
620 REGISTER_ACTION_HANDLER( CAHMountUnmount, "mount_unmount" );
622 // ***************************************************************************
623 // exchange
624 // Arg : none
625 // Exchange with the current target
626 // ***************************************************************************
627 class CAHExchange : public IActionHandler
629 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
631 CInterfaceManager *pIM = CInterfaceManager::getInstance();
632 if(pIM == NULL) return;
633 CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
635 if(UserEntity->mode()==MBEHAV::COMBAT
636 || UserEntity->mode()==MBEHAV::COMBAT_FLOAT)
638 return; // Cant exchange
640 // Mount
641 else
643 if (selection && selection->properties().canExchangeItem())
644 if (!UserEntity->isBusy())
645 CAHManager::getInstance()->runActionHandler("context_exchange",NULL);
649 REGISTER_ACTION_HANDLER( CAHExchange, "exchange" );
651 // ***************************************************************************
652 // set_top_window
653 // Arg : window full name
654 // ***************************************************************************
655 class CAHUISetTopWindow : public IActionHandler
657 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
659 CInterfaceManager *pIM = CInterfaceManager::getInstance();
660 string sWin = getParam(Params,"win");
661 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId(sWin));
662 if (pGC != NULL && isContainerAuthorized(pGC)) CWidgetManager::getInstance()->setTopWindow(pGC);
665 REGISTER_ACTION_HANDLER( CAHUISetTopWindow, "set_top_window" );
668 // ***************************************************************************
669 // dock_undock_chat
670 // ***************************************************************************
672 class CAHUIDockUndocChat : public IActionHandler
674 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
676 CInterfaceManager *pIM = CInterfaceManager::getInstance();
677 // change the DB (if exist)
678 CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp(toString("UI:SAVE:ISDETACHED:")+Params, false);
679 if(node)
681 // swap
682 node->setValueBool(!node->getValueBool());
686 REGISTER_ACTION_HANDLER( CAHUIDockUndocChat, "dock_undock_chat" );