Fix css style order when using external css files
[ryzomcore.git] / ryzom / client / src / interface_v3 / group_compas.cpp
blob5089149b44e786f82730302353ee55710c9b5a4f
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) 2012 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 //
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Affero General Public License as
11 // published by the Free Software Foundation, either version 3 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Affero General Public License for more details.
19 // You should have received a copy of the GNU Affero General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "stdpch.h"
26 #include "nel/misc/xml_auto_ptr.h"
28 #include "group_compas.h"
29 #include "interface_3d_scene.h"
30 #include "../entities.h"
31 #include "nel/gui/action_handler.h"
32 #include "group_map.h"
33 #include "../continent.h"
34 #include "../continent_manager.h"
35 #include "interface_manager.h"
36 #include "../time_client.h"
37 #include "people_interraction.h"
38 #include "../net_manager.h"
39 #include "../string_manager_client.h"
40 #include "view_radar.h"
41 #include "../client_cfg.h"
42 // Game share
43 #include "game_share/mission_desc.h"
44 #include "game_share/inventories.h"
45 #include "game_share/animal_type.h"
47 extern NL3D::UCamera MainCam;
48 extern CEntityManager EntitiesMngr;
49 extern CContinentManager ContinentMngr;
50 CCompassDialogsManager * CCompassDialogsManager::_Instance = NULL;
52 using namespace std;
53 using namespace NLMISC;
54 using namespace STRING_MANAGER;
56 // ***************************************************************************
57 CCompassTarget::CCompassTarget()
59 _Type = North;
60 Name = CI18N::get("uiNorth");
64 // ***************************************************************************
65 void CCompassTarget::serial(NLMISC::IStream &f)
67 if (!f.isReading())
69 // some position state may not support 'serial'
70 if (_PositionState && !_PositionState->canSave())
72 CCompassTarget defaultCompassTarget;
73 f.serial(defaultCompassTarget);
74 return;
77 f.serialCheck(NELID("CTAR"));
78 sint version = f.serialVersion(1);
79 f.serial(Pos);
80 // for the name, try to save a string identifier if possible, because language may be changed between
81 // save & reload
82 if (version < 1)
84 ucstring name; // Serial old version
85 f.serial(name);
86 Name = name.toUtf8();
88 else
90 f.serial(Name);
92 std::string language = toLowerAscii(ClientCfg.LanguageCode);
93 f.serial(language);
94 f.serialEnum(_Type);
95 if (_Type == PosTracker)
97 CPositionState *ps = _PositionState;
98 if (ps)
100 nlwarning("ClassName = %s", ps->getClassName().c_str());
102 nlwarning("%s poly ptr", f.isReading() ? "reading" : "writing");
103 f.serialPolyPtr(ps);
104 _PositionState = ps;
106 else
108 if (f.isReading())
110 _PositionState = NULL;
113 f.serialCheck(NELID("_END"));
114 // if language has been modified, then we are not able to display correctly the name, so just
115 // reset the compass to north to avoid incoherency
116 if (f.isReading())
118 if (toLowerAscii(ClientCfg.LanguageCode) != language)
120 *this = CCompassTarget();
126 // ***************************************************************************
127 NLMISC_REGISTER_OBJECT(CViewBase, CGroupCompas, std::string, "compas");
129 CGroupCompas::CGroupCompas(const TCtorParam &param)
130 : CGroupContainer(param)
132 _ArrowShape = NULL;
133 std::fill(_TargetTypeColor, _TargetTypeColor + CCompassTarget::NumTypes, CRGBA::White);
134 _Target.setType(CCompassTarget::North);
135 _Target.Name = CI18N::get("uiNorth");
136 _StartBlinkTime = 0;
137 _Blinking = false;
138 _NewTargetSelectedColor = CRGBA(255, 127, 0);
139 _DistView = NULL;
140 _RadarView = NULL;
141 _RadarRangeView = NULL;
142 _RadarPos = 1; // 50 m
143 _DynamicTargetPos = NULL;
144 _LastDynamicTargetPos = 0xFFFFFFFF;
145 _SavedTargetValid = false;
146 _TargetSetOnce = false;
148 CCDBNodeLeaf *pRC = CDBManager::getInstance()->getDbProp("UI:SAVE:RADAR:USE_CAMERA");
149 if (pRC)
151 ICDBNode::CTextId textId;
152 pRC->addObserver( &_UseCameraObs, textId);
156 // ***************************************************************************
157 CGroupCompas::~CGroupCompas()
159 CCDBNodeLeaf *pRC = CDBManager::getInstance()->getDbProp("UI:SAVE:RADAR:USE_CAMERA");
160 if (pRC)
162 ICDBNode::CTextId textId;
163 pRC->removeObserver( &_UseCameraObs, textId);
168 // ***************************************************************************
169 bool CGroupCompas::wantSerialConfig() const
171 // NB when the user first start the game, the target will befirst set to 'chiang the strong' when
172 // missions are being received for the first time. If his fail to occur, we just don't
173 // save anything
174 return _TargetSetOnce;
177 // ***************************************************************************
178 void CGroupCompas::serialConfig(NLMISC::IStream &f)
180 f.serialVersion(0);
181 if(!f.isReading())
183 _SavedTarget = _Target;
185 f.serial(_SavedTarget);
186 _SavedTargetValid = true;
190 // ***************************************************************************
191 void CGroupCompas::updateCoords()
193 CGroupContainer::updateCoords();
195 // Set the compas
196 if (_ArrowShape == NULL)
198 CInterfaceElement *element = getElement (_Id+":arrow3d");
199 if (element)
201 // 3d scene
202 CInterface3DScene *scene = dynamic_cast<CInterface3DScene *>(element);
203 if (scene)
205 element = scene->getElement (scene->getId()+":arrow");
206 if (element)
208 // Shape
209 _ArrowShape = dynamic_cast<CInterface3DShape *>(element);
215 // Get a pointer on the dist view
216 if (_DistView == NULL)
218 CInterfaceElement *element = getElement(_Id+":dist");
219 if (element)
220 _DistView = dynamic_cast<CViewText*>(element);
223 if (_RadarView == NULL)
225 CInterfaceElement *element = getElement(_Id+":visuel:radar");
226 if (element)
227 _RadarView = dynamic_cast<CViewRadar*>(element);
230 if (_RadarRangeView == NULL)
232 CInterfaceElement *element = getElement(_Id+":visuel:range");
233 if (element)
234 _RadarRangeView = dynamic_cast<CViewText*>(element);
238 // ***************************************************************************
239 void CGroupCompas::blink()
241 _Blinking = true;
242 _StartBlinkTime = TimeInSec;
245 // ***************************************************************************
246 NLMISC::CVector2f CGroupCompas::getNorthPos(const NLMISC::CVector2f &userPos) const
248 return NLMISC::CVector2f(userPos.x, userPos.y + 1.f);
251 // ***************************************************************************
252 void CGroupCompas::draw()
254 if ((uint) _Target.getType() >= CCompassTarget::NumTypes) return;
255 CInterfaceManager *im = CInterfaceManager::getInstance();
257 if (_RadarView && _UseCameraObs._changed)
259 _UseCameraObs._changed = false;
260 _RadarView->setUseCamera(_UseCameraObs._useCamera);
264 const NLMISC::CVectorD &userPosD = UserEntity->pos();
265 NLMISC::CVector userPos((float) userPosD.x, (float) userPosD.y, (float) userPosD.z);
266 NLMISC::CVector2f targetPos(0.f, 0.f);
267 // if a position tracker is provided, use it
268 CCompassTarget displayedTarget = _Target;
269 float myAngle;
271 if (_UseCameraObs._useCamera)
273 CVector projectedFront = MainCam.getMatrix().getJ();
274 if (projectedFront.norm() <= 0.01f)
276 projectedFront = MainCam.getMatrix().getK();
277 projectedFront.z = 0.f;
279 CVector cam = projectedFront.normed();
280 myAngle = (float)atan2(cam.y, cam.x);
282 else
284 const CVector &front = UserEntity->front();
285 myAngle = (float)atan2 (front.y, front.x);
288 switch(_Target.getType())
290 case CCompassTarget::North:
291 targetPos.set(userPos.x, userPos.y + 1.f);
292 break;
293 case CCompassTarget::PosTracker:
295 sint32 x = 0, y = 0;
296 if (_Target.getPositionState())
298 if (_Target.getPositionState()->getPos(x, y))
300 targetPos.set(x * 0.001f, y * 0.001f);
303 if (x == 0 && y == 0)
305 displayedTarget = CCompassTarget();
306 targetPos = getNorthPos(userPos);
309 break;
310 case CCompassTarget::Selection:
312 if (UserEntity->selection() != CLFECOMMON::INVALID_SLOT && UserEntity->selection() != 0)
314 CEntityCL *sel = EntitiesMngr.entity(UserEntity->selection());
315 if (sel != NULL)
317 _Target.Name = sel->removeTitleAndShardFromName(sel->getEntityName());
318 if (_Target.Name.empty())
320 _Target.Name = sel->getTitle();
322 targetPos.set((float)sel->pos().x, (float)sel->pos().y);
325 else
327 displayedTarget = CCompassTarget();
328 targetPos = getNorthPos(userPos);
331 break;
332 case CCompassTarget::Home:
334 // get pos
335 CCDBNodeLeaf *pos = NLGUI::CDBManager::getInstance()->getDbProp(COMPASS_DB_PATH ":HOME_POINT");
336 sint32 px = (sint32) (pos->getValue64() >> 32);
337 sint32 py = pos->getValue32();
338 if (px != 0 || py != 0)
340 targetPos.set(px * 0.001f, py * 0.001f);
342 else
344 displayedTarget = CCompassTarget();
345 targetPos = getNorthPos(userPos);
348 break;
349 default:
350 targetPos = _Target.Pos;
351 break;
354 CRGBA color = _TargetTypeColor[displayedTarget.getType()];
356 // apply blinking color if there's one
357 if (_Blinking)
359 float dt = (float) (TimeInSec - _StartBlinkTime);
360 if (dt >= COMPASS_BLINK_TIME)
362 _Blinking = false;
364 else
366 float blinkAmount;
367 if (dt > COMPASS_BLINK_TIME * 0.5f)
369 blinkAmount = 2.f * (COMPASS_BLINK_TIME - dt);
371 else
373 blinkAmount = 2.f * dt;
375 color.blendFromui(color, _NewTargetSelectedColor, (uint8) (blinkAmount * 255.f));
379 // todo hulud add here guild and bots locations
381 if (_ArrowShape)
383 // Set the color
384 if (_ArrowShape->getShape().getNumMaterials()>0)
385 _ArrowShape->getShape().getMaterial(0).setDiffuse(color);
387 // Set angle
388 float deltaX = targetPos.x - userPos.x;
389 float deltaY = targetPos.y - userPos.y;
390 float targetAngle = (float)atan2 (deltaY, deltaX);
391 _ArrowShape->setRotZ ((float)(targetAngle - myAngle)*180.f/(float)Pi);
393 // Set the distance text
394 if (_DistView)
396 bool active = (ContinentMngr.cur() && !ContinentMngr.cur()->Indoor);
397 if (_DistView->getActive() != active)
398 _DistView->setActive (active);
400 if (active)
402 float dist = (float)sqrt(deltaX*deltaX+deltaY*deltaY);
404 // The text
405 char message[50];
406 string distText;
407 if (displayedTarget.getType() != CCompassTarget::North)
409 if (dist > 999.0f)
411 smprintf (message, 50, "%.1f ", dist/1000.0f);
412 distText = message + CI18N::get("uiKilometerUnit");
414 else
416 smprintf (message, 50, "%.0f ", dist);
417 distText = message + CI18N::get("uiMeterUnit");
419 distText = distText + " - " + displayedTarget.Name;
421 else
423 distText = displayedTarget.Name;
425 if (_DistViewText != distText)
427 _DistView->setText(distText);
428 _DistViewText = distText;
434 CCtrlBase *toolTip = getCtrl("tt");
435 if (toolTip)
437 if (displayedTarget.getType() != CCompassTarget::North)
438 toolTip->setDefaultContextHelp(CI18N::get("uittCompassDistance"));
439 else
440 toolTip->setDefaultContextHelp(std::string());
443 if (displayedTarget.Name != _CurrTargetName)
445 _CurrTargetName = displayedTarget.Name;
447 CGroupContainer::draw ();
450 // ***************************************************************************
452 bool CGroupCompas::handleEvent (const NLGUI::CEventDescriptor &event)
454 if (event.getType() == NLGUI::CEventDescriptor::mouse)
456 const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
458 if ((_RadarView != NULL) && (_RadarRangeView != NULL))
460 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel)
462 CInterfaceManager *pIM = CInterfaceManager::getInstance();
463 _RadarPos = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:RADARZOOM")->getValue32();
464 if (eventDesc.getWheel() > 0)
466 // Zoom out
467 if (_RadarPos > 0) _RadarPos--;
469 else
471 // Zoom in
472 if (_RadarPos < 3) _RadarPos++;
475 NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:RADARZOOM")->setValue32(_RadarPos);
480 return CGroupContainer::handleEvent(event);
484 // ***************************************************************************
486 void CGroupCompas::setTarget(const CCompassTarget &target)
488 if (_LastDynamicTargetPos != 0xFFFFFFFF)
490 _LastDynamicTargetPos = 0xFFFFFFFF;
491 // ask server for no dynamic target update
492 CBitMemStream out;
493 if (GenericMsgHeaderMngr.pushNameToStream("TARGET:COMPASS_NOT_DYNAMIC", out))
495 NetMngr.push(out);
496 //nlinfo("impulseCallBack : TARGET:COMPASS_NOT_DYNAMIC sent");
498 else
499 nlwarning(" unknown message name 'TARGET:COMPASS_NOT_DYNAMIC");
502 _Target = target;
503 _TargetSetOnce = true;
507 // ***************************************************************************
509 bool CGroupCompas::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
511 // Call parent
512 CGroupContainer::parse (cur, parentGroup);
514 // Look for the arrow shape
515 _ArrowShape = NULL;
517 CXMLAutoPtr ptr;
518 ptr = xmlGetProp (cur, (xmlChar*)"north_color");
519 if (ptr) _TargetTypeColor[CCompassTarget::North] = convertColor(ptr);
521 ptr = xmlGetProp (cur, (xmlChar*)"selection_color");
522 if (ptr) _TargetTypeColor[CCompassTarget::Selection] = convertColor(ptr);
524 ptr = xmlGetProp (cur, (xmlChar*)"home_color");
525 if (ptr) _TargetTypeColor[CCompassTarget::Home] = convertColor(ptr);
527 ptr = xmlGetProp (cur, (xmlChar*)"respawn_color");
528 if (ptr) _TargetTypeColor[CCompassTarget::Respawn] = convertColor(ptr);
530 ptr = xmlGetProp (cur, (xmlChar*)"continent_landmark_color");
531 if (ptr) _TargetTypeColor[CCompassTarget::ContinentLandMark] = convertColor(ptr);
533 ptr = xmlGetProp (cur, (xmlChar*)"mission_landmark_color");
534 if (ptr) _TargetTypeColor[CCompassTarget::PosTracker] = convertColor(ptr); // TODO : see if more colors are needed for animal, mission target, etc.
535 // for now same color for dyanmic tracking of position
537 ptr = xmlGetProp (cur, (xmlChar*)"user_landmark_color");
538 if (ptr) _TargetTypeColor[CCompassTarget::UserLandMark] = convertColor(ptr);
540 ptr = xmlGetProp (cur, (xmlChar*)"new_target_selected_color");
541 if (ptr) _NewTargetSelectedColor = convertColor(ptr);
544 _DynamicTargetPos = NLGUI::CDBManager::getInstance()->getDbProp(COMPASS_DB_PATH ":TARGET");
546 return true;
549 // ***************************************************************************
550 void CGroupCompas::CDBUseCameraObs::update( NLMISC::ICDBNode *node)
552 _changed = true;
553 _useCamera = ((CCDBNodeLeaf*)node)->getValueBool();
556 // ***************************************************************************
557 bool buildCompassTargetFromTeamMember(CCompassTarget &ct, uint teamMemberId)
559 CInterfaceManager *pIM= CInterfaceManager::getInstance();
561 CCDBNodeLeaf *entityNode = NLGUI::CDBManager::getInstance()->getDbProp(toString(TEAM_DB_PATH ":%d:UID", teamMemberId), false);
562 CCDBNodeLeaf *nameNode = NLGUI::CDBManager::getInstance()->getDbProp(toString(TEAM_DB_PATH ":%d:NAME", teamMemberId), false);
563 if (nameNode && nameNode->getValueBool() && entityNode && entityNode->getValue32()!=0 && nameNode)
565 CSmartPtr<CTeammatePositionState> tracker = new CTeammatePositionState;
566 tracker->build(toString(TEAM_DB_PATH ":%d", teamMemberId));
567 ct.setPositionState(tracker);
569 CStringManagerClient *pSMC = CStringManagerClient::instance();
570 string name;
571 if (pSMC->getString(nameNode->getValue32(), name))
572 ct.Name = CEntityCL::removeTitleAndShardFromName(name); // TODO : dynamic support for name
573 else
574 ct.Name = CI18N::get("uiNotReceived");
575 return true;
578 return false;
582 // ***************************************************************************
583 // 0..MAX_INVENTORY_ANIMAL
584 bool buildCompassTargetFromAnimalMember(CCompassTarget &ct, uint animalMemberId)
586 CInterfaceManager *pIM= CInterfaceManager::getInstance();
588 string dbBase;
589 if(animalMemberId<MAX_INVENTORY_ANIMAL+1)
591 ANIMAL_TYPE::EAnimalType at;
592 at = (ANIMAL_TYPE::EAnimalType)NLGUI::CDBManager::getInstance()->getDbProp("SERVER:PACK_ANIMAL:BEAST"+toString(animalMemberId-1)+":TYPE")->getValue32();
593 string sPrefix;
594 switch(at)
596 default:
597 case ANIMAL_TYPE::All: sPrefix = "uiPATitleMount"; break;
598 case ANIMAL_TYPE::Mount: sPrefix = "uiPATitleMount"; break;
599 case ANIMAL_TYPE::Packer: sPrefix = "uiPATitlePacker"; break;
600 case ANIMAL_TYPE::Demon: sPrefix = "uiPATitleDemon"; break;
603 dbBase= toString("SERVER:PACK_ANIMAL:BEAST%d", animalMemberId-1);
604 // +1, its normal, see en.uxt
605 ct.Name= CI18N::get(sPrefix+toString(animalMemberId));
607 else
608 return false;
610 // get if present or not
611 CCDBNodeLeaf *statusNode = NLGUI::CDBManager::getInstance()->getDbProp(dbBase + ":STATUS", false);
612 if (statusNode && ANIMAL_STATUS::isSpawned((ANIMAL_STATUS::EAnimalStatus)statusNode->getValue32()) )
614 CSmartPtr<CAnimalPositionState> tracker = new CAnimalPositionState;
615 tracker->build(dbBase);
616 ct.setPositionState(tracker);
617 return true;
620 return false;
624 // ***************************************************************************
625 NLMISC_REGISTER_OBJECT(CViewBase, CGroupCompasMenu, std::string, "menu_compas");
627 CGroupCompasMenu::CGroupCompasMenu(const TCtorParam &param)
628 : CGroupMenu(param)
632 // ***************************************************************************
634 CGroupCompasMenu::~CGroupCompasMenu()
638 // ***************************************************************************
639 bool CGroupCompasMenu::parse(xmlNodePtr cur, CInterfaceGroup *parent /*=NULL*/)
641 if (!CGroupMenu::parse(cur, parent)) return false;
642 CXMLAutoPtr compass((const char*) xmlGetProp (cur, (xmlChar*)"compass"));
643 if (compass) _TargetCompass = (const char *) compass;
644 return true;
647 // Helper for sorting landmarks
648 static inline bool UserLandMarksSortPredicate(const CUserLandMark& lm1, const CUserLandMark& lm2)
650 return toLower(lm1.Title) < toLower(lm2.Title);
653 // ***************************************************************************
654 // Called when we activate the compass menu
655 void CGroupCompasMenu::setActive (bool state)
657 if (state && getRootMenu())
659 CInterfaceManager *im = CInterfaceManager::getInstance();
660 uint k;
663 // **** First clear entries
664 // get first SubMenu.
665 uint numLines = getRootMenu()->getNumLines();
666 uint firstSubMenu = numLines;
667 for(k = 0; k < numLines; ++k)
669 if (getRootMenu()->getSubMenu(k))
671 firstSubMenu = k;
672 break;
675 // remove lines until first sub menu
676 for(k = 0; k < firstSubMenu; ++k)
678 getRootMenu()->removeLine(0);
681 // clear all possible targets
682 Targets.clear();
684 // Get the 3 sub menus now (since not so many lines)
685 CGroupSubMenu *missionSubMenu= NULL;
686 CGroupSubMenu *landMarkSubMenu= NULL;
687 CGroupSubMenu *teamSubMenu= NULL;
688 CGroupSubMenu *animalSubMenu= NULL;
689 CGroupSubMenu *dialogsSubMenu= NULL;
690 sint missionLineIndex= 0;
691 sint landMarkLineIndex= 0;
692 sint teamLineIndex= 0;
693 sint animalLineIndex= 0;
694 sint dialogLineIndex= 0;
695 numLines = getRootMenu()->getNumLines();
696 for(k=0;k<numLines;k++)
698 CGroupSubMenu *subMenu= getRootMenu()->getSubMenu(k);
699 if(subMenu)
701 if(getRootMenu()->getLineId(k)=="mission")
702 missionLineIndex= k, missionSubMenu= subMenu;
703 else if(getRootMenu()->getLineId(k)=="land_mark")
704 landMarkLineIndex= k, landMarkSubMenu= subMenu;
705 else if(getRootMenu()->getLineId(k)=="team")
706 teamLineIndex= k, teamSubMenu= subMenu;
707 else if(getRootMenu()->getLineId(k)=="animal")
708 animalLineIndex= k, animalSubMenu= subMenu;
709 else if(getRootMenu()->getLineId(k)=="dialogs")
710 dialogLineIndex= k, dialogsSubMenu= subMenu;
715 // **** append North/Target etc...
717 uint lineIndex = 0;
718 CCompassTarget ct;
719 // North
720 ct.setType(CCompassTarget::North);
721 ct.Name = CI18N::get("uiNorth");
722 Targets.push_back(ct);
723 getRootMenu()->addLineAtIndex(lineIndex ++, ct.Name, "set_compas", toString ("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
724 // Home
725 CCDBNodeLeaf *pos = NLGUI::CDBManager::getInstance()->getDbProp(COMPASS_DB_PATH ":HOME_POINT");
726 sint32 px = (sint32) (pos->getValue64() >> 32);
727 sint32 py = pos->getValue32();
728 if (px != 0 || py != 0)
730 ct.setType(CCompassTarget::Home);
731 ct.Name = CI18N::get("uiHome");
732 Targets.push_back(ct);
733 getRootMenu()->addLineAtIndex(lineIndex ++, ct.Name, "set_compas", toString ("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
735 // Respawn
736 pos = NLGUI::CDBManager::getInstance()->getDbProp(COMPASS_DB_PATH ":BIND_POINT");
737 px = (sint32) (pos->getValue64() >> 32);
738 py = pos->getValue32();
739 if (px != 0 || py != 0)
741 ct.setType(CCompassTarget::Respawn);
742 ct.Name = CI18N::get("uiRespawn");
743 Targets.push_back(ct);
744 getRootMenu()->addLineAtIndex(lineIndex ++, ct.Name, "set_compas", toString ("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
747 // As of 6/5/2007 : The option to point the selection is always proposed even if no slot is currently targeted
748 //if (UserEntity->selection() != CLFECOMMON::INVALID_SLOT && UserEntity->selection() != 0)
750 /*CEntityCL *entity = EntitiesMngr.entity(UserEntity->selection());
751 if (entity != NULL)
753 //string targetName = CI18N::get("uiTargetTwoPoint") + entity->removeTitleAndShardFromName(entity->getEntityName());
754 string targetName = CI18N::get("uiTarget");
755 ct.setType(CCompassTarget::Selection);
756 ct.Name = targetName;
757 Targets.push_back(ct);
758 getRootMenu()->addLineAtIndex(lineIndex ++, targetName, "set_compas", toString ("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
762 // increment Menu line indexes.
763 missionLineIndex+= lineIndex;
764 landMarkLineIndex+= lineIndex;
765 teamLineIndex+= lineIndex;
766 animalLineIndex+= lineIndex;
767 dialogLineIndex+= lineIndex;
770 // **** Append Mission in a SubMenu
771 // Mission landmarks
772 if(missionSubMenu)
774 // clear this sub menu
775 missionSubMenu->reset();
777 // and add each entry
778 bool selectable= false;
779 for(uint m = 0; m < 2; ++m) // deals with solo & group missions
781 std::string baseDbPath = m == 0 ? MISSIONS_DB_PATH : GROUP_MISSIONS_DB_PATH;
782 for(k = 0; k < MAX_NUM_MISSIONS; ++k)
784 for(uint l = 0; l <MAX_NUM_MISSION_TARGETS; ++l)
786 CCDBNodeLeaf *textIDLeaf = NLGUI::CDBManager::getInstance()->getDbProp(baseDbPath + toString(":%d:TARGET%d:TITLE", (int) k, (int) l), false);
787 if (textIDLeaf)
789 string name;
790 if (CStringManagerClient::instance()->getDynString(textIDLeaf->getValue32(), name))
792 CCDBNodeLeaf *leafPosX= NLGUI::CDBManager::getInstance()->getDbProp(baseDbPath + toString(":%d:TARGET%d:X", (int) k, (int) l), false);
793 CCDBNodeLeaf *leafPosY = NLGUI::CDBManager::getInstance()->getDbProp(baseDbPath + toString(":%d:TARGET%d:Y", (int) k, (int) l), false);
794 if (leafPosX && leafPosY)
796 CCompassTarget ct;
797 CSmartPtr<CNamedEntityPositionState> tracker = new CNamedEntityPositionState;
798 tracker->build(textIDLeaf, leafPosX, leafPosY);
799 ct.setPositionState(tracker);
800 ct.Name = name;
801 Targets.push_back(ct);
802 missionSubMenu->addLine(ct.Name, "set_compas", toString("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
803 selectable= true;
810 // Not Empty?
811 getRootMenu()->setSelectable(missionLineIndex, selectable);
812 getRootMenu()->setGrayedLine(missionLineIndex, !selectable);
815 // **** Append LandMarks in a SubMenu
816 if(landMarkSubMenu)
818 uint numLMLines = landMarkSubMenu->getNumLines();
819 uint firstLMSubMenu = numLMLines;
820 for(k = 0; k < numLMLines; ++k)
822 if (landMarkSubMenu->getSubMenu(k))
824 firstLMSubMenu = k;
825 break;
828 // remove lines until first sub menu
829 for(k = 0; k < firstLMSubMenu; ++k)
831 landMarkSubMenu->removeLine(0);
834 // Get the userlm sub menus now (before adding the continent lm)
835 std::vector<CGroupSubMenu*> landMarkSubMenus;
836 landMarkSubMenus.resize(CUserLandMark::UserLandMarkTypeCount);
838 for(k=0;k<landMarkSubMenus.size();k++)
840 landMarkSubMenus[k] = landMarkSubMenu->getSubMenu(k);
841 landMarkSubMenus[k]->reset();
844 CContinent *currCont = ContinentMngr.cur();
845 bool selectable= false;
846 if (currCont)
848 uint contLandMarkIndex = 0;
849 // Continent landmarks
850 for(k = 0; k < currCont->ContLandMarks.size(); ++k)
851 if ((currCont->ContLandMarks[k].Type == CContLandMark::Capital) ||
852 (currCont->ContLandMarks[k].Type == CContLandMark::Village))
854 CCompassTarget ct;
855 ct.setType(CCompassTarget::ContinentLandMark);
856 ct.Pos = currCont->ContLandMarks[k].Pos;
857 ct.Name = CStringManagerClient::getPlaceLocalizedName(currCont->ContLandMarks[k].TitleTextID);
858 Targets.push_back(ct);
859 landMarkSubMenu->addLineAtIndex(contLandMarkIndex++, ct.Name, "set_compas", toString("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
860 selectable= true;
862 // separator?
863 if (currCont->ContLandMarks.size() != 0 && currCont->UserLandMarks.size() != 0)
865 landMarkSubMenu->addSeparatorAtIndex(contLandMarkIndex++);
868 // User landmarks
869 // Sort the landmarks
870 std::vector<CUserLandMark> sortedLandmarks(currCont->UserLandMarks);
871 std::sort(sortedLandmarks.begin(), sortedLandmarks.end(), UserLandMarksSortPredicate);
873 for(k = 0; k < sortedLandmarks.size(); ++k)
875 if (sortedLandmarks[k].Type < CUserLandMark::UserLandMarkTypeCount)
877 CCompassTarget ct;
878 ct.setType(CCompassTarget::UserLandMark);
879 ct.Pos = sortedLandmarks[k].Pos;
880 ct.Name = sortedLandmarks[k].Title.toUtf8();
881 Targets.push_back(ct);
882 landMarkSubMenus[sortedLandmarks[k].Type]->addLine(ct.Name, "set_compas", toString("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
883 selectable= true;
887 // Not Empty?
888 for(k=0;k<landMarkSubMenus.size();k++)
890 landMarkSubMenu->setHiddenLine(k + contLandMarkIndex, landMarkSubMenus[k]->getNumLines() <= 0);
895 // Not Empty?
896 getRootMenu()->setSelectable(landMarkLineIndex, selectable);
897 getRootMenu()->setGrayedLine(landMarkLineIndex, !selectable);
900 // **** Append Team Members in a SubMenu
901 if(teamSubMenu)
903 // clear this sub menu
904 teamSubMenu->reset();
906 bool selectable= false;
907 for (k = 0; k < MaxNumPeopleInTeam; k++)
909 CCompassTarget ct;
910 if (buildCompassTargetFromTeamMember(ct, k))
912 Targets.push_back(ct);
913 teamSubMenu->addLine(ct.Name, "set_compas", toString("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
914 selectable= true;
918 // Not Empty?
919 getRootMenu()->setSelectable(teamLineIndex, selectable);
920 getRootMenu()->setGrayedLine(teamLineIndex, !selectable);
923 // **** Append Animal Members in a SubMenu
924 if(animalSubMenu)
926 // clear this sub menu
927 animalSubMenu->reset();
929 bool selectable= false;
930 for (k = 0; k < 1 + MAX_INVENTORY_ANIMAL+1; k++)
932 CCompassTarget ct;
933 if (buildCompassTargetFromAnimalMember(ct, k))
935 Targets.push_back(ct);
936 animalSubMenu->addLine(ct.Name, "set_compas", toString("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
937 selectable= true;
941 // Not Empty?
942 getRootMenu()->setSelectable(animalLineIndex, selectable);
943 getRootMenu()->setGrayedLine(animalLineIndex, !selectable);
946 // **** Append Dialogs Members in a SubMenu
947 if(dialogsSubMenu)
949 // clear this sub menu
950 dialogsSubMenu->reset();
951 bool selectable= false;
953 // and add each entry
954 const std::vector<CCompassDialogsManager::CCompassDialogsEntry> & entries = CCompassDialogsManager::getInstance().getEntries();
955 const uint size = (uint)entries.size();
956 for( uint i = 0; i < size; ++i)
958 CCompassTarget ct;
959 if (CStringManagerClient::instance()->getDynString(entries[i].Text, ct.Name))
961 CSmartPtr<CDialogEntityPositionState> tracker = new CDialogEntityPositionState( i );
962 ct.setPositionState(tracker);
963 Targets.push_back(ct);
964 dialogsSubMenu->addLine(ct.Name, "set_compas", toString("compass=%s|id=%d|menu=%s", _TargetCompass.c_str(), (int) Targets.size() - 1, _Id.c_str()));
965 selectable= true;
968 // Not Empty?
969 getRootMenu()->setSelectable(dialogLineIndex, selectable);
970 getRootMenu()->setGrayedLine(dialogLineIndex, !selectable);
974 CGroupMenu::setActive (state);
977 // ***************************************************************************
978 // Called from a compass menu
979 class CHandlerSetCompas : public IActionHandler
981 void execute (CCtrlBase * /* pCaller */, const std::string &sParams)
983 std::string compassID = getParam(sParams, "compass");
984 std::string menuID = getParam(sParams, "menu");
985 CInterfaceManager *im = CInterfaceManager::getInstance();
986 CGroupCompas *gc = dynamic_cast<CGroupCompas *>(CWidgetManager::getInstance()->getElementFromId(compassID));
987 if (!gc) return;
988 CGroupCompasMenu *gcm = dynamic_cast<CGroupCompasMenu *>(CWidgetManager::getInstance()->getElementFromId(menuID));
989 if (!gcm) return;
990 int index;
991 std::string id = getParam(sParams, "id");
992 if (!fromString(id, index)) return;
993 if ((uint) index < (uint) gcm->Targets.size())
995 gc->setTarget(gcm->Targets[index]);
996 gc->setActive(true);
997 gc->blink();
998 CWidgetManager::getInstance()->setTopWindow(gc);
1002 REGISTER_ACTION_HANDLER( CHandlerSetCompas, "set_compas");
1005 // ***************************************************************************
1006 // Called from a Team member menu
1007 class CHandlerSetTeamCompas : public IActionHandler
1009 void execute (CCtrlBase * /* pCaller */, const std::string &sParams)
1011 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1013 // get the compass window
1014 std::string compassID = getParam(sParams, "compass");
1016 // Get the team member index
1017 CPeopleList *list;
1018 uint peopleIndex;
1019 if (PeopleInterraction.getPeopleFromCurrentMenu(list, peopleIndex))
1021 if (list == &PeopleInterraction.TeamList) // check for good list
1023 // If can CompassTarget this team member
1024 CCompassTarget ct;
1025 if(buildCompassTargetFromTeamMember(ct, peopleIndex))
1027 CGroupCompas *gc= dynamic_cast<CGroupCompas*>(CWidgetManager::getInstance()->getElementFromId(compassID));
1028 if(gc)
1030 gc->setTarget(ct);
1031 gc->setActive(true);
1032 gc->blink();
1033 CWidgetManager::getInstance()->setTopWindow(gc);
1040 REGISTER_ACTION_HANDLER( CHandlerSetTeamCompas, "set_team_compas");
1042 // ***************************************************************************
1043 class CHandlerSetCompassNorth : public IActionHandler
1045 void execute (CCtrlBase * /* pCaller */, const std::string &sParams)
1047 std::string compassID = getParam(sParams, "compass");
1048 CInterfaceManager *im = CInterfaceManager::getInstance();
1049 CGroupCompas *gc = dynamic_cast<CGroupCompas *>(CWidgetManager::getInstance()->getElementFromId(compassID));
1050 if (!gc) return;
1051 gc->setTarget(CCompassTarget());
1054 REGISTER_ACTION_HANDLER( CHandlerSetCompassNorth, "set_compass_north");
1057 class CCompassDialogsStringCallback : public IStringWaitCallback
1059 virtual void onDynStringAvailable(uint /* stringId */, const std::string &value)
1061 uint size = (uint)CCompassDialogsManager::getInstance()._Entries.size();
1062 for ( uint i = 0; i < size; i++)
1064 std::string name;
1065 if ( CStringManagerClient::instance()->getDynString(CCompassDialogsManager::getInstance()._Entries[i].Text, name) )
1067 if ( value == name )
1069 CCompassDialogsManager::getInstance()._Entries[i] = CCompassDialogsManager::getInstance()._Entries.back();
1070 CCompassDialogsManager::getInstance()._Entries.pop_back();
1071 break;
1079 void CCompassDialogsManager::removeEntry(uint32 text)
1081 CCompassDialogsStringCallback * callback = new CCompassDialogsStringCallback;
1082 CStringManagerClient::instance()->waitDynString( text,callback );