khanat-opennel-code/code/ryzom/client/src/interface_v3/view_pointer.cpp
2012-04-28 21:36:39 +02:00

778 lines
22 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "../input.h"
//
#include "view_pointer.h"
#include "interface_manager.h"
#include "view_renderer.h"
#include "ctrl_col_pick.h"
#include "group_paragraph.h"
#include "group_html.h"
#include "group_map.h"
//
#include "nel/misc/xml_auto_ptr.h"
//
#include "group_container.h"
#include "interface_3d_scene.h"
//
#include "../r2/editor.h"
using namespace std;
using namespace NLMISC;
NLMISC_REGISTER_OBJECT(CViewBase, CViewPointer, std::string, "pointer");
// --------------------------------------------------------------------------------------------------------------------
CViewPointer::CViewPointer (const TCtorParam &param)
: CViewBase(param),
_Buttons(NLMISC::noButton)
{
_PointerX = _PointerY = _PointerOldX = _PointerOldY = _PointerDownX = _PointerDownY = 0;
_PointerDown = false;
_PointerVisible = true;
_TxIdDefault = -2;
_TxIdMoveWindow = -2;
_TxIdResizeBRTL = -2;
_TxIdResizeBLTR = -2;
_TxIdResizeTB = -2;
_TxIdResizeLR = -2;
_TxIdRotate = -2;
_TxIdScale = -2;
_TxIdColPick = -2;
_TxIdPan = -2;
_TxIdCanPan = -2;
_TxIdPanR2 = -2;
_TxIdCanPanR2 = -2;
// The pointer must be draw over ALL layers
_RenderLayer= VR_LAYER_MAX;
_Color = CRGBA(255,255,255,255);
_LastHightLight = NULL;
_StringMode = false;
_ForceStringMode = false;
_StringCursor = NULL;
}
// +++ VIEW SPECIFIC +++
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::parse (xmlNodePtr cur,CInterfaceGroup * parentGroup)
{
CXMLAutoPtr prop;
if (! CViewBase::parse(cur, parentGroup) )
return false;
_OffsetX = getX();
_OffsetY = getY();
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_default");
if (prop) _TxDefault = (const char *) prop;
_TxDefault = NLMISC::strlwr (_TxDefault);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_move_window");
if (prop) _TxMoveWindow = (const char *) prop;
_TxMoveWindow = NLMISC::strlwr (_TxMoveWindow);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_resize_BR_TL");
if (prop) _TxResizeBRTL = (const char *) prop;
_TxResizeBRTL = NLMISC::strlwr (_TxResizeBRTL);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_resize_BL_TR");
if (prop) _TxResizeBLTR = (const char *) prop;
_TxResizeBLTR = NLMISC::strlwr (_TxResizeBLTR);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_resize_TB");
if (prop) _TxResizeTB = (const char *) prop;
_TxResizeTB = NLMISC::strlwr (_TxResizeTB);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_resize_LR");
if (prop) _TxResizeLR = (const char *) prop;
_TxResizeLR = NLMISC::strlwr (_TxResizeLR);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_rotate");
if (prop) _TxRotate = (const char *) prop;
_TxRotate = NLMISC::strlwr (_TxRotate);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_scale");
if (prop) _TxScale = (const char *) prop;
_TxScale = NLMISC::strlwr (_TxScale);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_colpick");
if (prop) _TxColPick = (const char *) prop;
_TxColPick = NLMISC::strlwr (_TxColPick);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_pan");
if (prop) _TxPan = (const char *) prop;
_TxPan = NLMISC::strlwr (_TxPan);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_can_pan");
if (prop) _TxCanPan = (const char *) prop;
_TxCanPan = NLMISC::strlwr (_TxCanPan);
if (ClientCfg.R2EDEnabled)
{
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_pan_r2");
if (prop) _TxPanR2 = (const char *) prop;
_TxPanR2 = NLMISC::strlwr (_TxPanR2);
prop = (char*) xmlGetProp (cur, (xmlChar*)"tx_can_pan_r2");
if (prop) _TxCanPanR2 = (const char *) prop;
_TxCanPanR2 = NLMISC::strlwr (_TxCanPanR2);
}
prop = (char*) xmlGetProp (cur, (xmlChar*)"color");
if (prop) _Color = convertColor(prop);
return true;
}
// --------------------------------------------------------------------------------------------------------------------
class CCtrlDepthEntry
{
public:
CCtrlBase *Ctrl;
uint Depth;
bool operator<(const CCtrlDepthEntry &o) const
{
// Inverse Test => descending order
return Depth>o.Depth;
}
};
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::draw ()
{
// Do not display the pointer if not visible.
if(!_PointerVisible)
return;
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewRenderer &rVR = pIM->getViewRenderer();
if (pIM->isInGame())
if (!_StringCursor)
{
// Create the string cursor instance
std::vector<std::pair<std::string,std::string> > templateParams;
templateParams.push_back (std::pair<std::string,std::string>("id", "string_cursor"));
_StringCursor = pIM->createGroupInstance("string_cursor", "", templateParams);
if (_StringCursor)
_StringCursor->setParentPos(pIM->getElementFromId("ui:interface"));
templateParams.clear();
templateParams.push_back (std::pair<std::string,std::string>("id", "string_cursor_hardware"));
_StringCursorHardware = pIM->createGroupInstance("string_cursor_hardware", "", templateParams);
if (_StringCursorHardware)
_StringCursorHardware->setParentPos(pIM->getElementFromId("ui:interface"));
}
CRGBA col;
if(getModulateGlobalColor())
col.modulateFromColor (_Color, pIM->getGlobalColor());
else
col= _Color;
//col.A = (uint8)(((sint32)col.A*((sint32)pIM->getGlobalColor().A+1))>>8);
col.A = _Color.A;
if (_LastHightLight != NULL)
{
_LastHightLight->setHighLighted(false,0);
_LastHightLight = NULL;
}
if (pIM->getCapturePointerLeft() != NULL && pIM->isMouseHandlingEnabled())
{
CCtrlMover *pCM = dynamic_cast<CCtrlMover*>(pIM->getCapturePointerLeft());
if ((pCM != NULL) && (pCM->canMove() == true))
{
CGroupContainer *pGC = dynamic_cast<CGroupContainer *>(pCM->getParent());
if (pGC != NULL && !pGC->isLocked())
{
pGC->setHighLighted(true, 255);
_LastHightLight = pGC;
}
}
}
if (_TxIdDefault == -2)
{
_TxIdDefault = rVR.getTextureIdFromName (_TxDefault);
_TxIdMoveWindow = rVR.getTextureIdFromName (_TxMoveWindow);
_TxIdResizeBRTL = rVR.getTextureIdFromName (_TxResizeBRTL);
_TxIdResizeBLTR = rVR.getTextureIdFromName (_TxResizeBLTR);
_TxIdResizeTB = rVR.getTextureIdFromName (_TxResizeTB);
_TxIdResizeLR = rVR.getTextureIdFromName (_TxResizeLR);
_TxIdRotate = rVR.getTextureIdFromName (_TxRotate);
_TxIdScale = rVR.getTextureIdFromName (_TxScale);
_TxIdColPick = rVR.getTextureIdFromName (_TxColPick);
_TxIdPan = rVR.getTextureIdFromName (_TxPan);
_TxIdCanPan = rVR.getTextureIdFromName (_TxCanPan);
if (ClientCfg.R2EDEnabled)
{
_TxIdPanR2 = rVR.getTextureIdFromName (_TxPanR2);
_TxIdCanPanR2 = rVR.getTextureIdFromName (_TxCanPanR2);
}
}
const vector<CCtrlBase *> &rICL = pIM->getCtrlsUnderPointer ();
// Draw the captured cursor
CCtrlBase *pCB = pIM->getCapturePointerLeft();
if (pCB != NULL)
{
if (drawResizer(pCB,col)) return;
//if (drawMover(pCB,col)) return;
if (drawColorPicker(pCB,col)) return;
if (drawRotate(pCB,col)) return;
if (drawPan(pCB,col)) return;
if (drawCustom(pCB)) return;
drawCursor(_TxIdDefault, col, 0);
return;
}
const vector<CViewBase *> &vUP = pIM->getViewsUnderPointer ();
for(uint i=0;i<vUP.size();i++)
{
CViewLink *vLink = dynamic_cast<CViewLink*>(vUP[i]);
if (vLink != NULL)
{
string tooltip;
uint8 rot;
if (vLink->getMouseOverShape(tooltip, rot, col))
{
setString(ucstring(tooltip));
sint32 texId = rVR.getTextureIdFromName ("curs_pick.tga");
CInterfaceGroup *stringCursor = IsMouseCursorHardware() ? _StringCursorHardware : _StringCursor;
if (stringCursor)
{
stringCursor->setX(_PointerX);
stringCursor->setY(_PointerY);
stringCursor->updateCoords();
stringCursor->draw();
// if in hardware mode, force to draw the default cursor no matter what..
if (IsMouseCursorHardware())
drawCursor(texId, col, 0);
}
else
{
drawCursor(texId, col, 0);
}
return;
}
}
}
// Draw if capture right
pCB = pIM->getCapturePointerRight();
if (pCB != NULL)
{
// Is it a 3d scene ?
if (drawScale(pCB,col)) return;
drawCursor(_TxIdDefault, col, 0);
return;
}
bool overModalWindow = false;
// is the cursor currently over a modal window ?
CInterfaceGroup *currModal = pIM->getModalWindow();
if (currModal)
{
sint32 xPos = _XReal + _OffsetX;
sint32 yPos = _YReal + _OffsetY;
overModalWindow = currModal->isIn(xPos, yPos, _WReal, _HReal);
}
// Draw the cursor type that are under the pointer
if (pIM->isMouseHandlingEnabled())
{
// Sorts the controls according to their depth, to approximate as best the CapturePointerLeft algo.
// Especially important so that Resizers controls get the precedence over the move control (else could randomly bug like in chat group)
static vector<CCtrlDepthEntry> sortedControls;
sortedControls.clear();
for(uint i=0;i<rICL.size();i++)
{
CCtrlDepthEntry cde;
cde.Ctrl= rICL[i];
// NB: not the exact CInterfaceManager getDepth test here, but should work fine
cde.Depth= cde.Ctrl->getParentDepth() + cde.Ctrl->getDeltaDepth();
sortedControls.push_back(cde);
}
std::sort(sortedControls.begin(), sortedControls.end());
// Then draw the correct cursor
for (uint32 i = 0; i < sortedControls.size(); ++i)
{
CCtrlBase *pCB = sortedControls[i].Ctrl;
if (overModalWindow)
{
if (!pCB->isSonOf(currModal)) continue;
}
if (drawBrowse(pCB, col)) return;
if (drawResizer(pCB,col)) return;
if (drawColorPicker(pCB,col)) return;
if (drawLink (pCB, col)) return;
if (drawCustom(pCB)) return;
// test for move highlight
if (_LastHightLight == NULL)
{
CCtrlMover *pCM = dynamic_cast<CCtrlMover*>(pCB);
if ( (pCM != NULL) && (pCM->canMove() == true) )
{
CGroupContainer *pGC = dynamic_cast<CGroupContainer *>(pCM->getParent());
if (pGC != NULL && !pGC->isLocked())
{
if (pIM->getCapturePointerLeft() != pCM)
pGC->setHighLighted(true, 128);
else
pGC->setHighLighted(true, 255);
_LastHightLight = pGC;
break;
}
}
}
//if (drawMover(pCB,col)) return;
}
}
if (pIM->isMouseHandlingEnabled())
{
if (rICL.empty())
{
const vector<CInterfaceGroup *> &rIGL = pIM->getGroupsUnderPointer ();
for (uint32 i = 0; i < rIGL.size(); ++i)
{
CInterfaceGroup *pG = rIGL[i];
if (overModalWindow)
{
if (!pG->isSonOf(currModal)) continue;
}
if (drawPan (pG, col)) return;
if (drawBrowse(pG, col)) return;
}
}
}
if (_StringMode && pIM->isMouseHandlingEnabled())
{
CInterfaceGroup *stringCursor = IsMouseCursorHardware() ? _StringCursorHardware : _StringCursor;
if (stringCursor)
{
stringCursor->setX(_PointerX);
stringCursor->setY(_PointerY);
stringCursor->updateCoords();
stringCursor->draw();
// if in hardware mode, force to draw the default cursor no matter what..
if (IsMouseCursorHardware())
{
drawCursor(_TxIdDefault, col, 0);
}
}
}
else
{
// Draw the default cursor
drawCursor(_TxIdDefault, col, 0);
}
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawResizer(CCtrlBase* pCB, CRGBA col)
{
CCtrlResizer *pCR = dynamic_cast<CCtrlResizer*>(pCB);
if (pCR != NULL)
{
CGroupContainer *parent = dynamic_cast<CGroupContainer *>(pCR->getParent());
if (parent && !parent->isLocked())
{
sint32 texID= -1;
switch(pCR->getRealResizerPos())
{
case Hotspot_BR:
case Hotspot_TL:
texID = _TxIdResizeBRTL;
break;
case Hotspot_BL:
case Hotspot_TR:
texID = _TxIdResizeBLTR;
break;
case Hotspot_MR:
case Hotspot_ML:
texID = _TxIdResizeLR;
break;
case Hotspot_TM:
case Hotspot_BM:
texID = _TxIdResizeTB;
break;
default:
return false;
break;
}
drawCursor(texID, col, false);
return true;
}
}
return false;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawMover(CCtrlBase* pCB, CRGBA col)
{
CCtrlMover *pCM = dynamic_cast<CCtrlMover*>(pCB);
if ((pCM != NULL) && (pCM->canMove() == true))
{
drawCursor(_TxIdMoveWindow, col, 0);
return true;
}
return false;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawRotate (CCtrlBase* pCB, CRGBA col)
{
CInterface3DScene *pI3DS = dynamic_cast<CInterface3DScene *>(pCB);
if (pI3DS != NULL)
{
drawCursor(_TxIdRotate, col, 0);
return true;
}
return false;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawScale (CCtrlBase* pCB, CRGBA col)
{
CInterface3DScene *pI3DS = dynamic_cast<CInterface3DScene *>(pCB);
if (pI3DS != NULL)
{
drawCursor(_TxIdScale, col, 0);
return true;
}
return false;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawColorPicker (CCtrlBase* pCB, CRGBA col)
{
CCtrlColPick *pCCP = dynamic_cast<CCtrlColPick*>(pCB);
if (pCCP != NULL)
{
drawCursor(_TxIdColPick, col, 0);
return true;
}
return false;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawLink (CCtrlBase* pCB, CRGBA col)
{
CCtrlLink *pCCP = dynamic_cast<CCtrlLink*>(pCB);
if (pCCP != NULL)
{
drawCursor(_TxIdColPick, col, 0);
return true;
}
return false;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawBrowse (CCtrlBase* pCB, CRGBA col)
{
CGroupHTML *pCGH = dynamic_cast<CGroupHTML *>(pCB);
if (pCGH != NULL)
{
if (pCGH->isBrowsing())
{
static uint8 rot =0;
drawCursor(_TxIdRotate, col, rot>>3);
rot = (rot+1) & 0x1f;
return true;
}
}
return false;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawPan(CCtrlBase* pCB, NLMISC::CRGBA col)
{
CGroupMap *gm = dynamic_cast<CGroupMap *>(pCB);
if (gm)
{
sint32 texId;
if (ClientCfg.R2EDEnabled && R2::getEditor().getCurrentTool())
{
/** If cursor is set to anything other than the default cursor, use that cursor (because action can be performed on the map
* by the current tool
*/
if (_TxDefault == "curs_default.tga")
{
texId = gm->isPanning() ? _TxIdPanR2 : _TxIdCanPanR2;
}
else return false;
}
else
{
texId = gm->isPanning() ? _TxIdPan : _TxIdCanPan;
}
drawCursor(texId, col, 0);
return true;
}
return false;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::drawCustom(CCtrlBase* pCB)
{
string texName;
uint8 rot;
NLMISC::CRGBA col;
if (pCB->getMouseOverShape(texName, rot, col))
{
if (texName[0] == '@')
{
const string &tooltipInfos = texName.substr(1);
string tooltip;
vector<string> tooltipInfosList;
splitString(tooltipInfos, "@", tooltipInfosList);
texName = tooltipInfosList[0];
tooltip = tooltipInfosList[1];
nlinfo(tooltip.c_str());
setString(ucstring(tooltip));
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewRenderer &rVR = pIM->getViewRenderer();
sint32 texId = rVR.getTextureIdFromName (texName);
CInterfaceGroup *stringCursor = IsMouseCursorHardware() ? _StringCursorHardware : _StringCursor;
if (stringCursor)
{
stringCursor->setX(_PointerX);
stringCursor->setY(_PointerY);
stringCursor->updateCoords();
stringCursor->draw();
// if in hardware mode, force to draw the default cursor no matter what..
if (IsMouseCursorHardware())
drawCursor(texId, col, 0);
}
else
{
drawCursor(texId, col, 0);
}
return true;
}
else
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewRenderer &rVR = pIM->getViewRenderer();
sint32 texId = rVR.getTextureIdFromName (texName);
drawCursor(texId, col, 0);
return true;
}
}
return false;
}
// +++ SET +++
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::setPointerPos (sint32 x, sint32 y)
{
if (_PointerDown)
{
if (!_PointerDrag)
{
if (((_PointerX - _PointerDownX) != 0) ||
((_PointerY - _PointerDownY) != 0))
{
_PointerDrag = true;
}
}
}
_PointerOldX = getX();
_PointerOldY = getY();
_PointerX = x;
_PointerY = y;
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::setPointerDispPos (sint32 x, sint32 y)
{
setX (x);
setY (y);
updateCoords ();
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::resetPointerPos ()
{
_PointerOldX = _PointerX;
_PointerOldY = _PointerY;
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::setPointerDown (bool pd)
{
_PointerDown = pd;
if (_PointerDown == true)
{
_PointerDownX = _PointerX;
_PointerDownY = _PointerY;
}
if (_PointerDown == false)
_PointerDrag = false;
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::setPointerDownString (const std::string &s)
{
_PointerDownString = s;
}
// +++ GET +++
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::getPointerPos (sint32 &x, sint32 &y)
{
x = _PointerX;
y = _PointerY;
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::getPointerDispPos (sint32 &x, sint32 &y)
{
x = getX();
y = getY();
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::getPointerOldPos (sint32 &x, sint32 &y)
{
x = _PointerOldX;
y = _PointerOldY;
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::getPointerDownPos (sint32 &x, sint32 &y)
{
x = _PointerDownX;
y = _PointerDownY;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::getPointerDown ()
{
return _PointerDown;
}
// --------------------------------------------------------------------------------------------------------------------
bool CViewPointer::getPointerDrag ()
{
return _PointerDrag;
}
// --------------------------------------------------------------------------------------------------------------------
std::string CViewPointer::getPointerDownString ()
{
return _PointerDownString;
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::setStringMode (bool stringCursor)
{
_StringMode = stringCursor;
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::setString (const ucstring &str, CInterfaceGroup *target)
{
if (target)
{
CInterfaceElement *element = target->getView ("fake_txt");
if (element)
{
CViewText *text = dynamic_cast<CViewText*> (element);
if (text)
text->setText(str);
}
element = target->getView ("real_txt");
if (element)
{
CViewText *text = dynamic_cast<CViewText*> (element);
if (text)
text->setText(str);
}
target->updateCoords();
target->updateCoords();
_ContextString = str;
}
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::setString (const ucstring &str)
{
if (_ContextString != str)
{
setString(str, _StringCursor);
setString(str, _StringCursorHardware);
}
}
// --------------------------------------------------------------------------------------------------------------------
void CViewPointer::drawCursor(sint32 texId, NLMISC::CRGBA col, uint8 rot)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewRenderer &rVR = pIM->getViewRenderer();
sint32 xPos = _XReal + _OffsetX;
sint32 yPos = _YReal + _OffsetY;
if (!IsMouseCursorHardware())
{
rVR.draw11RotFlipBitmap (_RenderLayer, xPos, yPos, rot, false, texId, col);
}
else
{
// set new cursor for the hardware mouse
std::string name = rVR.getTextureNameFromId(texId);
rVR.getDriver()->setCursor(name, col, rot, (uint32) std::max(getX() - xPos, (sint32) 0), (uint32) std::max(getY() - yPos, (sint32) 0));
}
}