aboutsummaryrefslogtreecommitdiff
path: root/src/gui/guiBox.cpp
blob: 443f1064f4942d1affcb43218481f8b6f7331a98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "guiBox.h"

GUIBox::GUIBox(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id,
	const core::rect<s32> &rectangle,
	const std::array<video::SColor, 4> &colors,
	const std::array<video::SColor, 4> &bordercolors,
	const std::array<s32, 4> &borderwidths) :
	gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle),
	m_colors(colors),
	m_bordercolors(bordercolors),
	m_borderwidths(borderwidths)
{
}

void GUIBox::draw()
{
	if (!IsVisible)
		return;

	std::array<s32, 4> negative_borders = {0, 0, 0, 0};
	std::array<s32, 4> positive_borders = {0, 0, 0, 0};

	for (size_t i = 0; i <= 3; i++) {
		if (m_borderwidths[i] > 0)
			positive_borders[i] = m_borderwidths[i];
		else
			negative_borders[i] = m_borderwidths[i];
	}

	v2s32 upperleft = AbsoluteRect.UpperLeftCorner;
	v2s32 lowerright = AbsoluteRect.LowerRightCorner;

	v2s32 topleft_border = {
		upperleft.X - positive_borders[3],
		upperleft.Y - positive_borders[0]
	};
	v2s32 topleft_rect = {
		upperleft.X - negative_borders[3],
		upperleft.Y - negative_borders[0]
	};

	v2s32 lowerright_border = {
		lowerright.X + positive_borders[1],
		lowerright.Y + positive_borders[2]
	};
	v2s32 lowerright_rect = {
		lowerright.X + negative_borders[1],
		lowerright.Y + negative_borders[2]
	};

	core::rect<s32> main_rect(
		topleft_rect.X,
		topleft_rect.Y,
		lowerright_rect.X,
		lowerright_rect.Y
	);

	std::array<core::rect<s32>, 4> border_rects;

	border_rects[0] = core::rect<s32>(
		topleft_border.X,
		topleft_border.Y,
		lowerright_border.X,
		topleft_rect.Y
	);

	border_rects[1] = core::rect<s32>(
		lowerright_rect.X,
		topleft_rect.Y,
		lowerright_border.X,
		lowerright_rect.Y
	);

	border_rects[2] = core::rect<s32>(
		topleft_border.X,
		lowerright_rect.Y,
		lowerright_border.X,
		lowerright_border.Y
	);

	border_rects[3] = core::rect<s32>(
		topleft_border.X,
		topleft_rect.Y,
		topleft_rect.X,
		lowerright_rect.Y
	);

	video::IVideoDriver *driver = Environment->getVideoDriver();

	driver->draw2DRectangle(main_rect, m_colors[0], m_colors[1], m_colors[3],
		m_colors[2], &AbsoluteClippingRect);

	for (size_t i = 0; i <= 3; i++)
		driver->draw2DRectangle(m_bordercolors[i], border_rects[i],
				&AbsoluteClippingRect);

	IGUIElement::draw();
}
GUI_ID_CB_AUX1_DESCENDS, GUI_ID_CB_DOUBLETAP_JUMP, }; GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) : GUIModalMenu(env, parent, id, menumgr) { shift_down = false; activeKey = -1; this->key_used_text = NULL; init_keys(); for(size_t i=0; i<key_settings.size(); i++) this->key_used.push_back(key_settings.at(i)->key); } GUIKeyChangeMenu::~GUIKeyChangeMenu() { removeChildren(); } void GUIKeyChangeMenu::removeChildren() { const core::list<gui::IGUIElement*> &children = getChildren(); core::list<gui::IGUIElement*> children_copy; for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i != children.end(); i++) { children_copy.push_back(*i); } for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i != children_copy.end(); i++) { (*i)->remove(); } } void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { removeChildren(); v2s32 size(620, 430); core::rect < s32 > rect(screensize.X / 2 - size.X / 2, screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2, screensize.Y / 2 + size.Y / 2); DesiredRect = rect; recalculateAbsolutePosition(false); v2s32 topleft(0, 0); changeCtype(""); { core::rect < s32 > rect(0, 0, 600, 40); rect += topleft + v2s32(25, 3); //gui::IGUIStaticText *t = Environment->addStaticText(wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)"), rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } // Build buttons v2s32 offset(25, 60); for(size_t i = 0; i < key_settings.size(); i++) { key_setting *k = key_settings.at(i); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); Environment->addStaticText(k->button_name, rect, false, true, this, -1); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); k->button = Environment->addButton(rect, this, k->id, wgettext(k->key.name())); } if(i + 1 == KMaxButtonPerColumns) offset = v2s32(250, 60); else offset += v2s32(0, 25); } { s32 option_x = offset.X + 10; s32 option_y = offset.Y; u32 option_w = 180; { core::rect<s32> rect(0, 0, option_w, 30); rect += topleft + v2s32(option_x, option_y); Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this, GUI_ID_CB_AUX1_DESCENDS, wgettext("\"Use\" = climb down")); } offset += v2s32(0, 25); } { s32 option_x = offset.X + 10; s32 option_y = offset.Y; u32 option_w = 220; { core::rect<s32> rect(0, 0, option_w, 30); rect += topleft + v2s32(option_x, option_y); Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this, GUI_ID_CB_DOUBLETAP_JUMP, wgettext("Double tap \"jump\" to toggle fly")); } offset += v2s32(0, 25); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(size.X - 100 - 20, size.Y - 40); Environment->addButton(rect, this, GUI_ID_BACK_BUTTON, wgettext("Save")); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(size.X - 100 - 20 - 100 - 20, size.Y - 40); Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON, wgettext("Cancel")); } changeCtype("C"); } void GUIKeyChangeMenu::drawMenu() { gui::IGUISkin* skin = Environment->getSkin(); if (!skin) return; video::IVideoDriver* driver = Environment->getVideoDriver(); video::SColor bgcolor(140, 0, 0, 0); { core::rect < s32 > rect(0, 0, 620, 620); rect += AbsoluteRect.UpperLeftCorner; driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect); } gui::IGUIElement::draw(); } bool GUIKeyChangeMenu::acceptInput() { for(size_t i = 0; i < key_settings.size(); i++) { key_setting *k = key_settings.at(i); g_settings->set(k->setting_name, k->key.sym()); } { gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked()); } { gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP); if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked()); } clearKeyCache(); return true; } bool GUIKeyChangeMenu::resetMenu() { if (activeKey >= 0) { for(size_t i = 0; i < key_settings.size(); i++) { key_setting *k = key_settings.at(i); if(k->id == activeKey) { k->button->setText(wgettext(k->key.name())); break; } } activeKey = -1; return false; } return true; } bool GUIKeyChangeMenu::OnEvent(const SEvent& event) { if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0 && event.KeyInput.PressedDown) { changeCtype(""); bool prefer_character = shift_down; KeyPress kp(event.KeyInput, prefer_character); bool shift_went_down = false; if(!shift_down && (event.KeyInput.Key == irr::KEY_SHIFT || event.KeyInput.Key == irr::KEY_LSHIFT || event.KeyInput.Key == irr::KEY_RSHIFT)) shift_went_down = true; // Remove Key already in use message if(this->key_used_text) { this->key_used_text->remove(); this->key_used_text = NULL; } // Display Key already in use message if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end()) { core::rect < s32 > rect(0, 0, 600, 40); rect += v2s32(0, 0) + v2s32(25, 30); this->key_used_text = Environment->addStaticText(wgettext("Key already in use"), rect, false, true, this, -1); //infostream << "Key already in use" << std::endl; } // But go on { key_setting *k=NULL; for(size_t i = 0; i < key_settings.size(); i++) { if(key_settings.at(i)->id == activeKey) { k = key_settings.at(i); break; } } assert(k); k->key = kp; k->button->setText(wgettext(k->key.name())); this->key_used.push_back(kp); changeCtype("C"); // Allow characters made with shift if(shift_went_down){ shift_down = true; return false; }else{ activeKey = -1; return true; } } } if (event.EventType == EET_GUI_EVENT) { if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST && isVisible()) { if (!canTakeFocus(event.GUIEvent.Element)) { dstream << "GUIMainMenu: Not allowing focus change." << std::endl; // Returning true disables focus change return true; } } if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) { if(event.GUIEvent.Caller->getID() != GUI_ID_BACK_BUTTON && event.GUIEvent.Caller->getID() != GUI_ID_ABORT_BUTTON) { changeCtype(""); } switch (event.GUIEvent.Caller->getID()) { case GUI_ID_BACK_BUTTON: //back acceptInput(); quitMenu(); return true; case GUI_ID_ABORT_BUTTON: //abort quitMenu(); return true; default: key_setting *k = NULL; for(size_t i = 0; i < key_settings.size(); i++) { if(key_settings.at(i)->id == event.GUIEvent.Caller->getID()) { k = key_settings.at(i); break; } } assert(k); resetMenu(); shift_down = false; activeKey = event.GUIEvent.Caller->getID(); k->button->setText(wgettext("press key")); this->key_used.erase(std::remove(this->key_used.begin(), this->key_used.end(), k->key), this->key_used.end()); break; } Environment->setFocus(this); //Buttons changeCtype("C"); } } return Parent ? Parent->OnEvent(event) : false; } void GUIKeyChangeMenu::add_key(int id, std::string button_name, std::string setting_name) { key_setting *k = new key_setting; k->id = id; k->button_name = wgettext(button_name.c_str()); k->setting_name = setting_name; k->key = getKeySetting(k->setting_name.c_str()); key_settings.push_back(k); } void GUIKeyChangeMenu::init_keys() { this->add_key(GUI_ID_KEY_FORWARD_BUTTON, gettext("Forward"), "keymap_forward"); this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, gettext("Backward"), "keymap_backward"); this->add_key(GUI_ID_KEY_LEFT_BUTTON, gettext("Left"), "keymap_left"); this->add_key(GUI_ID_KEY_RIGHT_BUTTON, gettext("Right"), "keymap_right"); this->add_key(GUI_ID_KEY_USE_BUTTON, gettext("Use"), "keymap_special1"); this->add_key(GUI_ID_KEY_JUMP_BUTTON, gettext("Jump"), "keymap_jump"); this->add_key(GUI_ID_KEY_SNEAK_BUTTON, gettext("Sneak"), "keymap_sneak"); this->add_key(GUI_ID_KEY_DROP_BUTTON, gettext("Drop"), "keymap_drop"); this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, gettext("Inventory"), "keymap_inventory"); this->add_key(GUI_ID_KEY_CHAT_BUTTON, gettext("Chat"), "keymap_chat"); this->add_key(GUI_ID_KEY_CMD_BUTTON, gettext("Command"), "keymap_cmd"); this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, gettext("Console"), "keymap_console"); this->add_key(GUI_ID_KEY_FLY_BUTTON, gettext("Toggle fly"), "keymap_freemove"); this->add_key(GUI_ID_KEY_FAST_BUTTON, gettext("Toggle fast"), "keymap_fastmove"); this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, gettext("Toggle noclip"), "keymap_noclip"); this->add_key(GUI_ID_KEY_RANGE_BUTTON, gettext("Range select"), "keymap_rangeselect"); this->add_key(GUI_ID_KEY_DUMP_BUTTON, gettext("Print stacks"), "keymap_print_debug_stacks"); }