Expand Up
@@ -604,7 +604,7 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element,std::stri
void GUIFormSpecMenu::parseBackground (parserData* data,std::string element) {
std::vector<std::string> parts = split (element,' ;' );
if (parts.size () == 3 ) {
if (( parts.size () == 3 ) || (parts. size () == 4 ) ) {
std::vector<std::string> v_pos = split (parts[0 ],' ,' );
std::vector<std::string> v_geom = split (parts[1 ],' ,' );
std::string name = unescape_string (parts[2 ]);
Expand All
@@ -620,6 +620,14 @@ void GUIFormSpecMenu::parseBackground(parserData* data,std::string element) {
geom.X = stof (v_geom[0 ]) * (float )spacing.X ;
geom.Y = stof (v_geom[1 ]) * (float )spacing.Y ;
if (parts.size () == 4 ) {
m_clipbackground = is_yes (parts[3 ]);
if (m_clipbackground) {
pos.X = stoi (v_pos[0 ]); // acts as offset
pos.Y = stoi (v_pos[1 ]); // acts as offset
}
}
if (data->bp_set != 2 )
errorstream<<" WARNING: invalid use of background without a size[] element" <<std::endl;
m_backgrounds.push_back (ImageDrawSpec (name, pos, geom));
Expand Down
Expand Up
@@ -686,16 +694,16 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) {
e->addItem (narrow_to_wide (unescape_string (items[i])).c_str () +1 );
}
else {
std::string color = items[i].substr (1 , 6 );
std::string color = items[i].substr (0 , 7 );
std::wstring toadd =
narrow_to_wide (unescape_string (items[i]).c_str () + 7 );
e->addItem (toadd.c_str ());
irr:: video::SColor toset ;
video::SColor tmp_color ;
if (parseColor (color, toset ))
e->setItemOverrideColor (i,toset );
if (parseColor (color, tmp_color, false ))
e->setItemOverrideColor (i,tmp_color );
}
}
else {
Expand Down
Expand Up
@@ -1329,7 +1337,6 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element) {
if (parts.size () == 3 ) {
std::vector<std::string> v_pos = split (parts[0 ],' ,' );
std::vector<std::string> v_geom = split (parts[1 ],' ,' );
std::string color_str = parts[2 ];
MY_CHECKPOS (" box" ,0 );
MY_CHECKGEOM (" box" ,1 );
Expand All
@@ -1342,10 +1349,10 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element) {
geom.X = stof (v_geom[0 ]) * (float )spacing.X ;
geom.Y = stof (v_geom[1 ]) * (float )spacing.Y ;
irr:: video::SColor color ;
video::SColor tmp_color ;
if (parseColor (color_str, color )) {
BoxDrawSpec spec (pos,geom,color );
if (parseColor (parts[ 2 ], tmp_color, false )) {
BoxDrawSpec spec (pos, geom, tmp_color );
m_boxes.push_back (spec);
}
Expand All
@@ -1357,6 +1364,46 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element) {
errorstream<< " Invalid Box element(" << parts.size () << " ): '" << element << " '" << std::endl;
}
void GUIFormSpecMenu::parseBackgroundColor (parserData* data,std::string element) {
std::vector<std::string> parts = split (element,' ;' );
if ((parts.size () == 1 ) || (parts.size () == 2 )) {
parseColor (parts[0 ],m_bgcolor,false );
if (parts.size () == 2 ) {
std::string fullscreen = parts[1 ];
m_bgfullscreen = is_yes (fullscreen);
}
return ;
}
errorstream<< " Invalid bgcolor element(" << parts.size () << " ): '" << element << " '" << std::endl;
}
void GUIFormSpecMenu::parseListColors (parserData* data,std::string element) {
std::vector<std::string> parts = split (element,' ;' );
if (parts.size () == 2 ) || (parts.size () == 3 ) || (parts.size () == 5 )) {
parseColor (parts[0 ], m_slotbg_n, false );
parseColor (parts[1 ], m_slotbg_h, false );
if (parts.size () >= 3 ) {
if (parseColor (parts[2 ], m_slotbordercolor, false )) {
m_slotborder = true ;
}
}
if (parts.size () == 5 ) {
video::SColor tmp_color;
if (parseColor (parts[3 ], tmp_color, false ))
m_tooltip_element->setBackgroundColor (tmp_color);
if (parseColor (parts[4 ], tmp_color, false ))
m_tooltip_element->setOverrideColor (tmp_color);
}
return ;
}
errorstream<< " Invalid listcolors element(" << parts.size () << " ): '" << element << " '" << std::endl;
}
void GUIFormSpecMenu::parseElement (parserData* data,std::string element) {
// some prechecks
Expand Down
Expand Up
@@ -1467,6 +1514,16 @@ void GUIFormSpecMenu::parseElement(parserData* data,std::string element) {
return ;
}
if (type == " bgcolor" ) {
parseBackgroundColor (data,description);
return ;
}
if (type == " listcolors" ) {
parseListColors (data,description);
return ;
}
// Ignore others
infostream
<< " Unknown DrawSpec: type=" <<type<<" , data=\" " <<description<<" \" "
Expand Down
Expand Up
@@ -1537,25 +1594,39 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
m_fields.clear ();
m_boxes.clear ();
// Set default values (fits old formspec values)
m_bgcolor = video::SColor (140 ,0 ,0 ,0 );
m_bgfullscreen = false ;
m_slotbg_n = video::SColor (255 ,128 ,128 ,128 );
m_slotbg_h = video::SColor (255 ,192 ,192 ,192 );
m_slotbordercolor = video::SColor (200 ,0 ,0 ,0 );
m_slotborder = false ;
m_clipbackground = false ;
// Add tooltip
{
// Note: parent != this so that the tooltip isn't clipped by the menu rectangle
m_tooltip_element = Environment->addStaticText (L" " ,core::rect<s32>(0 ,0 ,110 ,18 ));
m_tooltip_element->enableOverrideColor (true );
m_tooltip_element->setBackgroundColor (video::SColor (255 ,110 ,130 ,60 ));
m_tooltip_element->setDrawBackground (true );
m_tooltip_element->setDrawBorder (true );
m_tooltip_element->setOverrideColor (video::SColor (255 ,255 ,255 ,255 ));
m_tooltip_element->setTextAlignment (gui::EGUIA_CENTER, gui::EGUIA_CENTER);
m_tooltip_element->setWordWrap (false );
// we're not parent so no autograb for this one!
m_tooltip_element->grab ();
}
std::vector<std::string> elements = split (m_formspec_string,' ]' );
for (unsigned int i=0 ;i< elements.size ();i++) {
parseElement (&mydata,elements[i]);
}
// If there's inventory, put the usage string at the bottom
if (m_inventorylists.size ())
{
changeCtype (" " );
core::rect<s32> rect (0 , 0 , mydata.size .X -padding.X *2 , mydata.helptext_h );
rect = rect + v2s32 ((mydata.size .X /2 - mydata.rect .getWidth ()/2 ) +5 ,
mydata.size .Y -5 -mydata.helptext_h );
const wchar_t *text = wgettext (" Left click: Move all items, Right click: Move single item" );
Environment->addStaticText (text, rect, false , true , this , 256 );
delete[] text;
changeCtype (" C" );
}
// If there's fields, add a Proceed button
if (m_fields.size () && mydata.bp_set != 2 )
{
Expand Down
Expand Up
@@ -1583,20 +1654,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
}
changeCtype (" C" );
}
// Add tooltip
{
// Note: parent != this so that the tooltip isn't clipped by the menu rectangle
m_tooltip_element = Environment->addStaticText (L" " ,core::rect<s32>(0 ,0 ,110 ,18 ));
m_tooltip_element->enableOverrideColor (true );
m_tooltip_element->setBackgroundColor (video::SColor (255 ,110 ,130 ,60 ));
m_tooltip_element->setDrawBackground (true );
m_tooltip_element->setDrawBorder (true );
m_tooltip_element->setOverrideColor (video::SColor (255 ,255 ,255 ,255 ));
m_tooltip_element->setTextAlignment (gui::EGUIA_CENTER, gui::EGUIA_CENTER);
m_tooltip_element->setWordWrap (false );
// we're not parent so no autograb for this one!
m_tooltip_element->grab ();
}
// set initial focus if parser didn't set it
focused_element = Environment->getFocus ();
Expand Down
Expand Up
@@ -1681,16 +1738,31 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase)
if (phase == 0 )
{
if (hovering && m_selected_item)
{
video::SColor bgcolor (255 ,192 ,192 ,192 );
driver->draw2DRectangle (bgcolor, rect, &AbsoluteClippingRect);
}
if (hovering)
driver->draw2DRectangle (m_slotbg_h, rect, &AbsoluteClippingRect);
else
{
video::SColor bgcolor (255 ,128 ,128 ,128 );
driver->draw2DRectangle (bgcolor, rect, &AbsoluteClippingRect);
}
driver->draw2DRectangle (m_slotbg_n, rect, &AbsoluteClippingRect);
}
// Draw inv slot borders
if (m_slotborder) {
s32 x1 = rect.UpperLeftCorner .X ;
s32 y1 = rect.UpperLeftCorner .Y ;
s32 x2 = rect.LowerRightCorner .X ;
s32 y2 = rect.LowerRightCorner .Y ;
s32 border = 1 ;
driver->draw2DRectangle (m_slotbordercolor,
core::rect<s32>(v2s32 (x1 - border, y1 - border),
v2s32 (x2 + border, y1 )), NULL );
driver->draw2DRectangle (m_slotbordercolor,
core::rect<s32>(v2s32 (x1 - border, y2),
v2s32 (x2 + border, y2 + border)), NULL );
driver->draw2DRectangle (m_slotbordercolor,
core::rect<s32>(v2s32 (x1 - border, y1 ),
v2s32 (x1, y2)), NULL );
driver->draw2DRectangle (m_slotbordercolor,
core::rect<s32>(v2s32 (x2, y1 ),
v2s32 (x2 + border, y2)), NULL );
}
if (phase == 1 )
Expand Down
Expand Up
@@ -1771,8 +1843,12 @@ void GUIFormSpecMenu::drawMenu()
return ;
video::IVideoDriver* driver = Environment->getVideoDriver ();
video::SColor bgcolor (140 ,0 ,0 ,0 );
driver->draw2DRectangle (bgcolor, AbsoluteRect, &AbsoluteClippingRect);
v2u32 screenSize = driver->getScreenSize ();
core::rect<s32> allbg (0 , 0 , screenSize.X , screenSize.Y );
if (m_bgfullscreen)
driver->draw2DRectangle (m_bgcolor, allbg, &allbg);
else
driver->draw2DRectangle (m_bgcolor, AbsoluteRect, &AbsoluteClippingRect);
m_tooltip_element->setVisible (false );
Expand All
@@ -1789,6 +1865,15 @@ void GUIFormSpecMenu::drawMenu()
core::rect<s32> imgrect (0 , 0 , spec.geom .X , spec.geom .Y );
// Image rectangle on screen
core::rect<s32> rect = imgrect + spec.pos ;
if (m_clipbackground) {
core::dimension2d<s32> absrec_size = AbsoluteRect.getSize ();
rect = core::rect<s32>(AbsoluteRect.UpperLeftCorner .X - spec.pos .X ,
AbsoluteRect.UpperLeftCorner .Y - spec.pos .Y ,
AbsoluteRect.UpperLeftCorner .X + absrec_size.Width + spec.pos .X *2 ,
AbsoluteRect.UpperLeftCorner .Y + absrec_size.Height + spec.pos .Y *2 );
}
const video::SColor color (255 ,255 ,255 ,255 );
const video::SColor colors[] = {color,color,color,color};
driver->draw2DImage (texture, rect,
Expand Down
Expand Up
@@ -1880,10 +1965,8 @@ void GUIFormSpecMenu::drawMenu()
Draw items
Phase 0: Item slot rectangles
Phase 1: Item images; prepare tooltip
If backgrounds used, do not draw Item slot rectangles
*/
int start_phase=0 ;
if (m_backgrounds.size () > 0 ) start_phase=1 ;
for (int phase=start_phase; phase<=1 ; phase++)
for (u32 i=0 ; i<m_inventorylists.size (); i++)
{
Expand Down
Expand Up
@@ -2633,18 +2716,78 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
return Parent ? Parent->OnEvent (event) : false ;
}
bool GUIFormSpecMenu::parseColor (std::string color, irr::video::SColor& outcolor) {
outcolor = irr::video::SColor (0 ,0 ,0 ,0 );
if (!string_allowed (color, " 0123456789abcdefABCDEF" ))
static inline bool hex_digit_decode (char hexdigit, unsigned char &value)
{
if (hexdigit >= ' 0' && hexdigit <= ' 9' )
value = hexdigit - ' 0' ;
else if (hexdigit >= ' A' && hexdigit <= ' F' )
value = hexdigit - ' A' + 10 ;
else if (hexdigit >= ' a' && hexdigit <= ' f' )
value = hexdigit - ' a' + 10 ;
else
return false ;
return true ;
}
u32 color_value;
std::istringstream iss (color);
iss >> std::hex >> color_value;
outcolor = irr::video::SColor (color_value);
bool GUIFormSpecMenu::parseColor (std::string &value, video::SColor &color, bool quiet)
{
const char *hexpattern = NULL ;
if (value[0 ] == ' #' ) {
if (value.size () == 9 )
hexpattern = " #RRGGBBAA" ;
else if (value.size () == 7 )
hexpattern = " #RRGGBB" ;
else if (value.size () == 5 )
hexpattern = " #RGBA" ;
else if (value.size () == 4 )
hexpattern = " #RGB" ;
}
if (hexpattern) {
assert (strlen (hexpattern) == value.size ());
video::SColor outcolor (255 , 255 , 255 , 255 );
for (size_t pos = 0 ; pos < value.size (); ++pos) {
// '#' in the pattern means skip that character
if (hexpattern[pos] == ' #' )
continue ;
outcolor.setAlpha (255 );
return true ;
// Else assume hexpattern[pos] is one of 'R' 'G' 'B' 'A'
// Read one or two digits, depending on hexpattern
unsigned char c1, c2;
if (hexpattern[pos+1 ] == hexpattern[pos]) {
// Two digits, e.g. hexpattern == "#RRGGBB"
if (!hex_digit_decode (value[pos], c1) ||
!hex_digit_decode (value[pos+1 ], c2))
goto fail;
++pos;
}
else {
// One digit, e.g. hexpattern == "#RGB"
if (!hex_digit_decode (value[pos], c1))
goto fail;
c2 = c1;
}
u32 colorpart = ((c1 & 0x0f ) << 4 ) | (c2 & 0x0f );
// Update outcolor with newly read color part
if (hexpattern[pos] == ' R' )
outcolor.setRed (colorpart);
else if (hexpattern[pos] == ' G' )
outcolor.setGreen (colorpart);
else if (hexpattern[pos] == ' B' )
outcolor.setBlue (colorpart);
else if (hexpattern[pos] == ' A' )
outcolor.setAlpha (colorpart);
}
color = outcolor;
return true ;
}
// Optionally, named colors could be implemented here
fail:
if (!quiet)
errorstream<<" Invalid color: \" " <<value<<" \" " <<std::endl;
return false ;
}