mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-11-07 15:59:02 +00:00
580 lines
16 KiB
C++
580 lines
16 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 "view_bitmap_combo.h"
|
|
#include "interface_manager.h"
|
|
#include "game_share/xml_auto_ptr.h"
|
|
|
|
using namespace NLMISC;
|
|
|
|
//=======================================================================================
|
|
bool CComboBoxDesc::parse(xmlNodePtr cur, CInterfaceElement*owner)
|
|
{
|
|
nlassert(owner);
|
|
const std::string &ownerId = owner->getId();
|
|
CXMLAutoPtr prop;
|
|
//
|
|
prop = xmlGetProp(cur, (const xmlChar *) "selected");
|
|
if (!prop)
|
|
{
|
|
nlwarning((ownerId + " : Couldn't read 'selected' field").c_str());
|
|
return false;
|
|
}
|
|
owner->relativeSInt64Read(CurrSelected, "selected", prop, "0");
|
|
//
|
|
prop = xmlGetProp(cur, (const xmlChar *) "num_row");
|
|
owner->relativeSInt64Read(NumRow, "num_row", prop, "1");
|
|
//
|
|
prop = xmlGetProp(cur, (const xmlChar *) "num_col");
|
|
owner->relativeSInt64Read(NumCol, "num_col", prop, "1");
|
|
//
|
|
prop = xmlGetProp(cur, (const xmlChar *) "itemw");
|
|
owner->relativeSInt64Read(ItemWidth, "itemw", prop, "32");
|
|
//
|
|
prop = xmlGetProp(cur, (const xmlChar *) "itemh");
|
|
owner->relativeSInt64Read(ItemHeight, "itemh", prop, "32");
|
|
//
|
|
prop = xmlGetProp(cur, (const xmlChar *) "unrolled");
|
|
owner->relativeBoolRead(Unrolled, "unrolled", prop, "false");
|
|
//
|
|
prop = xmlGetProp(cur, (xmlChar *) "wgap");
|
|
owner->relativeSInt64Read(WGap, "wgap", prop, "0");
|
|
//
|
|
prop = xmlGetProp(cur, (xmlChar *) "hgap");
|
|
owner->relativeSInt64Read(HGap, "hgap", prop, "0");
|
|
//
|
|
prop = xmlGetProp(cur, (xmlChar *) "wgap_selected");
|
|
owner->relativeSInt64Read(WGapSelected, "wgap_selected", prop, "0");
|
|
//
|
|
prop = xmlGetProp(cur, (xmlChar *) "hgap_selected");
|
|
owner->relativeSInt64Read(HGapSelected, "hgap_selected", prop, "0");
|
|
//
|
|
//
|
|
prop = xmlGetProp(cur, (xmlChar *) "num_sel");
|
|
owner->relativeSInt64Read(NumSel, "num_sel", prop, "1");
|
|
//
|
|
prop = (char*) xmlGetProp (cur, (xmlChar*)"align");
|
|
Align.readSInt32 ("0", ownerId + ":align");
|
|
if (prop)
|
|
{
|
|
const char *seekPtr = prop.getDatas();
|
|
while (*seekPtr != 0)
|
|
{
|
|
if ((*seekPtr=='l')||(*seekPtr=='L'))
|
|
{
|
|
Align.setSInt32 (Align.getSInt32()&(~1));
|
|
}
|
|
if ((*seekPtr=='r')||(*seekPtr=='R'))
|
|
{
|
|
Align.setSInt32 (Align.getSInt32()|1);
|
|
}
|
|
if ((*seekPtr=='b')||(*seekPtr=='B'))
|
|
{
|
|
Align.setSInt32 (Align.getSInt32()&(~2));
|
|
}
|
|
if ((*seekPtr=='t')||(*seekPtr=='T'))
|
|
{
|
|
Align.setSInt32 (Align.getSInt32()|2);
|
|
}
|
|
++seekPtr;
|
|
}
|
|
}
|
|
//
|
|
return true;
|
|
}
|
|
|
|
|
|
//=========================================================================================
|
|
void CComboBoxDesc::addObserver(ICDBNode::IPropertyObserver *obs)
|
|
{
|
|
// Add observers on dimensions
|
|
if (NumRow.getNodePtr())
|
|
{
|
|
ICDBNode::CTextId textId;
|
|
NumRow.getNodePtr()->addObserver(obs, textId);
|
|
}
|
|
if (NumCol.getNodePtr())
|
|
{
|
|
ICDBNode::CTextId textId;
|
|
NumCol.getNodePtr()->addObserver(obs, textId);
|
|
}
|
|
if (ItemWidth.getNodePtr())
|
|
{
|
|
ICDBNode::CTextId textId;
|
|
ItemWidth.getNodePtr()->addObserver(obs, textId);
|
|
}
|
|
if (ItemHeight.getNodePtr())
|
|
{
|
|
ICDBNode::CTextId textId;
|
|
ItemHeight.getNodePtr()->addObserver(obs, textId);
|
|
}
|
|
if (Unrolled.getNodePtr())
|
|
{
|
|
ICDBNode::CTextId textId;
|
|
Unrolled.getNodePtr()->addObserver(obs, textId);
|
|
}
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CComboBoxDesc::getGridSize(uint &numRow, uint &numCol) const
|
|
{
|
|
numRow = NumRow.getSInt32();
|
|
numCol = NumCol.getSInt32();
|
|
if (numRow == 0 || numCol == 0) return;
|
|
if (!Unrolled.getBool())
|
|
{
|
|
numRow = numCol = 1;
|
|
}
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CComboBoxDesc::getDimensions(uint &w, uint &h) const
|
|
{
|
|
uint numRow, numCol;
|
|
getGridSize(numRow, numCol);
|
|
w = numCol * (ItemWidth.getSInt32() + WGap.getSInt32());
|
|
h = numRow * (ItemHeight.getSInt32() + HGap.getSInt32());
|
|
//
|
|
if (numCol == 1) w -= WGap.getSInt32();
|
|
else w += WGapSelected.getSInt32() - WGap.getSInt32();
|
|
//
|
|
if (numRow == 1) h -= HGap.getSInt32();
|
|
else h += HGapSelected.getSInt32() - HGap.getSInt32();
|
|
}
|
|
|
|
//=======================================================================================
|
|
NLMISC_REGISTER_OBJECT(CViewBase, CViewBitmapCombo, std::string, "bitmap_combo");
|
|
|
|
CViewBitmapCombo::CViewBitmapCombo(const TCtorParam ¶m) : CViewBase(param)
|
|
{
|
|
}
|
|
|
|
|
|
//=======================================================================================
|
|
bool CViewBitmapCombo::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup)
|
|
{
|
|
if (! CViewBase::parse(cur, parentGroup) )
|
|
{
|
|
parseError(parentGroup);
|
|
return false;
|
|
}
|
|
|
|
CXMLAutoPtr prop;
|
|
|
|
std::string texs;
|
|
prop = xmlGetProp(cur, (xmlChar *)"tx_normal");
|
|
if (prop) texs = (const char*)prop;
|
|
std::string texsOver;
|
|
prop = xmlGetProp(cur, (xmlChar *)"tx_over");
|
|
if (prop) texsOver = (const char*)prop;
|
|
std::string texsPushed;
|
|
prop = xmlGetProp(cur, (xmlChar *)"tx_pushed");
|
|
if (prop) texsPushed = (const char*)prop;
|
|
//
|
|
// for colors, an empty strings means all colors are white
|
|
//
|
|
std::string col;
|
|
prop = xmlGetProp(cur, (xmlChar *)"col_normal");
|
|
if (prop) col = (const char*)prop;
|
|
std::string colOver;
|
|
prop = xmlGetProp(cur, (xmlChar *)"col_over");
|
|
if (prop) colOver = (const char*)prop;
|
|
std::string colPushed;
|
|
prop = xmlGetProp(cur, (xmlChar *)"col_pushed");
|
|
if (prop) colPushed = (const char*)prop;
|
|
|
|
/* if (texs.empty() || texsOver.empty() || texsPushed.empty())
|
|
{
|
|
parseError(parentGroup, "Cannot read tx_normal, tx_over, or tx_pushed");
|
|
return false;
|
|
}*/
|
|
|
|
parseTexList(texs, _Texs);
|
|
parseTexList(texsOver, _TexsOver);
|
|
parseTexList(texsPushed, _TexsPushed);
|
|
|
|
parseColList(col, _Col);
|
|
parseColList(colOver, _ColOver);
|
|
parseColList(colPushed, _ColPushed);
|
|
//
|
|
/* if (_Texs.size() != _TexsOver.size() || _TexsOver.size() != _TexsPushed.size())
|
|
{
|
|
parseError(parentGroup, "Texture names arrays do not have the same size");
|
|
return false;
|
|
}
|
|
//
|
|
uint numCols = NLMISC::maxof(_Col.size(), _ColOver.size(), _ColPushed.size());
|
|
if (!
|
|
(
|
|
(_Col.empty() || _Col.size() == numCols)
|
|
&& (_ColOver.empty() || _ColOver.size() == numCols)
|
|
&& (_ColPushed.empty() || _ColPushed.size() == numCols)
|
|
)
|
|
)
|
|
{
|
|
parseError(parentGroup, "Color names arrays do not have the same size (note an empty array is valid, means all color are 255 255 255");
|
|
return false;
|
|
}*/
|
|
//
|
|
if (!_CD.parse(cur, this))
|
|
{
|
|
return false;
|
|
}
|
|
//
|
|
setupSize();
|
|
//
|
|
_CD.addObserver(this);
|
|
|
|
return true;
|
|
}
|
|
|
|
//=======================================================================================
|
|
NLMISC::CRGBA CViewBitmapCombo::getCol(const CViewBitmapCombo::TColorArray &array,uint index)
|
|
{
|
|
if (array.empty()) return CRGBA::White;
|
|
return array[index % array.size()];
|
|
}
|
|
|
|
//=======================================================================================
|
|
const std::string *CViewBitmapCombo::getTex(const TStringArray &array,uint index)
|
|
{
|
|
if (array.empty()) return NULL;
|
|
return &array[index % array.size()];
|
|
}
|
|
|
|
//=======================================================================================
|
|
sint32 CViewBitmapCombo::getTexId(const TIdArray &array, uint index)
|
|
{
|
|
if (array.empty()) return -1;
|
|
return array[index % array.size()];
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::draw()
|
|
{
|
|
if (_Texs.empty()) return;
|
|
uint numRow, numCol;
|
|
_CD.getGridSize(numRow, numCol);
|
|
if (numRow == 0 || numCol == 0) return;
|
|
|
|
sint32 mx = 0, my = 0;
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
CViewRenderer &rVR = pIM->getViewRenderer();
|
|
const std::vector<CViewBase *> &rVB = pIM->getViewsUnderPointer();
|
|
if (!pIM->getPointer()) return;
|
|
pIM->getPointer()->getPointerDispPos(mx, my);
|
|
bool over = false;
|
|
uint32 i;
|
|
for (i = 0; i < rVB.size(); ++i)
|
|
{
|
|
if (rVB[i] == this)
|
|
{
|
|
over = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_TexsId.size() == 0)
|
|
{
|
|
for (i = 0; i < _Texs.size(); ++i)
|
|
_TexsId.push_back(rVR.getTextureIdFromName(_Texs[i]));
|
|
for (i = 0; i < _TexsOver.size(); ++i)
|
|
_TexsOverId.push_back(rVR.getTextureIdFromName(_TexsOver[i]));
|
|
for (i = 0; i < _TexsPushed.size(); ++i)
|
|
_TexsPushedId.push_back(rVR.getTextureIdFromName(_TexsPushed[i]));
|
|
}
|
|
|
|
sint32 textId;
|
|
CRGBA color;
|
|
uint selectedTexIndex = _CD.CurrSelected.getSInt32();
|
|
uint itemw = _CD.ItemWidth.getSInt32() + _CD.WGap.getSInt32();
|
|
uint itemh = _CD.ItemHeight.getSInt32() + _CD.HGap.getSInt32();
|
|
uint counter = 0;
|
|
|
|
bool overItem = false;
|
|
for(uint x = 0; x < numCol; ++x)
|
|
{
|
|
for(uint y = 0; y < numRow; ++y)
|
|
{
|
|
uint texIndex = counter;
|
|
if (counter != 0)
|
|
{
|
|
if (counter == selectedTexIndex)
|
|
{
|
|
texIndex = 0;
|
|
}
|
|
sint px;
|
|
sint py;
|
|
// get the right position depending on alignment
|
|
if (_CD.Align.getSInt32() & 1) // right align ?
|
|
{
|
|
px = _XReal + _WReal - (x + 1) * itemw;
|
|
}
|
|
else
|
|
{
|
|
px = _XReal + x * itemw;
|
|
}
|
|
// top align ?
|
|
if (_CD.Align.getSInt32() & 2)
|
|
{
|
|
py = _YReal + _HReal - (y + 1) * itemh;
|
|
}
|
|
else
|
|
{
|
|
py = _YReal + y * itemh;
|
|
}
|
|
|
|
if (x != 0)
|
|
{
|
|
if (_CD.Align.getSInt32() & 1)
|
|
px -= _CD.WGapSelected.getSInt32() - _CD.WGap.getSInt32();
|
|
else px += _CD.WGapSelected.getSInt32() - _CD.WGap.getSInt32();
|
|
}
|
|
if (y != 0)
|
|
{
|
|
if (_CD.Align.getSInt32() & 2)
|
|
py -= _CD.HGapSelected.getSInt32() - _CD.HGap.getSInt32();
|
|
else py += _CD.HGapSelected.getSInt32() - _CD.HGap.getSInt32();
|
|
}
|
|
// is the mouse on current item ?
|
|
if (over
|
|
&& mx >= px
|
|
&& my >= py
|
|
&& mx < px + (sint32) itemw
|
|
&& my < py + (sint32) itemh)
|
|
{
|
|
overItem = true;
|
|
if (pIM->getPointer()->getButtonState() & NLMISC::leftButton)
|
|
{
|
|
textId = getTexId(_TexsPushedId, texIndex);
|
|
color = getCol(_ColPushed, texIndex);
|
|
}
|
|
else
|
|
{
|
|
textId = getTexId(_TexsOverId, texIndex);
|
|
color = getCol(_ColOver, texIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
textId = getTexId(_TexsId, texIndex);
|
|
color = getCol(_Col, texIndex);
|
|
}
|
|
pIM->getViewRenderer().drawRotFlipBitmap (_RenderLayer, px, py, itemw, itemh, 0, false,
|
|
textId,
|
|
color);
|
|
}
|
|
++counter;
|
|
if ((sint32) counter == _CD.NumSel.getSInt32())
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((sint32) selectedTexIndex >= _CD.NumSel.getSInt32())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// draw current selection
|
|
sint32 px;
|
|
sint32 py;
|
|
//
|
|
if (_CD.Align.getSInt32() & 1)
|
|
{
|
|
px = _XReal + _WReal - itemw;
|
|
}
|
|
else
|
|
{
|
|
px = _XReal;
|
|
}
|
|
//
|
|
if (_CD.Align.getSInt32() & 2)
|
|
{
|
|
py = _YReal + _HReal - itemh;
|
|
}
|
|
else
|
|
{
|
|
py = _YReal;
|
|
}
|
|
//
|
|
if (_CD.Unrolled.getBool())
|
|
{
|
|
if (overItem && pIM->getPointer()->getButtonState() & NLMISC::leftButton)
|
|
{
|
|
textId = getTexId(_TexsId, selectedTexIndex);
|
|
color = getCol(_Col, selectedTexIndex);
|
|
}
|
|
else
|
|
{
|
|
textId = getTexId(_TexsPushedId, selectedTexIndex);
|
|
color = getCol(_ColPushed, selectedTexIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (over
|
|
&& mx >= px
|
|
&& my >= py
|
|
&& mx < px + (sint32) itemw
|
|
&& my < py + (sint32) itemh
|
|
)
|
|
{
|
|
if (pIM->getPointer()->getButtonState() & NLMISC::leftButton)
|
|
{
|
|
textId = getTexId(_TexsPushedId, selectedTexIndex);
|
|
color = getCol(_ColPushed, selectedTexIndex);
|
|
}
|
|
else
|
|
{
|
|
textId = getTexId(_TexsOverId, selectedTexIndex);
|
|
color = getCol(_ColOver, selectedTexIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
textId = getTexId(_TexsId, selectedTexIndex);
|
|
color = getCol(_Col, selectedTexIndex);
|
|
}
|
|
}
|
|
|
|
pIM->getViewRenderer().drawRotFlipBitmap (_RenderLayer, px, py, itemw, itemh, 0, false,
|
|
textId,
|
|
color);
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::parseTexList(const std::string &names, TStringArray &dest)
|
|
{
|
|
static const char sep[] = " ,\t";
|
|
std::string::size_type pos = 0, nextPos;
|
|
dest.clear();
|
|
do
|
|
{
|
|
nextPos = names.find_first_of(sep, pos);
|
|
if (pos != nextPos)
|
|
{
|
|
dest.push_back(names.substr(pos, nextPos - pos));
|
|
}
|
|
pos = names.find_first_not_of(sep, nextPos);
|
|
}
|
|
while (pos != std::string::npos);
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::parseColList(const std::string &names,TColorArray &dest)
|
|
{
|
|
static const char sep[] = ",\t";
|
|
std::string::size_type pos = 0, nextPos;
|
|
dest.clear();
|
|
std::string col;
|
|
do
|
|
{
|
|
nextPos = names.find_first_of(sep, pos);
|
|
if (pos != nextPos)
|
|
{
|
|
col = names.substr(pos, nextPos - pos);
|
|
int r = 0, g = 0, b = 0, a = 255;
|
|
sscanf (col.c_str(), "%d %d %d %d", &r, &g, &b, &a);
|
|
NLMISC::clamp (r, 0, 255);
|
|
NLMISC::clamp (g, 0, 255);
|
|
NLMISC::clamp (b, 0, 255);
|
|
NLMISC::clamp (a, 0, 255);
|
|
dest.push_back(NLMISC::CRGBA((uint8) r, (uint8) g, (uint8) b, (uint8) a));
|
|
}
|
|
pos = names.find_first_not_of(sep, nextPos);
|
|
}
|
|
while (pos != std::string::npos);
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::setupSize()
|
|
{
|
|
uint w, h;
|
|
_CD.getDimensions(w, h);
|
|
setW(w);
|
|
setH(h);
|
|
invalidateCoords();
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::update(ICDBNode * /* leaf */)
|
|
{
|
|
setupSize();
|
|
}
|
|
|
|
|
|
//=======================================================================================
|
|
/** copy an array of char * into an array of strings
|
|
*/
|
|
static void copyStrArrayFromChar(CViewBitmapCombo::TStringArray &dest, const char * const src[], uint numColor)
|
|
{
|
|
dest.resize(numColor);
|
|
for(uint k = 0; k < numColor; ++k)
|
|
{
|
|
dest[k] = src[k];
|
|
}
|
|
}
|
|
|
|
|
|
static void copyRGBAVectorFromRGBAArray(CViewBitmapCombo::TColorArray &dest, const NLMISC::CRGBA src[], uint numColor)
|
|
{
|
|
dest.resize(numColor);
|
|
std::copy(src, src + numColor, dest.begin());
|
|
}
|
|
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::setTexs(const char * const tex[], uint numTex)
|
|
{
|
|
copyStrArrayFromChar(_Texs, tex, numTex);
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::setTexsOver(const char * const tex[], uint numTex)
|
|
{
|
|
copyStrArrayFromChar(_TexsOver, tex, numTex);
|
|
}
|
|
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::setTexsPushed(const char * const tex[], uint numTex)
|
|
{
|
|
copyStrArrayFromChar(_TexsPushed, tex, numTex);
|
|
}
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::setColors(const NLMISC::CRGBA colors[], uint numColors)
|
|
{
|
|
copyRGBAVectorFromRGBAArray(_Col, colors, numColors);
|
|
}
|
|
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::setColorsOver(const NLMISC::CRGBA colors[], uint numColors)
|
|
{
|
|
copyRGBAVectorFromRGBAArray(_ColOver, colors, numColors);
|
|
}
|
|
|
|
|
|
//=======================================================================================
|
|
void CViewBitmapCombo::setColorsPushed(const NLMISC::CRGBA colors[], uint numColors)
|
|
{
|
|
copyRGBAVectorFromRGBAArray(_ColPushed, colors, numColors);
|
|
}
|