mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
parent
fc9747eb4b
commit
20a85d76d9
118 changed files with 236 additions and 221 deletions
13
src/gui/CMakeLists.txt
Normal file
13
src/gui/CMakeLists.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
set(gui_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBoxWithScrollbar.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiEngine.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiFormSpecMenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiKeyChangeMenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiPasswordChange.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiPathSelectMenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiTable.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/guiVolumeChange.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/intlGUIEditBox.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
642
src/gui/guiChatConsole.cpp
Normal file
642
src/gui/guiChatConsole.cpp
Normal file
|
@ -0,0 +1,642 @@
|
|||
/*
|
||||
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 "guiChatConsole.h"
|
||||
#include "chat.h"
|
||||
#include "client.h"
|
||||
#include "debug.h"
|
||||
#include "gettime.h"
|
||||
#include "keycode.h"
|
||||
#include "settings.h"
|
||||
#include "porting.h"
|
||||
#include "client/tile.h"
|
||||
#include "fontengine.h"
|
||||
#include "log.h"
|
||||
#include "gettext.h"
|
||||
#include <string>
|
||||
|
||||
#if USE_FREETYPE
|
||||
#include "irrlicht_changes/CGUITTFont.h"
|
||||
#endif
|
||||
|
||||
inline u32 clamp_u8(s32 value)
|
||||
{
|
||||
return (u32) MYMIN(MYMAX(value, 0), 255);
|
||||
}
|
||||
|
||||
|
||||
GUIChatConsole::GUIChatConsole(
|
||||
gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent,
|
||||
s32 id,
|
||||
ChatBackend* backend,
|
||||
Client* client,
|
||||
IMenuManager* menumgr
|
||||
):
|
||||
IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
|
||||
core::rect<s32>(0,0,100,100)),
|
||||
m_chat_backend(backend),
|
||||
m_client(client),
|
||||
m_menumgr(menumgr),
|
||||
m_animate_time_old(porting::getTimeMs())
|
||||
{
|
||||
// load background settings
|
||||
s32 console_alpha = g_settings->getS32("console_alpha");
|
||||
m_background_color.setAlpha(clamp_u8(console_alpha));
|
||||
|
||||
// load the background texture depending on settings
|
||||
ITextureSource *tsrc = client->getTextureSource();
|
||||
if (tsrc->isKnownSourceImage("background_chat.jpg")) {
|
||||
m_background = tsrc->getTexture("background_chat.jpg");
|
||||
m_background_color.setRed(255);
|
||||
m_background_color.setGreen(255);
|
||||
m_background_color.setBlue(255);
|
||||
} else {
|
||||
v3f console_color = g_settings->getV3F("console_color");
|
||||
m_background_color.setRed(clamp_u8(myround(console_color.X)));
|
||||
m_background_color.setGreen(clamp_u8(myround(console_color.Y)));
|
||||
m_background_color.setBlue(clamp_u8(myround(console_color.Z)));
|
||||
}
|
||||
|
||||
m_font = g_fontengine->getFont(FONT_SIZE_UNSPECIFIED, FM_Mono);
|
||||
|
||||
if (!m_font) {
|
||||
errorstream << "GUIChatConsole: Unable to load mono font ";
|
||||
} else {
|
||||
core::dimension2d<u32> dim = m_font->getDimension(L"M");
|
||||
m_fontsize = v2u32(dim.Width, dim.Height);
|
||||
m_font->grab();
|
||||
}
|
||||
m_fontsize.X = MYMAX(m_fontsize.X, 1);
|
||||
m_fontsize.Y = MYMAX(m_fontsize.Y, 1);
|
||||
|
||||
// set default cursor options
|
||||
setCursor(true, true, 2.0, 0.1);
|
||||
}
|
||||
|
||||
GUIChatConsole::~GUIChatConsole()
|
||||
{
|
||||
if (m_font)
|
||||
m_font->drop();
|
||||
}
|
||||
|
||||
void GUIChatConsole::openConsole(f32 scale)
|
||||
{
|
||||
assert(scale > 0.0f && scale <= 1.0f);
|
||||
|
||||
m_open = true;
|
||||
m_desired_height_fraction = scale;
|
||||
m_desired_height = scale * m_screensize.Y;
|
||||
reformatConsole();
|
||||
m_animate_time_old = porting::getTimeMs();
|
||||
IGUIElement::setVisible(true);
|
||||
Environment->setFocus(this);
|
||||
m_menumgr->createdMenu(this);
|
||||
}
|
||||
|
||||
bool GUIChatConsole::isOpen() const
|
||||
{
|
||||
return m_open;
|
||||
}
|
||||
|
||||
bool GUIChatConsole::isOpenInhibited() const
|
||||
{
|
||||
return m_open_inhibited > 0;
|
||||
}
|
||||
|
||||
void GUIChatConsole::closeConsole()
|
||||
{
|
||||
m_open = false;
|
||||
Environment->removeFocus(this);
|
||||
m_menumgr->deletingMenu(this);
|
||||
}
|
||||
|
||||
void GUIChatConsole::closeConsoleAtOnce()
|
||||
{
|
||||
closeConsole();
|
||||
m_height = 0;
|
||||
recalculateConsolePosition();
|
||||
}
|
||||
|
||||
f32 GUIChatConsole::getDesiredHeight() const
|
||||
{
|
||||
return m_desired_height_fraction;
|
||||
}
|
||||
|
||||
void GUIChatConsole::replaceAndAddToHistory(std::wstring line)
|
||||
{
|
||||
ChatPrompt& prompt = m_chat_backend->getPrompt();
|
||||
prompt.addToHistory(prompt.getLine());
|
||||
prompt.replace(line);
|
||||
}
|
||||
|
||||
|
||||
void GUIChatConsole::setCursor(
|
||||
bool visible, bool blinking, f32 blink_speed, f32 relative_height)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
if (blinking)
|
||||
{
|
||||
// leave m_cursor_blink unchanged
|
||||
m_cursor_blink_speed = blink_speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cursor_blink = 0x8000; // on
|
||||
m_cursor_blink_speed = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cursor_blink = 0; // off
|
||||
m_cursor_blink_speed = 0.0;
|
||||
}
|
||||
m_cursor_height = relative_height;
|
||||
}
|
||||
|
||||
void GUIChatConsole::draw()
|
||||
{
|
||||
if(!IsVisible)
|
||||
return;
|
||||
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
// Check screen size
|
||||
v2u32 screensize = driver->getScreenSize();
|
||||
if (screensize != m_screensize)
|
||||
{
|
||||
// screen size has changed
|
||||
// scale current console height to new window size
|
||||
if (m_screensize.Y != 0)
|
||||
m_height = m_height * screensize.Y / m_screensize.Y;
|
||||
m_screensize = screensize;
|
||||
m_desired_height = m_desired_height_fraction * m_screensize.Y;
|
||||
reformatConsole();
|
||||
}
|
||||
|
||||
// Animation
|
||||
u64 now = porting::getTimeMs();
|
||||
animate(now - m_animate_time_old);
|
||||
m_animate_time_old = now;
|
||||
|
||||
// Draw console elements if visible
|
||||
if (m_height > 0)
|
||||
{
|
||||
drawBackground();
|
||||
drawText();
|
||||
drawPrompt();
|
||||
}
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
void GUIChatConsole::reformatConsole()
|
||||
{
|
||||
s32 cols = m_screensize.X / m_fontsize.X - 2; // make room for a margin (looks better)
|
||||
s32 rows = m_desired_height / m_fontsize.Y - 1; // make room for the input prompt
|
||||
if (cols <= 0 || rows <= 0)
|
||||
cols = rows = 0;
|
||||
recalculateConsolePosition();
|
||||
m_chat_backend->reformat(cols, rows);
|
||||
}
|
||||
|
||||
void GUIChatConsole::recalculateConsolePosition()
|
||||
{
|
||||
core::rect<s32> rect(0, 0, m_screensize.X, m_height);
|
||||
DesiredRect = rect;
|
||||
recalculateAbsolutePosition(false);
|
||||
}
|
||||
|
||||
void GUIChatConsole::animate(u32 msec)
|
||||
{
|
||||
// animate the console height
|
||||
s32 goal = m_open ? m_desired_height : 0;
|
||||
|
||||
// Set invisible if close animation finished (reset by openConsole)
|
||||
// This function (animate()) is never called once its visibility becomes false so do not
|
||||
// actually set visible to false before the inhibited period is over
|
||||
if (!m_open && m_height == 0 && m_open_inhibited == 0)
|
||||
IGUIElement::setVisible(false);
|
||||
|
||||
if (m_height != goal)
|
||||
{
|
||||
s32 max_change = msec * m_screensize.Y * (m_height_speed / 1000.0);
|
||||
if (max_change == 0)
|
||||
max_change = 1;
|
||||
|
||||
if (m_height < goal)
|
||||
{
|
||||
// increase height
|
||||
if (m_height + max_change < goal)
|
||||
m_height += max_change;
|
||||
else
|
||||
m_height = goal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// decrease height
|
||||
if (m_height > goal + max_change)
|
||||
m_height -= max_change;
|
||||
else
|
||||
m_height = goal;
|
||||
}
|
||||
|
||||
recalculateConsolePosition();
|
||||
}
|
||||
|
||||
// blink the cursor
|
||||
if (m_cursor_blink_speed != 0.0)
|
||||
{
|
||||
u32 blink_increase = 0x10000 * msec * (m_cursor_blink_speed / 1000.0);
|
||||
if (blink_increase == 0)
|
||||
blink_increase = 1;
|
||||
m_cursor_blink = ((m_cursor_blink + blink_increase) & 0xffff);
|
||||
}
|
||||
|
||||
// decrease open inhibit counter
|
||||
if (m_open_inhibited > msec)
|
||||
m_open_inhibited -= msec;
|
||||
else
|
||||
m_open_inhibited = 0;
|
||||
}
|
||||
|
||||
void GUIChatConsole::drawBackground()
|
||||
{
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
if (m_background != NULL)
|
||||
{
|
||||
core::rect<s32> sourcerect(0, -m_height, m_screensize.X, 0);
|
||||
driver->draw2DImage(
|
||||
m_background,
|
||||
v2s32(0, 0),
|
||||
sourcerect,
|
||||
&AbsoluteClippingRect,
|
||||
m_background_color,
|
||||
false);
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->draw2DRectangle(
|
||||
m_background_color,
|
||||
core::rect<s32>(0, 0, m_screensize.X, m_height),
|
||||
&AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
|
||||
void GUIChatConsole::drawText()
|
||||
{
|
||||
if (m_font == NULL)
|
||||
return;
|
||||
|
||||
ChatBuffer& buf = m_chat_backend->getConsoleBuffer();
|
||||
for (u32 row = 0; row < buf.getRows(); ++row)
|
||||
{
|
||||
const ChatFormattedLine& line = buf.getFormattedLine(row);
|
||||
if (line.fragments.empty())
|
||||
continue;
|
||||
|
||||
s32 line_height = m_fontsize.Y;
|
||||
s32 y = row * line_height + m_height - m_desired_height;
|
||||
if (y + line_height < 0)
|
||||
continue;
|
||||
|
||||
for (const ChatFormattedFragment &fragment : line.fragments) {
|
||||
s32 x = (fragment.column + 1) * m_fontsize.X;
|
||||
core::rect<s32> destrect(
|
||||
x, y, x + m_fontsize.X * fragment.text.size(), y + m_fontsize.Y);
|
||||
|
||||
|
||||
#if USE_FREETYPE
|
||||
// Draw colored text if FreeType is enabled
|
||||
irr::gui::CGUITTFont *tmp = dynamic_cast<irr::gui::CGUITTFont *>(m_font);
|
||||
tmp->draw(
|
||||
fragment.text,
|
||||
destrect,
|
||||
video::SColor(255, 255, 255, 255),
|
||||
false,
|
||||
false,
|
||||
&AbsoluteClippingRect);
|
||||
#else
|
||||
// Otherwise use standard text
|
||||
m_font->draw(
|
||||
fragment.text.c_str(),
|
||||
destrect,
|
||||
video::SColor(255, 255, 255, 255),
|
||||
false,
|
||||
false,
|
||||
&AbsoluteClippingRect);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUIChatConsole::drawPrompt()
|
||||
{
|
||||
if (!m_font)
|
||||
return;
|
||||
|
||||
u32 row = m_chat_backend->getConsoleBuffer().getRows();
|
||||
s32 line_height = m_fontsize.Y;
|
||||
s32 y = row * line_height + m_height - m_desired_height;
|
||||
|
||||
ChatPrompt& prompt = m_chat_backend->getPrompt();
|
||||
std::wstring prompt_text = prompt.getVisiblePortion();
|
||||
|
||||
// FIXME Draw string at once, not character by character
|
||||
// That will only work with the cursor once we have a monospace font
|
||||
for (u32 i = 0; i < prompt_text.size(); ++i)
|
||||
{
|
||||
wchar_t ws[2] = {prompt_text[i], 0};
|
||||
s32 x = (1 + i) * m_fontsize.X;
|
||||
core::rect<s32> destrect(
|
||||
x, y, x + m_fontsize.X, y + m_fontsize.Y);
|
||||
m_font->draw(
|
||||
ws,
|
||||
destrect,
|
||||
video::SColor(255, 255, 255, 255),
|
||||
false,
|
||||
false,
|
||||
&AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
// Draw the cursor during on periods
|
||||
if ((m_cursor_blink & 0x8000) != 0)
|
||||
{
|
||||
s32 cursor_pos = prompt.getVisibleCursorPosition();
|
||||
if (cursor_pos >= 0)
|
||||
{
|
||||
s32 cursor_len = prompt.getCursorLength();
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
s32 x = (1 + cursor_pos) * m_fontsize.X;
|
||||
core::rect<s32> destrect(
|
||||
x,
|
||||
y + m_fontsize.Y * (1.0 - m_cursor_height),
|
||||
x + m_fontsize.X * MYMAX(cursor_len, 1),
|
||||
y + m_fontsize.Y * (cursor_len ? m_cursor_height+1 : 1)
|
||||
);
|
||||
video::SColor cursor_color(255,255,255,255);
|
||||
driver->draw2DRectangle(
|
||||
cursor_color,
|
||||
destrect,
|
||||
&AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool GUIChatConsole::OnEvent(const SEvent& event)
|
||||
{
|
||||
|
||||
ChatPrompt &prompt = m_chat_backend->getPrompt();
|
||||
|
||||
if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
|
||||
{
|
||||
// Key input
|
||||
if (KeyPress(event.KeyInput) == getKeySetting("keymap_console")) {
|
||||
closeConsole();
|
||||
|
||||
// inhibit open so the_game doesn't reopen immediately
|
||||
m_open_inhibited = 50;
|
||||
m_close_on_enter = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.KeyInput.Key == KEY_ESCAPE) {
|
||||
closeConsoleAtOnce();
|
||||
m_close_on_enter = false;
|
||||
// inhibit open so the_game doesn't reopen immediately
|
||||
m_open_inhibited = 1; // so the ESCAPE button doesn't open the "pause menu"
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_PRIOR)
|
||||
{
|
||||
m_chat_backend->scrollPageUp();
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_NEXT)
|
||||
{
|
||||
m_chat_backend->scrollPageDown();
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_RETURN)
|
||||
{
|
||||
prompt.addToHistory(prompt.getLine());
|
||||
std::wstring text = prompt.replace(L"");
|
||||
m_client->typeChatMessage(text);
|
||||
if (m_close_on_enter) {
|
||||
closeConsoleAtOnce();
|
||||
m_close_on_enter = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_UP)
|
||||
{
|
||||
// Up pressed
|
||||
// Move back in history
|
||||
prompt.historyPrev();
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_DOWN)
|
||||
{
|
||||
// Down pressed
|
||||
// Move forward in history
|
||||
prompt.historyNext();
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_LEFT || event.KeyInput.Key == KEY_RIGHT)
|
||||
{
|
||||
// Left/right pressed
|
||||
// Move/select character/word to the left depending on control and shift keys
|
||||
ChatPrompt::CursorOp op = event.KeyInput.Shift ?
|
||||
ChatPrompt::CURSOROP_SELECT :
|
||||
ChatPrompt::CURSOROP_MOVE;
|
||||
ChatPrompt::CursorOpDir dir = event.KeyInput.Key == KEY_LEFT ?
|
||||
ChatPrompt::CURSOROP_DIR_LEFT :
|
||||
ChatPrompt::CURSOROP_DIR_RIGHT;
|
||||
ChatPrompt::CursorOpScope scope = event.KeyInput.Control ?
|
||||
ChatPrompt::CURSOROP_SCOPE_WORD :
|
||||
ChatPrompt::CURSOROP_SCOPE_CHARACTER;
|
||||
prompt.cursorOperation(op, dir, scope);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_HOME)
|
||||
{
|
||||
// Home pressed
|
||||
// move to beginning of line
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_MOVE,
|
||||
ChatPrompt::CURSOROP_DIR_LEFT,
|
||||
ChatPrompt::CURSOROP_SCOPE_LINE);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_END)
|
||||
{
|
||||
// End pressed
|
||||
// move to end of line
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_MOVE,
|
||||
ChatPrompt::CURSOROP_DIR_RIGHT,
|
||||
ChatPrompt::CURSOROP_SCOPE_LINE);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_BACK)
|
||||
{
|
||||
// Backspace or Ctrl-Backspace pressed
|
||||
// delete character / word to the left
|
||||
ChatPrompt::CursorOpScope scope =
|
||||
event.KeyInput.Control ?
|
||||
ChatPrompt::CURSOROP_SCOPE_WORD :
|
||||
ChatPrompt::CURSOROP_SCOPE_CHARACTER;
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_DELETE,
|
||||
ChatPrompt::CURSOROP_DIR_LEFT,
|
||||
scope);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_DELETE)
|
||||
{
|
||||
// Delete or Ctrl-Delete pressed
|
||||
// delete character / word to the right
|
||||
ChatPrompt::CursorOpScope scope =
|
||||
event.KeyInput.Control ?
|
||||
ChatPrompt::CURSOROP_SCOPE_WORD :
|
||||
ChatPrompt::CURSOROP_SCOPE_CHARACTER;
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_DELETE,
|
||||
ChatPrompt::CURSOROP_DIR_RIGHT,
|
||||
scope);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_KEY_A && event.KeyInput.Control)
|
||||
{
|
||||
// Ctrl-A pressed
|
||||
// Select all text
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_SELECT,
|
||||
ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
|
||||
ChatPrompt::CURSOROP_SCOPE_LINE);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_KEY_C && event.KeyInput.Control)
|
||||
{
|
||||
// Ctrl-C pressed
|
||||
// Copy text to clipboard
|
||||
if (prompt.getCursorLength() <= 0)
|
||||
return true;
|
||||
std::wstring wselected = prompt.getSelection();
|
||||
std::string selected(wselected.begin(), wselected.end());
|
||||
Environment->getOSOperator()->copyToClipboard(selected.c_str());
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_KEY_V && event.KeyInput.Control)
|
||||
{
|
||||
// Ctrl-V pressed
|
||||
// paste text from clipboard
|
||||
if (prompt.getCursorLength() > 0) {
|
||||
// Delete selected section of text
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_DELETE,
|
||||
ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
|
||||
ChatPrompt::CURSOROP_SCOPE_SELECTION);
|
||||
}
|
||||
IOSOperator *os_operator = Environment->getOSOperator();
|
||||
const c8 *text = os_operator->getTextFromClipboard();
|
||||
if (!text)
|
||||
return true;
|
||||
std::basic_string<unsigned char> str((const unsigned char*)text);
|
||||
prompt.input(std::wstring(str.begin(), str.end()));
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_KEY_X && event.KeyInput.Control)
|
||||
{
|
||||
// Ctrl-X pressed
|
||||
// Cut text to clipboard
|
||||
if (prompt.getCursorLength() <= 0)
|
||||
return true;
|
||||
std::wstring wselected = prompt.getSelection();
|
||||
std::string selected(wselected.begin(), wselected.end());
|
||||
Environment->getOSOperator()->copyToClipboard(selected.c_str());
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_DELETE,
|
||||
ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
|
||||
ChatPrompt::CURSOROP_SCOPE_SELECTION);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_KEY_U && event.KeyInput.Control)
|
||||
{
|
||||
// Ctrl-U pressed
|
||||
// kill line to left end
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_DELETE,
|
||||
ChatPrompt::CURSOROP_DIR_LEFT,
|
||||
ChatPrompt::CURSOROP_SCOPE_LINE);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_KEY_K && event.KeyInput.Control)
|
||||
{
|
||||
// Ctrl-K pressed
|
||||
// kill line to right end
|
||||
prompt.cursorOperation(
|
||||
ChatPrompt::CURSOROP_DELETE,
|
||||
ChatPrompt::CURSOROP_DIR_RIGHT,
|
||||
ChatPrompt::CURSOROP_SCOPE_LINE);
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key == KEY_TAB)
|
||||
{
|
||||
// Tab or Shift-Tab pressed
|
||||
// Nick completion
|
||||
std::list<std::string> names = m_client->getConnectedPlayerNames();
|
||||
bool backwards = event.KeyInput.Shift;
|
||||
prompt.nickCompletion(names, backwards);
|
||||
return true;
|
||||
} else if (!iswcntrl(event.KeyInput.Char) && !event.KeyInput.Control) {
|
||||
#if defined(__linux__) && (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9)
|
||||
wchar_t wc = L'_';
|
||||
mbtowc( &wc, (char *) &event.KeyInput.Char, sizeof(event.KeyInput.Char) );
|
||||
prompt.input(wc);
|
||||
#else
|
||||
prompt.input(event.KeyInput.Char);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(event.EventType == EET_MOUSE_INPUT_EVENT)
|
||||
{
|
||||
if(event.MouseInput.Event == EMIE_MOUSE_WHEEL)
|
||||
{
|
||||
s32 rows = myround(-3.0 * event.MouseInput.Wheel);
|
||||
m_chat_backend->scroll(rows);
|
||||
}
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
||||
void GUIChatConsole::setVisible(bool visible)
|
||||
{
|
||||
m_open = visible;
|
||||
IGUIElement::setVisible(visible);
|
||||
if (!visible) {
|
||||
m_height = 0;
|
||||
recalculateConsolePosition();
|
||||
}
|
||||
}
|
||||
|
133
src/gui/guiChatConsole.h
Normal file
133
src/gui/guiChatConsole.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "chat.h"
|
||||
#include "config.h"
|
||||
|
||||
class Client;
|
||||
|
||||
class GUIChatConsole : public gui::IGUIElement
|
||||
{
|
||||
public:
|
||||
GUIChatConsole(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent,
|
||||
s32 id,
|
||||
ChatBackend* backend,
|
||||
Client* client,
|
||||
IMenuManager* menumgr);
|
||||
virtual ~GUIChatConsole();
|
||||
|
||||
// Open the console (height = desired fraction of screen size)
|
||||
// This doesn't open immediately but initiates an animation.
|
||||
// You should call isOpenInhibited() before this.
|
||||
void openConsole(f32 scale);
|
||||
|
||||
bool isOpen() const;
|
||||
|
||||
// Check if the console should not be opened at the moment
|
||||
// This is to avoid reopening the console immediately after closing
|
||||
bool isOpenInhibited() const;
|
||||
// Close the console, equivalent to openConsole(0).
|
||||
// This doesn't close immediately but initiates an animation.
|
||||
void closeConsole();
|
||||
// Close the console immediately, without animation.
|
||||
void closeConsoleAtOnce();
|
||||
// Set whether to close the console after the user presses enter.
|
||||
void setCloseOnEnter(bool close) { m_close_on_enter = close; }
|
||||
|
||||
// Return the desired height (fraction of screen size)
|
||||
// Zero if the console is closed or getting closed
|
||||
f32 getDesiredHeight() const;
|
||||
|
||||
// Replace actual line when adding the actual to the history (if there is any)
|
||||
void replaceAndAddToHistory(std::wstring line);
|
||||
|
||||
// Change how the cursor looks
|
||||
void setCursor(
|
||||
bool visible,
|
||||
bool blinking = false,
|
||||
f32 blink_speed = 1.0,
|
||||
f32 relative_height = 1.0);
|
||||
|
||||
// Irrlicht draw method
|
||||
virtual void draw();
|
||||
|
||||
bool canTakeFocus(gui::IGUIElement* element) { return false; }
|
||||
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
private:
|
||||
void reformatConsole();
|
||||
void recalculateConsolePosition();
|
||||
|
||||
// These methods are called by draw
|
||||
void animate(u32 msec);
|
||||
void drawBackground();
|
||||
void drawText();
|
||||
void drawPrompt();
|
||||
|
||||
private:
|
||||
ChatBackend* m_chat_backend;
|
||||
Client* m_client;
|
||||
IMenuManager* m_menumgr;
|
||||
|
||||
// current screen size
|
||||
v2u32 m_screensize;
|
||||
|
||||
// used to compute how much time passed since last animate()
|
||||
u64 m_animate_time_old;
|
||||
|
||||
// should the console be opened or closed?
|
||||
bool m_open = false;
|
||||
// should it close after you press enter?
|
||||
bool m_close_on_enter = false;
|
||||
// current console height [pixels]
|
||||
s32 m_height = 0;
|
||||
// desired height [pixels]
|
||||
f32 m_desired_height = 0.0f;
|
||||
// desired height [screen height fraction]
|
||||
f32 m_desired_height_fraction = 0.0f;
|
||||
// console open/close animation speed [screen height fraction / second]
|
||||
f32 m_height_speed = 5.0f;
|
||||
// if nonzero, opening the console is inhibited [milliseconds]
|
||||
u32 m_open_inhibited = 0;
|
||||
|
||||
// cursor blink frame (16-bit value)
|
||||
// cursor is off during [0,32767] and on during [32768,65535]
|
||||
u32 m_cursor_blink = 0;
|
||||
// cursor blink speed [on/off toggles / second]
|
||||
f32 m_cursor_blink_speed = 0.0f;
|
||||
// cursor height [line height]
|
||||
f32 m_cursor_height = 0.0f;
|
||||
|
||||
// background texture
|
||||
video::ITexture *m_background = nullptr;
|
||||
// background color (including alpha)
|
||||
video::SColor m_background_color = video::SColor(255, 0, 0, 0);
|
||||
|
||||
// font
|
||||
gui::IGUIFont *m_font = nullptr;
|
||||
v2u32 m_fontsize;
|
||||
};
|
1524
src/gui/guiEditBoxWithScrollbar.cpp
Normal file
1524
src/gui/guiEditBoxWithScrollbar.cpp
Normal file
File diff suppressed because it is too large
Load diff
192
src/gui/guiEditBoxWithScrollbar.h
Normal file
192
src/gui/guiEditBoxWithScrollbar.h
Normal file
|
@ -0,0 +1,192 @@
|
|||
// Copyright (C) 2002-2012 Nikolaus Gebhardt, Modified by Mustapha Tachouct
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef GUIEDITBOXWITHSCROLLBAR_HEADER
|
||||
#define GUIEDITBOXWITHSCROLLBAR_HEADER
|
||||
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IOSOperator.h"
|
||||
#include "IGUIScrollBar.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace irr;
|
||||
using namespace irr::gui;
|
||||
|
||||
class GUIEditBoxWithScrollBar : public IGUIEditBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
GUIEditBoxWithScrollBar(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
|
||||
bool writable = true, bool has_vscrollbar = true);
|
||||
|
||||
//! destructor
|
||||
virtual ~GUIEditBoxWithScrollBar();
|
||||
|
||||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont* font = 0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor() const;
|
||||
|
||||
//! Sets if the text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable);
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
//! Turns the border on or off
|
||||
virtual void setDrawBorder(bool border);
|
||||
|
||||
//! Enables or disables word wrap for using the edit box as multiline text editor.
|
||||
virtual void setWordWrap(bool enable);
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
//! \return true if word wrap is enabled, false otherwise
|
||||
virtual bool isWordWrapEnabled() const;
|
||||
|
||||
//! Enables or disables newlines.
|
||||
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
|
||||
instead a newline character will be inserted. */
|
||||
virtual void setMultiLine(bool enable);
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
//! \return true if mult-line is enabled, false otherwise
|
||||
virtual bool isMultiLineEnabled() const;
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
virtual void setAutoScroll(bool enable);
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
virtual bool isAutoScrollEnabled() const;
|
||||
|
||||
//! Gets the size area of the text in the edit box
|
||||
//! \return Returns the size in pixels of the text
|
||||
virtual core::dimension2du getTextDimension();
|
||||
|
||||
//! Sets text justification
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Sets the new caption of this element.
|
||||
virtual void setText(const wchar_t* text);
|
||||
|
||||
//! Sets the maximum amount of characters which may be entered in the box.
|
||||
//! \param max: Maximum amount of characters. If 0, the character amount is
|
||||
//! infinity.
|
||||
virtual void setMax(u32 max);
|
||||
|
||||
//! Returns maximum amount of characters, previously set by setMax();
|
||||
virtual u32 getMax() const;
|
||||
|
||||
//! Sets whether the edit box is a password box. Setting this to true will
|
||||
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
|
||||
\param passwordBox: true to enable password, false to disable
|
||||
\param passwordChar: the character that is displayed instead of letters */
|
||||
virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*');
|
||||
|
||||
//! Returns true if the edit box is currently a password box.
|
||||
virtual bool isPasswordBox() const;
|
||||
|
||||
//! Updates the absolute position, splits text if required
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
virtual void setWritable(bool writable);
|
||||
|
||||
//! Change the background color
|
||||
virtual void setBackgroundColor(const video::SColor &bg_color);
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
//! sets the area of the given line
|
||||
void setTextRect(s32 line);
|
||||
//! returns the line number that the cursor is on
|
||||
s32 getLineFromPos(s32 pos);
|
||||
//! adds a letter to the edit box
|
||||
void inputChar(wchar_t c);
|
||||
//! calculates the current scroll position
|
||||
void calculateScrollPos();
|
||||
//! calculated the FrameRect
|
||||
void calculateFrameRect();
|
||||
//! send some gui event to parent
|
||||
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
||||
//! set text markers
|
||||
void setTextMarkers(s32 begin, s32 end);
|
||||
//! create a Vertical ScrollBar
|
||||
void createVScrollBar();
|
||||
//! update the vertical scrollBar (visibilty & position)
|
||||
void updateVScrollBar();
|
||||
|
||||
bool processKey(const SEvent& event);
|
||||
bool processMouse(const SEvent& event);
|
||||
s32 getCursorPos(s32 x, s32 y);
|
||||
|
||||
bool m_mouse_marking;
|
||||
bool m_border;
|
||||
bool m_background;
|
||||
bool m_override_color_enabled;
|
||||
s32 m_mark_begin;
|
||||
s32 m_mark_end;
|
||||
|
||||
video::SColor m_override_color;
|
||||
gui::IGUIFont *m_override_font, *m_last_break_font;
|
||||
IOSOperator* m_operator;
|
||||
|
||||
u32 m_blink_start_time;
|
||||
s32 m_cursor_pos;
|
||||
s32 m_hscroll_pos, m_vscroll_pos; // scroll position in characters
|
||||
u32 m_max;
|
||||
|
||||
bool m_word_wrap, m_multiline, m_autoscroll, m_passwordbox;
|
||||
wchar_t m_passwordchar;
|
||||
EGUI_ALIGNMENT m_halign, m_valign;
|
||||
|
||||
std::vector<core::stringw> m_broken_text;
|
||||
std::vector<s32> m_broken_text_positions;
|
||||
|
||||
core::rect<s32> m_current_text_rect, m_frame_rect; // temporary values
|
||||
|
||||
u32 m_scrollbar_width;
|
||||
IGUIScrollBar *m_vscrollbar;
|
||||
bool m_writable;
|
||||
|
||||
bool m_bg_color_used;
|
||||
video::SColor m_bg_color;
|
||||
};
|
||||
|
||||
|
||||
#endif // GUIEDITBOXWITHSCROLLBAR_HEADER
|
||||
|
587
src/gui/guiEngine.cpp
Normal file
587
src/gui/guiEngine.cpp
Normal file
|
@ -0,0 +1,587 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 sapier
|
||||
|
||||
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 "guiEngine.h"
|
||||
|
||||
#include <IGUIStaticText.h>
|
||||
#include <ICameraSceneNode.h>
|
||||
#include "client/renderingengine.h"
|
||||
#include "scripting_mainmenu.h"
|
||||
#include "util/numeric.h"
|
||||
#include "config.h"
|
||||
#include "version.h"
|
||||
#include "porting.h"
|
||||
#include "filesys.h"
|
||||
#include "settings.h"
|
||||
#include "guiMainMenu.h"
|
||||
#include "sound.h"
|
||||
#include "sound_openal.h"
|
||||
#include "clouds.h"
|
||||
#include "httpfetch.h"
|
||||
#include "log.h"
|
||||
#include "fontengine.h"
|
||||
#include "guiscalingfilter.h"
|
||||
#include "irrlicht_changes/static_text.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "client/tile.h"
|
||||
#include <GLES/gl.h>
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
void TextDestGuiEngine::gotText(const StringMap &fields)
|
||||
{
|
||||
m_engine->getScriptIface()->handleMainMenuButtons(fields);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void TextDestGuiEngine::gotText(const std::wstring &text)
|
||||
{
|
||||
m_engine->getScriptIface()->handleMainMenuEvent(wide_to_utf8(text));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
MenuTextureSource::~MenuTextureSource()
|
||||
{
|
||||
for (const std::string &texture_to_delete : m_to_delete) {
|
||||
const char *tname = texture_to_delete.c_str();
|
||||
video::ITexture *texture = m_driver->getTexture(tname);
|
||||
m_driver->removeTexture(texture);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
video::ITexture *MenuTextureSource::getTexture(const std::string &name, u32 *id)
|
||||
{
|
||||
if(id)
|
||||
*id = 0;
|
||||
if(name.empty())
|
||||
return NULL;
|
||||
m_to_delete.insert(name);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
video::IImage *image = m_driver->createImageFromFile(name.c_str());
|
||||
if (image) {
|
||||
image = Align2Npot2(image, m_driver);
|
||||
video::ITexture* retval = m_driver->addTexture(name.c_str(), image);
|
||||
image->drop();
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
return m_driver->getTexture(name.c_str());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/** MenuMusicFetcher */
|
||||
/******************************************************************************/
|
||||
void MenuMusicFetcher::fetchSounds(const std::string &name,
|
||||
std::set<std::string> &dst_paths,
|
||||
std::set<std::string> &dst_datas)
|
||||
{
|
||||
if(m_fetched.count(name))
|
||||
return;
|
||||
m_fetched.insert(name);
|
||||
std::string base;
|
||||
base = porting::path_share + DIR_DELIM + "sounds";
|
||||
dst_paths.insert(base + DIR_DELIM + name + ".ogg");
|
||||
int i;
|
||||
for(i=0; i<10; i++)
|
||||
dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg");
|
||||
base = porting::path_user + DIR_DELIM + "sounds";
|
||||
dst_paths.insert(base + DIR_DELIM + name + ".ogg");
|
||||
for(i=0; i<10; i++)
|
||||
dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/** GUIEngine */
|
||||
/******************************************************************************/
|
||||
GUIEngine::GUIEngine(JoystickController *joystick,
|
||||
gui::IGUIElement *parent,
|
||||
IMenuManager *menumgr,
|
||||
MainMenuData *data,
|
||||
bool &kill) :
|
||||
m_parent(parent),
|
||||
m_menumanager(menumgr),
|
||||
m_smgr(RenderingEngine::get_scene_manager()),
|
||||
m_data(data),
|
||||
m_kill(kill)
|
||||
{
|
||||
//initialize texture pointers
|
||||
for (image_definition &texture : m_textures) {
|
||||
texture.texture = NULL;
|
||||
}
|
||||
// is deleted by guiformspec!
|
||||
m_buttonhandler = new TextDestGuiEngine(this);
|
||||
|
||||
//create texture source
|
||||
m_texture_source = new MenuTextureSource(RenderingEngine::get_video_driver());
|
||||
|
||||
//create soundmanager
|
||||
MenuMusicFetcher soundfetcher;
|
||||
#if USE_SOUND
|
||||
m_sound_manager = createOpenALSoundManager(&soundfetcher);
|
||||
#endif
|
||||
if(!m_sound_manager)
|
||||
m_sound_manager = &dummySoundManager;
|
||||
|
||||
//create topleft header
|
||||
m_toplefttext = L"";
|
||||
|
||||
core::rect<s32> rect(0, 0, g_fontengine->getTextWidth(m_toplefttext.c_str()),
|
||||
g_fontengine->getTextHeight());
|
||||
rect += v2s32(4, 0);
|
||||
|
||||
m_irr_toplefttext =
|
||||
addStaticText(RenderingEngine::get_gui_env(), m_toplefttext,
|
||||
rect, false, true, 0, -1);
|
||||
|
||||
//create formspecsource
|
||||
m_formspecgui = new FormspecFormSource("");
|
||||
|
||||
/* Create menu */
|
||||
m_menu = new GUIFormSpecMenu(joystick,
|
||||
m_parent,
|
||||
-1,
|
||||
m_menumanager,
|
||||
NULL /* &client */,
|
||||
m_texture_source,
|
||||
m_formspecgui,
|
||||
m_buttonhandler,
|
||||
false);
|
||||
|
||||
m_menu->allowClose(false);
|
||||
m_menu->lockSize(true,v2u32(800,600));
|
||||
|
||||
// Initialize scripting
|
||||
|
||||
infostream << "GUIEngine: Initializing Lua" << std::endl;
|
||||
|
||||
m_script = new MainMenuScripting(this);
|
||||
|
||||
try {
|
||||
m_script->setMainMenuData(&m_data->script_data);
|
||||
m_data->script_data.errormessage = "";
|
||||
|
||||
if (!loadMainMenuScript()) {
|
||||
errorstream << "No future without main menu!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
run();
|
||||
} catch (LuaError &e) {
|
||||
errorstream << "Main menu error: " << e.what() << std::endl;
|
||||
m_data->script_data.errormessage = e.what();
|
||||
}
|
||||
|
||||
m_menu->quitMenu();
|
||||
m_menu->drop();
|
||||
m_menu = NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
bool GUIEngine::loadMainMenuScript()
|
||||
{
|
||||
// Set main menu path (for core.get_mainmenu_path())
|
||||
m_scriptdir = g_settings->get("main_menu_path");
|
||||
if (m_scriptdir.empty()) {
|
||||
m_scriptdir = porting::path_share + DIR_DELIM + "builtin" + DIR_DELIM + "mainmenu";
|
||||
}
|
||||
|
||||
// Load builtin (which will load the main menu script)
|
||||
std::string script = porting::path_share + DIR_DELIM "builtin" + DIR_DELIM "init.lua";
|
||||
try {
|
||||
m_script->loadScript(script);
|
||||
// Menu script loaded
|
||||
return true;
|
||||
} catch (const ModError &e) {
|
||||
errorstream << "GUIEngine: execution of menu script failed: "
|
||||
<< e.what() << std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::run()
|
||||
{
|
||||
// Always create clouds because they may or may not be
|
||||
// needed based on the game selected
|
||||
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||
|
||||
cloudInit();
|
||||
|
||||
unsigned int text_height = g_fontengine->getTextHeight();
|
||||
|
||||
irr::core::dimension2d<u32> previous_screen_size(g_settings->getU16("screen_w"),
|
||||
g_settings->getU16("screen_h"));
|
||||
|
||||
while (RenderingEngine::run() && (!m_startgame) && (!m_kill)) {
|
||||
|
||||
const irr::core::dimension2d<u32> ¤t_screen_size =
|
||||
RenderingEngine::get_video_driver()->getScreenSize();
|
||||
// Verify if window size has changed and save it if it's the case
|
||||
// Ensure evaluating settings->getBool after verifying screensize
|
||||
// First condition is cheaper
|
||||
if (previous_screen_size != current_screen_size &&
|
||||
current_screen_size != irr::core::dimension2d<u32>(0,0) &&
|
||||
g_settings->getBool("autosave_screensize")) {
|
||||
g_settings->setU16("screen_w", current_screen_size.Width);
|
||||
g_settings->setU16("screen_h", current_screen_size.Height);
|
||||
previous_screen_size = current_screen_size;
|
||||
}
|
||||
|
||||
//check if we need to update the "upper left corner"-text
|
||||
if (text_height != g_fontengine->getTextHeight()) {
|
||||
updateTopLeftTextSize();
|
||||
text_height = g_fontengine->getTextHeight();
|
||||
}
|
||||
|
||||
driver->beginScene(true, true, video::SColor(255,140,186,250));
|
||||
|
||||
if (m_clouds_enabled)
|
||||
{
|
||||
cloudPreProcess();
|
||||
drawOverlay(driver);
|
||||
}
|
||||
else
|
||||
drawBackground(driver);
|
||||
|
||||
drawHeader(driver);
|
||||
drawFooter(driver);
|
||||
|
||||
RenderingEngine::get_gui_env()->drawAll();
|
||||
|
||||
driver->endScene();
|
||||
|
||||
if (m_clouds_enabled)
|
||||
cloudPostProcess();
|
||||
else
|
||||
sleep_ms(25);
|
||||
|
||||
m_script->step();
|
||||
|
||||
#ifdef __ANDROID__
|
||||
m_menu->getAndroidUIInput();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
GUIEngine::~GUIEngine()
|
||||
{
|
||||
if (m_sound_manager != &dummySoundManager){
|
||||
delete m_sound_manager;
|
||||
m_sound_manager = NULL;
|
||||
}
|
||||
|
||||
infostream<<"GUIEngine: Deinitializing scripting"<<std::endl;
|
||||
delete m_script;
|
||||
|
||||
m_irr_toplefttext->setText(L"");
|
||||
|
||||
//clean up texture pointers
|
||||
for (image_definition &texture : m_textures) {
|
||||
if (texture.texture)
|
||||
RenderingEngine::get_video_driver()->removeTexture(texture.texture);
|
||||
}
|
||||
|
||||
delete m_texture_source;
|
||||
|
||||
if (m_cloud.clouds)
|
||||
m_cloud.clouds->drop();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::cloudInit()
|
||||
{
|
||||
m_cloud.clouds = new Clouds(m_smgr, -1, rand());
|
||||
m_cloud.clouds->setHeight(100.0f);
|
||||
m_cloud.clouds->update(v3f(0, 0, 0), video::SColor(255,200,200,255));
|
||||
|
||||
m_cloud.camera = m_smgr->addCameraSceneNode(0,
|
||||
v3f(0,0,0), v3f(0, 60, 100));
|
||||
m_cloud.camera->setFarValue(10000);
|
||||
|
||||
m_cloud.lasttime = RenderingEngine::get_timer_time();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::cloudPreProcess()
|
||||
{
|
||||
u32 time = RenderingEngine::get_timer_time();
|
||||
|
||||
if(time > m_cloud.lasttime)
|
||||
m_cloud.dtime = (time - m_cloud.lasttime) / 1000.0;
|
||||
else
|
||||
m_cloud.dtime = 0;
|
||||
|
||||
m_cloud.lasttime = time;
|
||||
|
||||
m_cloud.clouds->step(m_cloud.dtime*3);
|
||||
m_cloud.clouds->render();
|
||||
m_smgr->drawAll();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::cloudPostProcess()
|
||||
{
|
||||
float fps_max = g_settings->getFloat("pause_fps_max");
|
||||
// Time of frame without fps limit
|
||||
u32 busytime_u32;
|
||||
|
||||
// not using getRealTime is necessary for wine
|
||||
u32 time = RenderingEngine::get_timer_time();
|
||||
if(time > m_cloud.lasttime)
|
||||
busytime_u32 = time - m_cloud.lasttime;
|
||||
else
|
||||
busytime_u32 = 0;
|
||||
|
||||
// FPS limiter
|
||||
u32 frametime_min = 1000./fps_max;
|
||||
|
||||
if (busytime_u32 < frametime_min) {
|
||||
u32 sleeptime = frametime_min - busytime_u32;
|
||||
RenderingEngine::get_raw_device()->sleep(sleeptime);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::drawBackground(video::IVideoDriver *driver)
|
||||
{
|
||||
v2u32 screensize = driver->getScreenSize();
|
||||
|
||||
video::ITexture* texture = m_textures[TEX_LAYER_BACKGROUND].texture;
|
||||
|
||||
/* If no texture, draw background of solid color */
|
||||
if(!texture){
|
||||
video::SColor color(255,80,58,37);
|
||||
core::rect<s32> rect(0, 0, screensize.X, screensize.Y);
|
||||
driver->draw2DRectangle(color, rect, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
v2u32 sourcesize = texture->getOriginalSize();
|
||||
|
||||
if (m_textures[TEX_LAYER_BACKGROUND].tile)
|
||||
{
|
||||
v2u32 tilesize(
|
||||
MYMAX(sourcesize.X,m_textures[TEX_LAYER_BACKGROUND].minsize),
|
||||
MYMAX(sourcesize.Y,m_textures[TEX_LAYER_BACKGROUND].minsize));
|
||||
for (unsigned int x = 0; x < screensize.X; x += tilesize.X )
|
||||
{
|
||||
for (unsigned int y = 0; y < screensize.Y; y += tilesize.Y )
|
||||
{
|
||||
draw2DImageFilterScaled(driver, texture,
|
||||
core::rect<s32>(x, y, x+tilesize.X, y+tilesize.Y),
|
||||
core::rect<s32>(0, 0, sourcesize.X, sourcesize.Y),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Draw background texture */
|
||||
draw2DImageFilterScaled(driver, texture,
|
||||
core::rect<s32>(0, 0, screensize.X, screensize.Y),
|
||||
core::rect<s32>(0, 0, sourcesize.X, sourcesize.Y),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::drawOverlay(video::IVideoDriver *driver)
|
||||
{
|
||||
v2u32 screensize = driver->getScreenSize();
|
||||
|
||||
video::ITexture* texture = m_textures[TEX_LAYER_OVERLAY].texture;
|
||||
|
||||
/* If no texture, draw nothing */
|
||||
if(!texture)
|
||||
return;
|
||||
|
||||
/* Draw background texture */
|
||||
v2u32 sourcesize = texture->getOriginalSize();
|
||||
draw2DImageFilterScaled(driver, texture,
|
||||
core::rect<s32>(0, 0, screensize.X, screensize.Y),
|
||||
core::rect<s32>(0, 0, sourcesize.X, sourcesize.Y),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::drawHeader(video::IVideoDriver *driver)
|
||||
{
|
||||
core::dimension2d<u32> screensize = driver->getScreenSize();
|
||||
|
||||
video::ITexture* texture = m_textures[TEX_LAYER_HEADER].texture;
|
||||
|
||||
/* If no texture, draw nothing */
|
||||
if(!texture)
|
||||
return;
|
||||
|
||||
f32 mult = (((f32)screensize.Width / 2.0)) /
|
||||
((f32)texture->getOriginalSize().Width);
|
||||
|
||||
v2s32 splashsize(((f32)texture->getOriginalSize().Width) * mult,
|
||||
((f32)texture->getOriginalSize().Height) * mult);
|
||||
|
||||
// Don't draw the header if there isn't enough room
|
||||
s32 free_space = (((s32)screensize.Height)-320)/2;
|
||||
|
||||
if (free_space > splashsize.Y) {
|
||||
core::rect<s32> splashrect(0, 0, splashsize.X, splashsize.Y);
|
||||
splashrect += v2s32((screensize.Width/2)-(splashsize.X/2),
|
||||
((free_space/2)-splashsize.Y/2)+10);
|
||||
|
||||
video::SColor bgcolor(255,50,50,50);
|
||||
|
||||
draw2DImageFilterScaled(driver, texture, splashrect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0),
|
||||
core::dimension2di(texture->getOriginalSize())),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::drawFooter(video::IVideoDriver *driver)
|
||||
{
|
||||
core::dimension2d<u32> screensize = driver->getScreenSize();
|
||||
|
||||
video::ITexture* texture = m_textures[TEX_LAYER_FOOTER].texture;
|
||||
|
||||
/* If no texture, draw nothing */
|
||||
if(!texture)
|
||||
return;
|
||||
|
||||
f32 mult = (((f32)screensize.Width)) /
|
||||
((f32)texture->getOriginalSize().Width);
|
||||
|
||||
v2s32 footersize(((f32)texture->getOriginalSize().Width) * mult,
|
||||
((f32)texture->getOriginalSize().Height) * mult);
|
||||
|
||||
// Don't draw the footer if there isn't enough room
|
||||
s32 free_space = (((s32)screensize.Height)-320)/2;
|
||||
|
||||
if (free_space > footersize.Y) {
|
||||
core::rect<s32> rect(0,0,footersize.X,footersize.Y);
|
||||
rect += v2s32(screensize.Width/2,screensize.Height-footersize.Y);
|
||||
rect -= v2s32(footersize.X/2, 0);
|
||||
|
||||
draw2DImageFilterScaled(driver, texture, rect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0),
|
||||
core::dimension2di(texture->getOriginalSize())),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
bool GUIEngine::setTexture(texture_layer layer, std::string texturepath,
|
||||
bool tile_image, unsigned int minsize)
|
||||
{
|
||||
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
|
||||
|
||||
if (m_textures[layer].texture) {
|
||||
driver->removeTexture(m_textures[layer].texture);
|
||||
m_textures[layer].texture = NULL;
|
||||
}
|
||||
|
||||
if (texturepath.empty() || !fs::PathExists(texturepath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_textures[layer].texture = driver->getTexture(texturepath.c_str());
|
||||
m_textures[layer].tile = tile_image;
|
||||
m_textures[layer].minsize = minsize;
|
||||
|
||||
if (!m_textures[layer].texture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
bool GUIEngine::downloadFile(const std::string &url, const std::string &target)
|
||||
{
|
||||
#if USE_CURL
|
||||
std::ofstream target_file(target.c_str(), std::ios::out | std::ios::binary);
|
||||
|
||||
if (!target_file.good()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HTTPFetchRequest fetch_request;
|
||||
HTTPFetchResult fetch_result;
|
||||
fetch_request.url = url;
|
||||
fetch_request.caller = HTTPFETCH_SYNC;
|
||||
fetch_request.timeout = g_settings->getS32("curl_file_download_timeout");
|
||||
httpfetch_sync(fetch_request, fetch_result);
|
||||
|
||||
if (!fetch_result.succeeded) {
|
||||
return false;
|
||||
}
|
||||
target_file << fetch_result.data;
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::setTopleftText(const std::string &text)
|
||||
{
|
||||
m_toplefttext = translate_string(utf8_to_wide(text));
|
||||
|
||||
updateTopLeftTextSize();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::updateTopLeftTextSize()
|
||||
{
|
||||
core::rect<s32> rect(0, 0, g_fontengine->getTextWidth(m_toplefttext.c_str()),
|
||||
g_fontengine->getTextHeight());
|
||||
rect += v2s32(4, 0);
|
||||
|
||||
m_irr_toplefttext->remove();
|
||||
m_irr_toplefttext =
|
||||
addStaticText(RenderingEngine::get_gui_env(), m_toplefttext,
|
||||
rect, false, true, 0, -1);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
s32 GUIEngine::playSound(SimpleSoundSpec spec, bool looped)
|
||||
{
|
||||
s32 handle = m_sound_manager->playSound(spec, looped);
|
||||
return handle;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::stopSound(s32 handle)
|
||||
{
|
||||
m_sound_manager->stopSound(handle);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
unsigned int GUIEngine::queueAsync(const std::string &serialized_func,
|
||||
const std::string &serialized_params)
|
||||
{
|
||||
return m_script->queueAsync(serialized_func, serialized_params);
|
||||
}
|
||||
|
304
src/gui/guiEngine.h
Normal file
304
src/gui/guiEngine.h
Normal file
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 sapier
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
/* Includes */
|
||||
/******************************************************************************/
|
||||
#include "irrlichttypes.h"
|
||||
#include "modalMenu.h"
|
||||
#include "guiFormSpecMenu.h"
|
||||
#include "sound.h"
|
||||
#include "client/tile.h"
|
||||
#include "util/enriched_string.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* Typedefs and macros */
|
||||
/******************************************************************************/
|
||||
/** texture layer ids */
|
||||
typedef enum {
|
||||
TEX_LAYER_BACKGROUND = 0,
|
||||
TEX_LAYER_OVERLAY,
|
||||
TEX_LAYER_HEADER,
|
||||
TEX_LAYER_FOOTER,
|
||||
TEX_LAYER_MAX
|
||||
} texture_layer;
|
||||
|
||||
typedef struct {
|
||||
video::ITexture *texture = nullptr;
|
||||
bool tile;
|
||||
unsigned int minsize;
|
||||
} image_definition;
|
||||
|
||||
/******************************************************************************/
|
||||
/* forward declarations */
|
||||
/******************************************************************************/
|
||||
class GUIEngine;
|
||||
class MainMenuScripting;
|
||||
class Clouds;
|
||||
struct MainMenuData;
|
||||
|
||||
/******************************************************************************/
|
||||
/* declarations */
|
||||
/******************************************************************************/
|
||||
|
||||
/** GUIEngine specific implementation of TextDest used within guiFormSpecMenu */
|
||||
class TextDestGuiEngine : public TextDest
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* default constructor
|
||||
* @param engine the engine data is transmitted for further processing
|
||||
*/
|
||||
TextDestGuiEngine(GUIEngine* engine) : m_engine(engine) {};
|
||||
|
||||
/**
|
||||
* receive fields transmitted by guiFormSpecMenu
|
||||
* @param fields map containing formspec field elements currently active
|
||||
*/
|
||||
void gotText(const StringMap &fields);
|
||||
|
||||
/**
|
||||
* receive text/events transmitted by guiFormSpecMenu
|
||||
* @param text textual representation of event
|
||||
*/
|
||||
void gotText(const std::wstring &text);
|
||||
|
||||
private:
|
||||
/** target to transmit data to */
|
||||
GUIEngine *m_engine = nullptr;
|
||||
};
|
||||
|
||||
/** GUIEngine specific implementation of ISimpleTextureSource */
|
||||
class MenuTextureSource : public ISimpleTextureSource
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* default constructor
|
||||
* @param driver the video driver to load textures from
|
||||
*/
|
||||
MenuTextureSource(video::IVideoDriver *driver) : m_driver(driver) {};
|
||||
|
||||
/**
|
||||
* destructor, removes all loaded textures
|
||||
*/
|
||||
virtual ~MenuTextureSource();
|
||||
|
||||
/**
|
||||
* get a texture, loading it if required
|
||||
* @param name path to the texture
|
||||
* @param id receives the texture ID, always 0 in this implementation
|
||||
*/
|
||||
video::ITexture *getTexture(const std::string &name, u32 *id = NULL);
|
||||
|
||||
private:
|
||||
/** driver to get textures from */
|
||||
video::IVideoDriver *m_driver = nullptr;
|
||||
/** set of texture names to delete */
|
||||
std::set<std::string> m_to_delete;
|
||||
};
|
||||
|
||||
/** GUIEngine specific implementation of OnDemandSoundFetcher */
|
||||
class MenuMusicFetcher: public OnDemandSoundFetcher
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* get sound file paths according to sound name
|
||||
* @param name sound name
|
||||
* @param dst_paths receives possible paths to sound files
|
||||
* @param dst_datas receives binary sound data (not used here)
|
||||
*/
|
||||
void fetchSounds(const std::string &name,
|
||||
std::set<std::string> &dst_paths,
|
||||
std::set<std::string> &dst_datas);
|
||||
|
||||
private:
|
||||
/** set of fetched sound names */
|
||||
std::set<std::string> m_fetched;
|
||||
};
|
||||
|
||||
/** implementation of main menu based uppon formspecs */
|
||||
class GUIEngine {
|
||||
/** grant ModApiMainMenu access to private members */
|
||||
friend class ModApiMainMenu;
|
||||
friend class ModApiSound;
|
||||
|
||||
public:
|
||||
/**
|
||||
* default constructor
|
||||
* @param dev device to draw at
|
||||
* @param parent parent gui element
|
||||
* @param menumgr manager to add menus to
|
||||
* @param smgr scene manager to add scene elements to
|
||||
* @param data struct to transfer data to main game handling
|
||||
*/
|
||||
GUIEngine(JoystickController *joystick,
|
||||
gui::IGUIElement *parent,
|
||||
IMenuManager *menumgr,
|
||||
MainMenuData *data,
|
||||
bool &kill);
|
||||
|
||||
/** default destructor */
|
||||
virtual ~GUIEngine();
|
||||
|
||||
/**
|
||||
* return MainMenuScripting interface
|
||||
*/
|
||||
MainMenuScripting *getScriptIface()
|
||||
{
|
||||
return m_script;
|
||||
}
|
||||
|
||||
/**
|
||||
* return dir of current menuscript
|
||||
*/
|
||||
std::string getScriptDir()
|
||||
{
|
||||
return m_scriptdir;
|
||||
}
|
||||
|
||||
/** pass async callback to scriptengine **/
|
||||
unsigned int queueAsync(const std::string &serialized_fct,
|
||||
const std::string &serialized_params);
|
||||
|
||||
private:
|
||||
|
||||
/** find and run the main menu script */
|
||||
bool loadMainMenuScript();
|
||||
|
||||
/** run main menu loop */
|
||||
void run();
|
||||
|
||||
/** update size of topleftext element */
|
||||
void updateTopLeftTextSize();
|
||||
|
||||
/** parent gui element */
|
||||
gui::IGUIElement *m_parent = nullptr;
|
||||
/** manager to add menus to */
|
||||
IMenuManager *m_menumanager = nullptr;
|
||||
/** scene manager to add scene elements to */
|
||||
scene::ISceneManager *m_smgr = nullptr;
|
||||
/** pointer to data beeing transfered back to main game handling */
|
||||
MainMenuData *m_data = nullptr;
|
||||
/** pointer to texture source */
|
||||
ISimpleTextureSource *m_texture_source = nullptr;
|
||||
/** pointer to soundmanager*/
|
||||
ISoundManager *m_sound_manager = nullptr;
|
||||
|
||||
/** representation of form source to be used in mainmenu formspec */
|
||||
FormspecFormSource *m_formspecgui = nullptr;
|
||||
/** formspec input receiver */
|
||||
TextDestGuiEngine *m_buttonhandler = nullptr;
|
||||
/** the formspec menu */
|
||||
GUIFormSpecMenu *m_menu = nullptr;
|
||||
|
||||
/** reference to kill variable managed by SIGINT handler */
|
||||
bool &m_kill;
|
||||
|
||||
/** variable used to abort menu and return back to main game handling */
|
||||
bool m_startgame = false;
|
||||
|
||||
/** scripting interface */
|
||||
MainMenuScripting *m_script = nullptr;
|
||||
|
||||
/** script basefolder */
|
||||
std::string m_scriptdir = "";
|
||||
|
||||
/**
|
||||
* draw background layer
|
||||
* @param driver to use for drawing
|
||||
*/
|
||||
void drawBackground(video::IVideoDriver *driver);
|
||||
/**
|
||||
* draw overlay layer
|
||||
* @param driver to use for drawing
|
||||
*/
|
||||
void drawOverlay(video::IVideoDriver *driver);
|
||||
/**
|
||||
* draw header layer
|
||||
* @param driver to use for drawing
|
||||
*/
|
||||
void drawHeader(video::IVideoDriver *driver);
|
||||
/**
|
||||
* draw footer layer
|
||||
* @param driver to use for drawing
|
||||
*/
|
||||
void drawFooter(video::IVideoDriver *driver);
|
||||
|
||||
/**
|
||||
* load a texture for a specified layer
|
||||
* @param layer draw layer to specify texture
|
||||
* @param texturepath full path of texture to load
|
||||
*/
|
||||
bool setTexture(texture_layer layer, std::string texturepath,
|
||||
bool tile_image, unsigned int minsize);
|
||||
|
||||
/**
|
||||
* download a file using curl
|
||||
* @param url url to download
|
||||
* @param target file to store to
|
||||
*/
|
||||
static bool downloadFile(const std::string &url, const std::string &target);
|
||||
|
||||
/** array containing pointers to current specified texture layers */
|
||||
image_definition m_textures[TEX_LAYER_MAX];
|
||||
|
||||
/**
|
||||
* specify text to appear as top left string
|
||||
* @param text to set
|
||||
*/
|
||||
void setTopleftText(const std::string &text);
|
||||
|
||||
/** pointer to gui element shown at topleft corner */
|
||||
irr::gui::IGUIStaticText *m_irr_toplefttext = nullptr;
|
||||
/** and text that is in it */
|
||||
EnrichedString m_toplefttext;
|
||||
|
||||
/** initialize cloud subsystem */
|
||||
void cloudInit();
|
||||
/** do preprocessing for cloud subsystem */
|
||||
void cloudPreProcess();
|
||||
/** do postprocessing for cloud subsystem */
|
||||
void cloudPostProcess();
|
||||
|
||||
/** internam data required for drawing clouds */
|
||||
struct clouddata {
|
||||
/** delta time since last cloud processing */
|
||||
f32 dtime;
|
||||
/** absolute time of last cloud processing */
|
||||
u32 lasttime;
|
||||
/** pointer to cloud class */
|
||||
Clouds *clouds = nullptr;
|
||||
/** camera required for drawing clouds */
|
||||
scene::ICameraSceneNode *camera = nullptr;
|
||||
};
|
||||
|
||||
/** is drawing of clouds enabled atm */
|
||||
bool m_clouds_enabled = true;
|
||||
/** data used to draw clouds */
|
||||
clouddata m_cloud;
|
||||
|
||||
/** start playing a sound and return handle */
|
||||
s32 playSound(SimpleSoundSpec spec, bool looped);
|
||||
/** stop playing a sound started with playSound() */
|
||||
void stopSound(s32 handle);
|
||||
|
||||
|
||||
};
|
3864
src/gui/guiFormSpecMenu.cpp
Normal file
3864
src/gui/guiFormSpecMenu.cpp
Normal file
File diff suppressed because it is too large
Load diff
565
src/gui/guiFormSpecMenu.h
Normal file
565
src/gui/guiFormSpecMenu.h
Normal file
|
@ -0,0 +1,565 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <stack>
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "inventorymanager.h"
|
||||
#include "modalMenu.h"
|
||||
#include "guiTable.h"
|
||||
#include "network/networkprotocol.h"
|
||||
#include "client/joystick_controller.h"
|
||||
#include "util/string.h"
|
||||
#include "util/enriched_string.h"
|
||||
|
||||
class InventoryManager;
|
||||
class ISimpleTextureSource;
|
||||
class Client;
|
||||
|
||||
typedef enum {
|
||||
f_Button,
|
||||
f_Table,
|
||||
f_TabHeader,
|
||||
f_CheckBox,
|
||||
f_DropDown,
|
||||
f_ScrollBar,
|
||||
f_Unknown
|
||||
} FormspecFieldType;
|
||||
|
||||
typedef enum {
|
||||
quit_mode_no,
|
||||
quit_mode_accept,
|
||||
quit_mode_cancel
|
||||
} FormspecQuitMode;
|
||||
|
||||
struct TextDest
|
||||
{
|
||||
virtual ~TextDest() = default;
|
||||
|
||||
// This is deprecated I guess? -celeron55
|
||||
virtual void gotText(const std::wstring &text) {}
|
||||
virtual void gotText(const StringMap &fields) = 0;
|
||||
|
||||
std::string m_formname;
|
||||
};
|
||||
|
||||
class IFormSource
|
||||
{
|
||||
public:
|
||||
virtual ~IFormSource() = default;
|
||||
virtual const std::string &getForm() const = 0;
|
||||
// Fill in variables in field text
|
||||
virtual std::string resolveText(const std::string &str) { return str; }
|
||||
};
|
||||
|
||||
class GUIFormSpecMenu : public GUIModalMenu
|
||||
{
|
||||
struct ItemSpec
|
||||
{
|
||||
ItemSpec() = default;
|
||||
|
||||
ItemSpec(const InventoryLocation &a_inventoryloc,
|
||||
const std::string &a_listname,
|
||||
s32 a_i) :
|
||||
inventoryloc(a_inventoryloc),
|
||||
listname(a_listname),
|
||||
i(a_i)
|
||||
{
|
||||
}
|
||||
|
||||
bool isValid() const { return i != -1; }
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
std::string listname;
|
||||
s32 i = -1;
|
||||
};
|
||||
|
||||
struct ListDrawSpec
|
||||
{
|
||||
ListDrawSpec() = default;
|
||||
|
||||
ListDrawSpec(const InventoryLocation &a_inventoryloc,
|
||||
const std::string &a_listname,
|
||||
v2s32 a_pos, v2s32 a_geom, s32 a_start_item_i):
|
||||
inventoryloc(a_inventoryloc),
|
||||
listname(a_listname),
|
||||
pos(a_pos),
|
||||
geom(a_geom),
|
||||
start_item_i(a_start_item_i)
|
||||
{
|
||||
}
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
std::string listname;
|
||||
v2s32 pos;
|
||||
v2s32 geom;
|
||||
s32 start_item_i;
|
||||
};
|
||||
|
||||
struct ListRingSpec
|
||||
{
|
||||
ListRingSpec() = default;
|
||||
|
||||
ListRingSpec(const InventoryLocation &a_inventoryloc,
|
||||
const std::string &a_listname):
|
||||
inventoryloc(a_inventoryloc),
|
||||
listname(a_listname)
|
||||
{
|
||||
}
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
std::string listname;
|
||||
};
|
||||
|
||||
struct ImageDrawSpec
|
||||
{
|
||||
ImageDrawSpec():
|
||||
parent_button(NULL),
|
||||
clip(false)
|
||||
{
|
||||
}
|
||||
|
||||
ImageDrawSpec(const std::string &a_name,
|
||||
const std::string &a_item_name,
|
||||
gui::IGUIButton *a_parent_button,
|
||||
const v2s32 &a_pos, const v2s32 &a_geom):
|
||||
name(a_name),
|
||||
item_name(a_item_name),
|
||||
parent_button(a_parent_button),
|
||||
pos(a_pos),
|
||||
geom(a_geom),
|
||||
scale(true),
|
||||
clip(false)
|
||||
{
|
||||
}
|
||||
|
||||
ImageDrawSpec(const std::string &a_name,
|
||||
const std::string &a_item_name,
|
||||
const v2s32 &a_pos, const v2s32 &a_geom):
|
||||
name(a_name),
|
||||
item_name(a_item_name),
|
||||
parent_button(NULL),
|
||||
pos(a_pos),
|
||||
geom(a_geom),
|
||||
scale(true),
|
||||
clip(false)
|
||||
{
|
||||
}
|
||||
|
||||
ImageDrawSpec(const std::string &a_name,
|
||||
const v2s32 &a_pos, const v2s32 &a_geom, bool clip=false):
|
||||
name(a_name),
|
||||
parent_button(NULL),
|
||||
pos(a_pos),
|
||||
geom(a_geom),
|
||||
scale(true),
|
||||
clip(clip)
|
||||
{
|
||||
}
|
||||
|
||||
ImageDrawSpec(const std::string &a_name,
|
||||
const v2s32 &a_pos):
|
||||
name(a_name),
|
||||
parent_button(NULL),
|
||||
pos(a_pos),
|
||||
scale(false),
|
||||
clip(false)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string item_name;
|
||||
gui::IGUIButton *parent_button;
|
||||
v2s32 pos;
|
||||
v2s32 geom;
|
||||
bool scale;
|
||||
bool clip;
|
||||
};
|
||||
|
||||
struct FieldSpec
|
||||
{
|
||||
FieldSpec() = default;
|
||||
|
||||
FieldSpec(const std::string &name, const std::wstring &label,
|
||||
const std::wstring &default_text, int id) :
|
||||
fname(name),
|
||||
flabel(label),
|
||||
fdefault(unescape_enriched(translate_string(default_text))),
|
||||
fid(id),
|
||||
send(false),
|
||||
ftype(f_Unknown),
|
||||
is_exit(false)
|
||||
{
|
||||
}
|
||||
|
||||
std::string fname;
|
||||
std::wstring flabel;
|
||||
std::wstring fdefault;
|
||||
int fid;
|
||||
bool send;
|
||||
FormspecFieldType ftype;
|
||||
bool is_exit;
|
||||
core::rect<s32> rect;
|
||||
};
|
||||
|
||||
struct BoxDrawSpec
|
||||
{
|
||||
BoxDrawSpec(v2s32 a_pos, v2s32 a_geom,irr::video::SColor a_color):
|
||||
pos(a_pos),
|
||||
geom(a_geom),
|
||||
color(a_color)
|
||||
{
|
||||
}
|
||||
v2s32 pos;
|
||||
v2s32 geom;
|
||||
irr::video::SColor color;
|
||||
};
|
||||
|
||||
struct TooltipSpec
|
||||
{
|
||||
TooltipSpec() = default;
|
||||
TooltipSpec(const std::wstring &a_tooltip, irr::video::SColor a_bgcolor,
|
||||
irr::video::SColor a_color):
|
||||
tooltip(translate_string(a_tooltip)),
|
||||
bgcolor(a_bgcolor),
|
||||
color(a_color)
|
||||
{
|
||||
}
|
||||
|
||||
std::wstring tooltip;
|
||||
irr::video::SColor bgcolor;
|
||||
irr::video::SColor color;
|
||||
};
|
||||
|
||||
struct StaticTextSpec
|
||||
{
|
||||
StaticTextSpec():
|
||||
parent_button(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
StaticTextSpec(const std::wstring &a_text,
|
||||
const core::rect<s32> &a_rect):
|
||||
text(a_text),
|
||||
rect(a_rect),
|
||||
parent_button(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
StaticTextSpec(const std::wstring &a_text,
|
||||
const core::rect<s32> &a_rect,
|
||||
gui::IGUIButton *a_parent_button):
|
||||
text(a_text),
|
||||
rect(a_rect),
|
||||
parent_button(a_parent_button)
|
||||
{
|
||||
}
|
||||
|
||||
std::wstring text;
|
||||
core::rect<s32> rect;
|
||||
gui::IGUIButton *parent_button;
|
||||
};
|
||||
|
||||
public:
|
||||
GUIFormSpecMenu(JoystickController *joystick,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr,
|
||||
Client *client,
|
||||
ISimpleTextureSource *tsrc,
|
||||
IFormSource* fs_src,
|
||||
TextDest* txt_dst,
|
||||
bool remap_dbl_click = true);
|
||||
|
||||
~GUIFormSpecMenu();
|
||||
|
||||
void setFormSpec(const std::string &formspec_string,
|
||||
const InventoryLocation ¤t_inventory_location)
|
||||
{
|
||||
m_formspec_string = formspec_string;
|
||||
m_current_inventory_location = current_inventory_location;
|
||||
regenerateGui(m_screensize_old);
|
||||
}
|
||||
|
||||
// form_src is deleted by this GUIFormSpecMenu
|
||||
void setFormSource(IFormSource *form_src)
|
||||
{
|
||||
delete m_form_src;
|
||||
m_form_src = form_src;
|
||||
}
|
||||
|
||||
// text_dst is deleted by this GUIFormSpecMenu
|
||||
void setTextDest(TextDest *text_dst)
|
||||
{
|
||||
delete m_text_dst;
|
||||
m_text_dst = text_dst;
|
||||
}
|
||||
|
||||
void allowClose(bool value)
|
||||
{
|
||||
m_allowclose = value;
|
||||
}
|
||||
|
||||
void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0))
|
||||
{
|
||||
m_lock = lock;
|
||||
m_lockscreensize = basescreensize;
|
||||
}
|
||||
|
||||
void removeChildren();
|
||||
void setInitialFocus();
|
||||
|
||||
void setFocus(const std::string &elementname)
|
||||
{
|
||||
m_focused_element = elementname;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
ItemSpec getItemAtPos(v2s32 p) const;
|
||||
void drawList(const ListDrawSpec &s, int phase, bool &item_hovered);
|
||||
void drawSelectedItem();
|
||||
void drawMenu();
|
||||
void updateSelectedItem();
|
||||
ItemStack verifySelectedItem();
|
||||
|
||||
void acceptInput(FormspecQuitMode quitmode);
|
||||
bool preprocessEvent(const SEvent& event);
|
||||
bool OnEvent(const SEvent& event);
|
||||
bool doPause;
|
||||
bool pausesGame() { return doPause; }
|
||||
|
||||
GUITable* getTable(const std::string &tablename);
|
||||
std::vector<std::string>* getDropDownValues(const std::string &name);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool getAndroidUIInput();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
v2s32 getBasePos() const
|
||||
{
|
||||
return padding + offset + AbsoluteRect.UpperLeftCorner;
|
||||
}
|
||||
|
||||
v2s32 padding;
|
||||
v2s32 spacing;
|
||||
v2s32 imgsize;
|
||||
v2s32 offset;
|
||||
v2s32 pos_offset;
|
||||
std::stack<v2s32> container_stack;
|
||||
|
||||
InventoryManager *m_invmgr;
|
||||
ISimpleTextureSource *m_tsrc;
|
||||
Client *m_client;
|
||||
|
||||
std::string m_formspec_string;
|
||||
InventoryLocation m_current_inventory_location;
|
||||
|
||||
std::vector<ListDrawSpec> m_inventorylists;
|
||||
std::vector<ListRingSpec> m_inventory_rings;
|
||||
std::vector<ImageDrawSpec> m_backgrounds;
|
||||
std::vector<ImageDrawSpec> m_images;
|
||||
std::vector<ImageDrawSpec> m_itemimages;
|
||||
std::vector<BoxDrawSpec> m_boxes;
|
||||
std::unordered_map<std::string, bool> field_close_on_enter;
|
||||
std::vector<FieldSpec> m_fields;
|
||||
std::vector<StaticTextSpec> m_static_texts;
|
||||
std::vector<std::pair<FieldSpec,GUITable*> > m_tables;
|
||||
std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes;
|
||||
std::map<std::string, TooltipSpec> m_tooltips;
|
||||
std::vector<std::pair<FieldSpec,gui::IGUIScrollBar*> > m_scrollbars;
|
||||
std::vector<std::pair<FieldSpec, std::vector<std::string> > > m_dropdowns;
|
||||
|
||||
ItemSpec *m_selected_item = nullptr;
|
||||
u32 m_selected_amount = 0;
|
||||
bool m_selected_dragging = false;
|
||||
|
||||
// WARNING: BLACK MAGIC
|
||||
// Used to guess and keep up with some special things the server can do.
|
||||
// If name is "", no guess exists.
|
||||
ItemStack m_selected_content_guess;
|
||||
InventoryLocation m_selected_content_guess_inventory;
|
||||
|
||||
v2s32 m_pointer;
|
||||
v2s32 m_old_pointer; // Mouse position after previous mouse event
|
||||
gui::IGUIStaticText *m_tooltip_element = nullptr;
|
||||
|
||||
u64 m_tooltip_show_delay;
|
||||
bool m_tooltip_append_itemname;
|
||||
u64 m_hovered_time = 0;
|
||||
s32 m_old_tooltip_id = -1;
|
||||
|
||||
bool m_auto_place = false;
|
||||
|
||||
bool m_allowclose = true;
|
||||
bool m_lock = false;
|
||||
v2u32 m_lockscreensize;
|
||||
|
||||
bool m_bgfullscreen;
|
||||
bool m_slotborder;
|
||||
video::SColor m_bgcolor;
|
||||
video::SColor m_fullscreen_bgcolor;
|
||||
video::SColor m_slotbg_n;
|
||||
video::SColor m_slotbg_h;
|
||||
video::SColor m_slotbordercolor;
|
||||
video::SColor m_default_tooltip_bgcolor;
|
||||
video::SColor m_default_tooltip_color;
|
||||
|
||||
private:
|
||||
IFormSource *m_form_src;
|
||||
TextDest *m_text_dst;
|
||||
u32 m_formspec_version = 0;
|
||||
std::string m_focused_element = "";
|
||||
JoystickController *m_joystick;
|
||||
|
||||
typedef struct {
|
||||
bool explicit_size;
|
||||
v2f invsize;
|
||||
v2s32 size;
|
||||
v2f32 offset;
|
||||
v2f32 anchor;
|
||||
core::rect<s32> rect;
|
||||
v2s32 basepos;
|
||||
v2u32 screensize;
|
||||
std::string focused_fieldname;
|
||||
GUITable::TableOptions table_options;
|
||||
GUITable::TableColumns table_columns;
|
||||
// used to restore table selection/scroll/treeview state
|
||||
std::unordered_map<std::string, GUITable::DynamicData> table_dyndata;
|
||||
} parserData;
|
||||
|
||||
typedef struct {
|
||||
bool key_up;
|
||||
bool key_down;
|
||||
bool key_enter;
|
||||
bool key_escape;
|
||||
} fs_key_pendig;
|
||||
|
||||
fs_key_pendig current_keys_pending;
|
||||
std::string current_field_enter_pending = "";
|
||||
|
||||
void parseElement(parserData* data, const std::string &element);
|
||||
|
||||
void parseSize(parserData* data, const std::string &element);
|
||||
void parseContainer(parserData* data, const std::string &element);
|
||||
void parseContainerEnd(parserData* data);
|
||||
void parseList(parserData* data, const std::string &element);
|
||||
void parseListRing(parserData* data, const std::string &element);
|
||||
void parseCheckbox(parserData* data, const std::string &element);
|
||||
void parseImage(parserData* data, const std::string &element);
|
||||
void parseItemImage(parserData* data, const std::string &element);
|
||||
void parseButton(parserData* data, const std::string &element,
|
||||
const std::string &typ);
|
||||
void parseBackground(parserData* data, const std::string &element);
|
||||
void parseTableOptions(parserData* data, const std::string &element);
|
||||
void parseTableColumns(parserData* data, const std::string &element);
|
||||
void parseTable(parserData* data, const std::string &element);
|
||||
void parseTextList(parserData* data, const std::string &element);
|
||||
void parseDropDown(parserData* data, const std::string &element);
|
||||
void parseFieldCloseOnEnter(parserData *data, const std::string &element);
|
||||
void parsePwdField(parserData* data, const std::string &element);
|
||||
void parseField(parserData* data, const std::string &element, const std::string &type);
|
||||
void parseSimpleField(parserData* data,std::vector<std::string> &parts);
|
||||
void parseTextArea(parserData* data,std::vector<std::string>& parts,
|
||||
const std::string &type);
|
||||
void parseLabel(parserData* data, const std::string &element);
|
||||
void parseVertLabel(parserData* data, const std::string &element);
|
||||
void parseImageButton(parserData* data, const std::string &element,
|
||||
const std::string &type);
|
||||
void parseItemImageButton(parserData* data, const std::string &element);
|
||||
void parseTabHeader(parserData* data, const std::string &element);
|
||||
void parseBox(parserData* data, const std::string &element);
|
||||
void parseBackgroundColor(parserData* data, const std::string &element);
|
||||
void parseListColors(parserData* data, const std::string &element);
|
||||
void parseTooltip(parserData* data, const std::string &element);
|
||||
bool parseVersionDirect(const std::string &data);
|
||||
bool parseSizeDirect(parserData* data, const std::string &element);
|
||||
void parseScrollBar(parserData* data, const std::string &element);
|
||||
bool parsePositionDirect(parserData *data, const std::string &element);
|
||||
void parsePosition(parserData *data, const std::string &element);
|
||||
bool parseAnchorDirect(parserData *data, const std::string &element);
|
||||
void parseAnchor(parserData *data, const std::string &element);
|
||||
|
||||
void tryClose();
|
||||
|
||||
void showTooltip(const std::wstring &text, const irr::video::SColor &color,
|
||||
const irr::video::SColor &bgcolor);
|
||||
|
||||
/**
|
||||
* check if event is part of a double click
|
||||
* @param event event to evaluate
|
||||
* @return true/false if a doubleclick was detected
|
||||
*/
|
||||
bool DoubleClickDetection(const SEvent event);
|
||||
|
||||
struct clickpos
|
||||
{
|
||||
v2s32 pos;
|
||||
s64 time;
|
||||
};
|
||||
clickpos m_doubleclickdetect[2];
|
||||
|
||||
int m_btn_height;
|
||||
gui::IGUIFont *m_font = nullptr;
|
||||
|
||||
std::wstring getLabelByID(s32 id);
|
||||
std::string getNameByID(s32 id);
|
||||
#ifdef __ANDROID__
|
||||
v2s32 m_down_pos;
|
||||
std::string m_JavaDialogFieldName;
|
||||
#endif
|
||||
|
||||
/* If true, remap a double-click (or double-tap) action to ESC. This is so
|
||||
* that, for example, Android users can double-tap to close a formspec.
|
||||
*
|
||||
* This value can (currently) only be set by the class constructor
|
||||
* and the default value for the setting is true.
|
||||
*/
|
||||
bool m_remap_dbl_click;
|
||||
|
||||
};
|
||||
|
||||
class FormspecFormSource: public IFormSource
|
||||
{
|
||||
public:
|
||||
FormspecFormSource(const std::string &formspec):
|
||||
m_formspec(formspec)
|
||||
{
|
||||
}
|
||||
|
||||
~FormspecFormSource() = default;
|
||||
|
||||
void setForm(const std::string &formspec)
|
||||
{
|
||||
m_formspec = FORMSPEC_VERSION_STRING + formspec;
|
||||
}
|
||||
|
||||
const std::string &getForm() const
|
||||
{
|
||||
return m_formspec;
|
||||
}
|
||||
|
||||
std::string m_formspec;
|
||||
};
|
436
src/gui/guiKeyChangeMenu.cpp
Normal file
436
src/gui/guiKeyChangeMenu.cpp
Normal file
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2013 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||
Copyright (C) 2013 teddydestodes <derkomtur@schattengang.net>
|
||||
|
||||
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 "guiKeyChangeMenu.h"
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "settings.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "mainmenumanager.h" // for g_gamecallback
|
||||
|
||||
#define KMaxButtonPerColumns 12
|
||||
|
||||
extern MainGameCallback *g_gamecallback;
|
||||
|
||||
enum
|
||||
{
|
||||
GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
|
||||
// buttons
|
||||
GUI_ID_KEY_FORWARD_BUTTON,
|
||||
GUI_ID_KEY_BACKWARD_BUTTON,
|
||||
GUI_ID_KEY_LEFT_BUTTON,
|
||||
GUI_ID_KEY_RIGHT_BUTTON,
|
||||
GUI_ID_KEY_USE_BUTTON,
|
||||
GUI_ID_KEY_FLY_BUTTON,
|
||||
GUI_ID_KEY_FAST_BUTTON,
|
||||
GUI_ID_KEY_JUMP_BUTTON,
|
||||
GUI_ID_KEY_NOCLIP_BUTTON,
|
||||
GUI_ID_KEY_CINEMATIC_BUTTON,
|
||||
GUI_ID_KEY_CHAT_BUTTON,
|
||||
GUI_ID_KEY_CMD_BUTTON,
|
||||
GUI_ID_KEY_CMD_LOCAL_BUTTON,
|
||||
GUI_ID_KEY_CONSOLE_BUTTON,
|
||||
GUI_ID_KEY_SNEAK_BUTTON,
|
||||
GUI_ID_KEY_DROP_BUTTON,
|
||||
GUI_ID_KEY_INVENTORY_BUTTON,
|
||||
GUI_ID_KEY_HOTBAR_PREV_BUTTON,
|
||||
GUI_ID_KEY_HOTBAR_NEXT_BUTTON,
|
||||
GUI_ID_KEY_MUTE_BUTTON,
|
||||
GUI_ID_KEY_DEC_VOLUME_BUTTON,
|
||||
GUI_ID_KEY_INC_VOLUME_BUTTON,
|
||||
GUI_ID_KEY_RANGE_BUTTON,
|
||||
GUI_ID_KEY_ZOOM_BUTTON,
|
||||
GUI_ID_KEY_CAMERA_BUTTON,
|
||||
GUI_ID_KEY_MINIMAP_BUTTON,
|
||||
GUI_ID_KEY_SCREENSHOT_BUTTON,
|
||||
GUI_ID_KEY_CHATLOG_BUTTON,
|
||||
GUI_ID_KEY_HUD_BUTTON,
|
||||
GUI_ID_KEY_FOG_BUTTON,
|
||||
GUI_ID_KEY_DEC_RANGE_BUTTON,
|
||||
GUI_ID_KEY_INC_RANGE_BUTTON,
|
||||
GUI_ID_KEY_AUTOFWD_BUTTON,
|
||||
// other
|
||||
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)
|
||||
{
|
||||
init_keys();
|
||||
for (key_setting *ks : key_settings)
|
||||
key_used.push_back(ks->key);
|
||||
}
|
||||
|
||||
GUIKeyChangeMenu::~GUIKeyChangeMenu()
|
||||
{
|
||||
removeChildren();
|
||||
|
||||
for (key_setting *ks : key_settings) {
|
||||
delete[] ks->button_name;
|
||||
delete ks;
|
||||
}
|
||||
key_settings.clear();
|
||||
}
|
||||
|
||||
void GUIKeyChangeMenu::removeChildren()
|
||||
{
|
||||
const core::list<gui::IGUIElement*> &children = getChildren();
|
||||
core::list<gui::IGUIElement*> children_copy;
|
||||
for (gui::IGUIElement*i : children) {
|
||||
children_copy.push_back(i);
|
||||
}
|
||||
|
||||
for (gui::IGUIElement *i : children_copy) {
|
||||
i->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
removeChildren();
|
||||
v2s32 size(745, 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);
|
||||
|
||||
{
|
||||
core::rect < s32 > rect(0, 0, 600, 40);
|
||||
rect += topleft + v2s32(25, 3);
|
||||
//gui::IGUIStaticText *t =
|
||||
const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)");
|
||||
Environment->addStaticText(text,
|
||||
rect, false, true, this, -1);
|
||||
delete[] text;
|
||||
//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, 150, 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 + 120, offset.Y - 5);
|
||||
const wchar_t *text = wgettext(k->key.name());
|
||||
k->button = Environment->addButton(rect, this, k->id, text);
|
||||
delete[] text;
|
||||
}
|
||||
if ((i + 1) % KMaxButtonPerColumns == 0) {
|
||||
offset.X += 230;
|
||||
offset.Y = 60;
|
||||
} else {
|
||||
offset += v2s32(0, 25);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
s32 option_x = offset.X;
|
||||
s32 option_y = offset.Y + 5;
|
||||
u32 option_w = 180;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, option_w, 30);
|
||||
rect += topleft + v2s32(option_x, option_y);
|
||||
const wchar_t *text = wgettext("\"Special\" = climb down");
|
||||
Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
|
||||
GUI_ID_CB_AUX1_DESCENDS, text);
|
||||
delete[] text;
|
||||
}
|
||||
offset += v2s32(0, 25);
|
||||
}
|
||||
|
||||
{
|
||||
s32 option_x = offset.X;
|
||||
s32 option_y = offset.Y + 5;
|
||||
u32 option_w = 280;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, option_w, 30);
|
||||
rect += topleft + v2s32(option_x, option_y);
|
||||
const wchar_t *text = wgettext("Double tap \"jump\" to toggle fly");
|
||||
Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
|
||||
GUI_ID_CB_DOUBLETAP_JUMP, text);
|
||||
delete[] text;
|
||||
}
|
||||
offset += v2s32(0, 25);
|
||||
}
|
||||
|
||||
{
|
||||
core::rect < s32 > rect(0, 0, 100, 30);
|
||||
rect += topleft + v2s32(size.X / 2 - 105, size.Y - 40);
|
||||
const wchar_t *text = wgettext("Save");
|
||||
Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
|
||||
text);
|
||||
delete[] text;
|
||||
}
|
||||
{
|
||||
core::rect < s32 > rect(0, 0, 100, 30);
|
||||
rect += topleft + v2s32(size.X / 2 + 5, size.Y - 40);
|
||||
const wchar_t *text = wgettext("Cancel");
|
||||
Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
|
||||
text);
|
||||
delete[] text;
|
||||
}
|
||||
}
|
||||
|
||||
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, 745, 620);
|
||||
rect += AbsoluteRect.UpperLeftCorner;
|
||||
driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
bool GUIKeyChangeMenu::acceptInput()
|
||||
{
|
||||
for (key_setting *k : key_settings) {
|
||||
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();
|
||||
|
||||
g_gamecallback->signalKeyConfigChange();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUIKeyChangeMenu::resetMenu()
|
||||
{
|
||||
if (activeKey >= 0)
|
||||
{
|
||||
for (key_setting *k : key_settings) {
|
||||
if (k->id == activeKey) {
|
||||
const wchar_t *text = wgettext(k->key.name());
|
||||
k->button->setText(text);
|
||||
delete[] text;
|
||||
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) {
|
||||
|
||||
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);
|
||||
const wchar_t *text = wgettext("Key already in use");
|
||||
this->key_used_text = Environment->addStaticText(text,
|
||||
rect, false, true, this, -1);
|
||||
delete[] text;
|
||||
//infostream << "Key already in use" << std::endl;
|
||||
}
|
||||
|
||||
// But go on
|
||||
{
|
||||
key_setting *k = NULL;
|
||||
for (key_setting *ks : key_settings) {
|
||||
if (ks->id == activeKey) {
|
||||
k = ks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
FATAL_ERROR_IF(k == NULL, "Key setting not found");
|
||||
k->key = kp;
|
||||
const wchar_t *text = wgettext(k->key.name());
|
||||
k->button->setText(text);
|
||||
delete[] text;
|
||||
|
||||
this->key_used.push_back(kp);
|
||||
|
||||
// Allow characters made with shift
|
||||
if(shift_went_down){
|
||||
shift_down = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
activeKey = -1;
|
||||
return true;
|
||||
}
|
||||
} else if (event.EventType == EET_KEY_INPUT_EVENT && activeKey < 0
|
||||
&& event.KeyInput.PressedDown
|
||||
&& event.KeyInput.Key == irr::KEY_ESCAPE) {
|
||||
quitMenu();
|
||||
return true;
|
||||
} else 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)
|
||||
{
|
||||
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 (key_setting *ks : key_settings) {
|
||||
if (ks->id == event.GUIEvent.Caller->getID()) {
|
||||
k = ks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
FATAL_ERROR_IF(k == NULL, "Key setting not found");
|
||||
|
||||
resetMenu();
|
||||
shift_down = false;
|
||||
activeKey = event.GUIEvent.Caller->getID();
|
||||
const wchar_t *text = wgettext("press key");
|
||||
k->button->setText(text);
|
||||
delete[] text;
|
||||
this->key_used.erase(std::remove(this->key_used.begin(),
|
||||
this->key_used.end(), k->key), this->key_used.end());
|
||||
break;
|
||||
}
|
||||
Environment->setFocus(this);
|
||||
}
|
||||
}
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
||||
void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
|
||||
{
|
||||
key_setting *k = new key_setting;
|
||||
k->id = id;
|
||||
|
||||
k->button_name = button_name;
|
||||
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, wgettext("Forward"), "keymap_forward");
|
||||
this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
|
||||
this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
|
||||
this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
|
||||
this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Special"), "keymap_special1");
|
||||
this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
|
||||
this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
|
||||
this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
|
||||
this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
|
||||
this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON,wgettext("Prev. item"), "keymap_hotbar_previous");
|
||||
this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON,wgettext("Next item"), "keymap_hotbar_next");
|
||||
this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom");
|
||||
this->add_key(GUI_ID_KEY_CAMERA_BUTTON, wgettext("Change camera"), "keymap_camera_mode");
|
||||
this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
|
||||
this->add_key(GUI_ID_KEY_MINIMAP_BUTTON, wgettext("Toggle minimap"), "keymap_minimap");
|
||||
this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
|
||||
this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
|
||||
this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
|
||||
this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute");
|
||||
this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON,wgettext("Dec. volume"), "keymap_decrease_volume");
|
||||
this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON,wgettext("Inc. volume"), "keymap_increase_volume");
|
||||
this->add_key(GUI_ID_KEY_AUTOFWD_BUTTON, wgettext("Autoforward"), "keymap_autoforward");
|
||||
this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
|
||||
this->add_key(GUI_ID_KEY_SCREENSHOT_BUTTON,wgettext("Screenshot"), "keymap_screenshot");
|
||||
this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
|
||||
this->add_key(GUI_ID_KEY_DEC_RANGE_BUTTON, wgettext("Dec. range"), "keymap_decrease_viewing_range_min");
|
||||
this->add_key(GUI_ID_KEY_INC_RANGE_BUTTON, wgettext("Inc. range"), "keymap_increase_viewing_range_min");
|
||||
this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
|
||||
this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
|
||||
this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local");
|
||||
this->add_key(GUI_ID_KEY_HUD_BUTTON, wgettext("Toggle HUD"), "keymap_toggle_hud");
|
||||
this->add_key(GUI_ID_KEY_CHATLOG_BUTTON, wgettext("Toggle chat log"), "keymap_toggle_chat");
|
||||
this->add_key(GUI_ID_KEY_FOG_BUTTON, wgettext("Toggle fog"), "keymap_toggle_force_fog_off");
|
||||
}
|
||||
|
74
src/gui/guiKeyChangeMenu.h
Normal file
74
src/gui/guiKeyChangeMenu.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2013 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||
Copyright (C) 2013 teddydestodes <derkomtur@schattengang.net>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include "gettext.h"
|
||||
#include "keycode.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct key_setting
|
||||
{
|
||||
int id;
|
||||
const wchar_t *button_name;
|
||||
KeyPress key;
|
||||
std::string setting_name;
|
||||
gui::IGUIButton *button;
|
||||
};
|
||||
|
||||
class GUIKeyChangeMenu : public GUIModalMenu
|
||||
{
|
||||
public:
|
||||
GUIKeyChangeMenu(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id,
|
||||
IMenuManager *menumgr);
|
||||
~GUIKeyChangeMenu();
|
||||
|
||||
void removeChildren();
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
bool acceptInput();
|
||||
|
||||
bool OnEvent(const SEvent &event);
|
||||
|
||||
bool pausesGame() { return true; }
|
||||
|
||||
private:
|
||||
void init_keys();
|
||||
|
||||
bool resetMenu();
|
||||
|
||||
void add_key(int id, const wchar_t *button_name, const std::string &setting_name);
|
||||
|
||||
bool shift_down = false;
|
||||
s32 activeKey = -1;
|
||||
|
||||
std::vector<KeyPress> key_used;
|
||||
gui::IGUIStaticText *key_used_text = nullptr;
|
||||
std::vector<key_setting *> key_settings;
|
||||
};
|
55
src/gui/guiMainMenu.h
Normal file
55
src/gui/guiMainMenu.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
struct MainMenuDataForScript {
|
||||
|
||||
MainMenuDataForScript() = default;
|
||||
|
||||
// Whether the server has requested a reconnect
|
||||
bool reconnect_requested = false;
|
||||
std::string errormessage = "";
|
||||
};
|
||||
|
||||
struct MainMenuData {
|
||||
// Client options
|
||||
std::string servername;
|
||||
std::string serverdescription;
|
||||
std::string address;
|
||||
std::string port;
|
||||
std::string name;
|
||||
std::string password;
|
||||
// Whether to reconnect
|
||||
bool do_reconnect = false;
|
||||
|
||||
// Server options
|
||||
int selected_world = 0;
|
||||
bool simple_singleplayer_mode = false;
|
||||
|
||||
// Data to be passed to the script
|
||||
MainMenuDataForScript script_data;
|
||||
|
||||
MainMenuData() = default;
|
||||
};
|
261
src/gui/guiPasswordChange.cpp
Normal file
261
src/gui/guiPasswordChange.cpp
Normal file
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
Part of Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2013 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "guiPasswordChange.h"
|
||||
#include "client.h"
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
const int ID_oldPassword = 256;
|
||||
const int ID_newPassword1 = 257;
|
||||
const int ID_newPassword2 = 258;
|
||||
const int ID_change = 259;
|
||||
const int ID_message = 260;
|
||||
const int ID_cancel = 261;
|
||||
|
||||
GUIPasswordChange::GUIPasswordChange(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr,
|
||||
Client* client
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_client(client)
|
||||
{
|
||||
}
|
||||
|
||||
GUIPasswordChange::~GUIPasswordChange()
|
||||
{
|
||||
removeChildren();
|
||||
}
|
||||
|
||||
void GUIPasswordChange::removeChildren()
|
||||
{
|
||||
const core::list<gui::IGUIElement *> &children = getChildren();
|
||||
core::list<gui::IGUIElement *> children_copy;
|
||||
for (gui::IGUIElement *i : children) {
|
||||
children_copy.push_back(i);
|
||||
}
|
||||
|
||||
for (gui::IGUIElement *i : children_copy) {
|
||||
i->remove();
|
||||
}
|
||||
}
|
||||
void GUIPasswordChange::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
/*
|
||||
save current input
|
||||
*/
|
||||
acceptInput();
|
||||
|
||||
/*
|
||||
Remove stuff
|
||||
*/
|
||||
removeChildren();
|
||||
|
||||
/*
|
||||
Calculate new sizes and positions
|
||||
*/
|
||||
core::rect<s32> rect(
|
||||
screensize.X/2 - 580/2,
|
||||
screensize.Y/2 - 300/2,
|
||||
screensize.X/2 + 580/2,
|
||||
screensize.Y/2 + 300/2
|
||||
);
|
||||
|
||||
DesiredRect = rect;
|
||||
recalculateAbsolutePosition(false);
|
||||
|
||||
v2s32 size = rect.getSize();
|
||||
v2s32 topleft_client(40, 0);
|
||||
|
||||
const wchar_t *text;
|
||||
|
||||
/*
|
||||
Add stuff
|
||||
*/
|
||||
s32 ypos = 50;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 150, 20);
|
||||
rect += topleft_client + v2s32(25, ypos + 6);
|
||||
text = wgettext("Old Password");
|
||||
Environment->addStaticText(text, rect, false, true, this, -1);
|
||||
delete[] text;
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 230, 30);
|
||||
rect += topleft_client + v2s32(160, ypos);
|
||||
gui::IGUIEditBox *e = Environment->addEditBox(
|
||||
m_oldpass.c_str(), rect, true, this, ID_oldPassword);
|
||||
Environment->setFocus(e);
|
||||
e->setPasswordBox(true);
|
||||
}
|
||||
ypos += 50;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 150, 20);
|
||||
rect += topleft_client + v2s32(25, ypos + 6);
|
||||
text = wgettext("New Password");
|
||||
Environment->addStaticText(text, rect, false, true, this, -1);
|
||||
delete[] text;
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 230, 30);
|
||||
rect += topleft_client + v2s32(160, ypos);
|
||||
gui::IGUIEditBox *e = Environment->addEditBox(
|
||||
m_newpass.c_str(), rect, true, this, ID_newPassword1);
|
||||
e->setPasswordBox(true);
|
||||
}
|
||||
ypos += 50;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 150, 20);
|
||||
rect += topleft_client + v2s32(25, ypos + 6);
|
||||
text = wgettext("Confirm Password");
|
||||
Environment->addStaticText(text, rect, false, true, this, -1);
|
||||
delete[] text;
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 230, 30);
|
||||
rect += topleft_client + v2s32(160, ypos);
|
||||
gui::IGUIEditBox *e = Environment->addEditBox(
|
||||
m_newpass_confirm.c_str(), rect, true, this, ID_newPassword2);
|
||||
e->setPasswordBox(true);
|
||||
}
|
||||
|
||||
ypos += 50;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 100, 30);
|
||||
rect = rect + v2s32(size.X / 4 + 56, ypos);
|
||||
text = wgettext("Change");
|
||||
Environment->addButton(rect, this, ID_change, text);
|
||||
delete[] text;
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 100, 30);
|
||||
rect = rect + v2s32(size.X / 4 + 185, ypos);
|
||||
text = wgettext("Cancel");
|
||||
Environment->addButton(rect, this, ID_cancel, text);
|
||||
delete[] text;
|
||||
}
|
||||
|
||||
ypos += 50;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 300, 20);
|
||||
rect += topleft_client + v2s32(35, ypos);
|
||||
text = wgettext("Passwords do not match!");
|
||||
IGUIElement *e =
|
||||
Environment->addStaticText(
|
||||
text, rect, false, true, this, ID_message);
|
||||
e->setVisible(false);
|
||||
delete[] text;
|
||||
}
|
||||
}
|
||||
|
||||
void GUIPasswordChange::drawMenu()
|
||||
{
|
||||
gui::IGUISkin *skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
video::IVideoDriver *driver = Environment->getVideoDriver();
|
||||
|
||||
video::SColor bgcolor(140, 0, 0, 0);
|
||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
void GUIPasswordChange::acceptInput()
|
||||
{
|
||||
gui::IGUIElement *e;
|
||||
e = getElementFromId(ID_oldPassword);
|
||||
if (e != NULL)
|
||||
m_oldpass = e->getText();
|
||||
e = getElementFromId(ID_newPassword1);
|
||||
if (e != NULL)
|
||||
m_newpass = e->getText();
|
||||
e = getElementFromId(ID_newPassword2);
|
||||
if (e != NULL)
|
||||
m_newpass_confirm = e->getText();
|
||||
}
|
||||
|
||||
bool GUIPasswordChange::processInput()
|
||||
{
|
||||
if (m_newpass != m_newpass_confirm) {
|
||||
gui::IGUIElement *e = getElementFromId(ID_message);
|
||||
if (e != NULL)
|
||||
e->setVisible(true);
|
||||
return false;
|
||||
}
|
||||
m_client->sendChangePassword(wide_to_utf8(m_oldpass), wide_to_utf8(m_newpass));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUIPasswordChange::OnEvent(const SEvent &event)
|
||||
{
|
||||
if (event.EventType == EET_KEY_INPUT_EVENT) {
|
||||
if (event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown) {
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
if (event.KeyInput.Key == KEY_RETURN && event.KeyInput.PressedDown) {
|
||||
acceptInput();
|
||||
if (processInput())
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (event.EventType == EET_GUI_EVENT) {
|
||||
if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST &&
|
||||
isVisible()) {
|
||||
if (!canTakeFocus(event.GUIEvent.Element)) {
|
||||
dstream << "GUIPasswordChange: Not allowing focus change."
|
||||
<< std::endl;
|
||||
// Returning true disables focus change
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) {
|
||||
switch (event.GUIEvent.Caller->getID()) {
|
||||
case ID_change:
|
||||
acceptInput();
|
||||
if (processInput())
|
||||
quitMenu();
|
||||
return true;
|
||||
case ID_cancel:
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (event.GUIEvent.EventType == gui::EGET_EDITBOX_ENTER) {
|
||||
switch (event.GUIEvent.Caller->getID()) {
|
||||
case ID_oldPassword:
|
||||
case ID_newPassword1:
|
||||
case ID_newPassword2:
|
||||
acceptInput();
|
||||
if (processInput())
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
53
src/gui/guiPasswordChange.h
Normal file
53
src/gui/guiPasswordChange.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Part of Minetest
|
||||
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2013 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include <string>
|
||||
|
||||
class Client;
|
||||
|
||||
class GUIPasswordChange : public GUIModalMenu
|
||||
{
|
||||
public:
|
||||
GUIPasswordChange(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id,
|
||||
IMenuManager *menumgr, Client *client);
|
||||
~GUIPasswordChange();
|
||||
|
||||
void removeChildren();
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
void acceptInput();
|
||||
|
||||
bool processInput();
|
||||
|
||||
bool OnEvent(const SEvent &event);
|
||||
|
||||
private:
|
||||
Client *m_client;
|
||||
std::wstring m_oldpass = L"";
|
||||
std::wstring m_newpass = L"";
|
||||
std::wstring m_newpass_confirm = L"";
|
||||
};
|
113
src/gui/guiPathSelectMenu.cpp
Normal file
113
src/gui/guiPathSelectMenu.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 sapier
|
||||
|
||||
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 "guiPathSelectMenu.h"
|
||||
|
||||
GUIFileSelectMenu::GUIFileSelectMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
|
||||
const std::string &title, const std::string &formname,
|
||||
bool is_file_select) :
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_title(utf8_to_wide(title)),
|
||||
m_formname(formname),
|
||||
m_file_select_dialog(is_file_select)
|
||||
{
|
||||
}
|
||||
|
||||
GUIFileSelectMenu::~GUIFileSelectMenu()
|
||||
{
|
||||
removeChildren();
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
}
|
||||
|
||||
void GUIFileSelectMenu::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
removeChildren();
|
||||
m_fileOpenDialog = 0;
|
||||
|
||||
core::dimension2du size(600, 400);
|
||||
core::rect<s32> rect(0, 0, screensize.X, screensize.Y);
|
||||
|
||||
DesiredRect = rect;
|
||||
recalculateAbsolutePosition(false);
|
||||
|
||||
m_fileOpenDialog =
|
||||
Environment->addFileOpenDialog(m_title.c_str(), false, this, -1);
|
||||
|
||||
core::position2di pos = core::position2di(screensize.X / 2 - size.Width / 2,
|
||||
screensize.Y / 2 - size.Height / 2);
|
||||
m_fileOpenDialog->setRelativePosition(pos);
|
||||
m_fileOpenDialog->setMinSize(size);
|
||||
}
|
||||
|
||||
void GUIFileSelectMenu::drawMenu()
|
||||
{
|
||||
gui::IGUISkin *skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
void GUIFileSelectMenu::acceptInput()
|
||||
{
|
||||
if (m_text_dst && !m_formname.empty()) {
|
||||
StringMap fields;
|
||||
if (m_accepted) {
|
||||
std::string path;
|
||||
if (!m_file_select_dialog) {
|
||||
core::string<fschar_t> string =
|
||||
m_fileOpenDialog->getDirectoryName();
|
||||
path = std::string(string.c_str());
|
||||
} else {
|
||||
path = wide_to_utf8(m_fileOpenDialog->getFileName());
|
||||
}
|
||||
fields[m_formname + "_accepted"] = path;
|
||||
} else {
|
||||
fields[m_formname + "_canceled"] = m_formname;
|
||||
}
|
||||
m_text_dst->gotText(fields);
|
||||
}
|
||||
quitMenu();
|
||||
}
|
||||
|
||||
bool GUIFileSelectMenu::OnEvent(const SEvent &event)
|
||||
{
|
||||
if (event.EventType == irr::EET_GUI_EVENT) {
|
||||
switch (event.GUIEvent.EventType) {
|
||||
case gui::EGET_ELEMENT_CLOSED:
|
||||
case gui::EGET_FILE_CHOOSE_DIALOG_CANCELLED:
|
||||
m_accepted = false;
|
||||
acceptInput();
|
||||
return true;
|
||||
case gui::EGET_DIRECTORY_SELECTED:
|
||||
m_accepted = !m_file_select_dialog;
|
||||
acceptInput();
|
||||
return true;
|
||||
case gui::EGET_FILE_SELECTED:
|
||||
m_accepted = m_file_select_dialog;
|
||||
acceptInput();
|
||||
return true;
|
||||
default:
|
||||
// ignore this event
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
59
src/gui/guiPathSelectMenu.h
Normal file
59
src/gui/guiPathSelectMenu.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 sapier
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "modalMenu.h"
|
||||
#include "IGUIFileOpenDialog.h"
|
||||
#include "guiFormSpecMenu.h" //required because of TextDest only !!!
|
||||
|
||||
class GUIFileSelectMenu : public GUIModalMenu
|
||||
{
|
||||
public:
|
||||
GUIFileSelectMenu(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id,
|
||||
IMenuManager *menumgr, const std::string &title,
|
||||
const std::string &formid, bool is_file_select);
|
||||
~GUIFileSelectMenu();
|
||||
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
bool OnEvent(const SEvent &event);
|
||||
|
||||
void setTextDest(TextDest *dest) { m_text_dst = dest; }
|
||||
|
||||
private:
|
||||
void acceptInput();
|
||||
|
||||
std::wstring m_title;
|
||||
bool m_accepted = false;
|
||||
|
||||
gui::IGUIFileOpenDialog *m_fileOpenDialog = nullptr;
|
||||
|
||||
TextDest *m_text_dst = nullptr;
|
||||
|
||||
std::string m_formname;
|
||||
bool m_file_select_dialog;
|
||||
};
|
1261
src/gui/guiTable.cpp
Normal file
1261
src/gui/guiTable.cpp
Normal file
File diff suppressed because it is too large
Load diff
256
src/gui/guiTable.h
Normal file
256
src/gui/guiTable.h
Normal file
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
|
||||
class ISimpleTextureSource;
|
||||
|
||||
/*
|
||||
A table GUI element for GUIFormSpecMenu.
|
||||
|
||||
Sends a EGET_TABLE_CHANGED event to the parent when
|
||||
an item is selected or double-clicked.
|
||||
Call checkEvent() to get info.
|
||||
|
||||
Credits: The interface and implementation of this class are (very)
|
||||
loosely based on the Irrlicht classes CGUITable and CGUIListBox.
|
||||
CGUITable and CGUIListBox are licensed under the Irrlicht license;
|
||||
they are Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
*/
|
||||
class GUITable : public gui::IGUIElement
|
||||
{
|
||||
public:
|
||||
/*
|
||||
Stores dynamic data that should be preserved
|
||||
when updating a formspec
|
||||
*/
|
||||
struct DynamicData
|
||||
{
|
||||
s32 selected = 0;
|
||||
s32 scrollpos = 0;
|
||||
s32 keynav_time = 0;
|
||||
core::stringw keynav_buffer;
|
||||
std::set<s32> opened_trees;
|
||||
};
|
||||
|
||||
/*
|
||||
An option of the form <name>=<value>
|
||||
*/
|
||||
struct Option
|
||||
{
|
||||
std::string name;
|
||||
std::string value;
|
||||
|
||||
Option(const std::string &name_, const std::string &value_) :
|
||||
name(name_),
|
||||
value(value_)
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
A list of options that concern the entire table
|
||||
*/
|
||||
typedef std::vector<Option> TableOptions;
|
||||
|
||||
/*
|
||||
A column with options
|
||||
*/
|
||||
struct TableColumn
|
||||
{
|
||||
std::string type;
|
||||
std::vector<Option> options;
|
||||
};
|
||||
typedef std::vector<TableColumn> TableColumns;
|
||||
|
||||
|
||||
GUITable(gui::IGUIEnvironment *env,
|
||||
gui::IGUIElement *parent, s32 id,
|
||||
core::rect<s32> rectangle,
|
||||
ISimpleTextureSource *tsrc);
|
||||
|
||||
virtual ~GUITable();
|
||||
|
||||
/* Split a string of the form "name=value" into name and value */
|
||||
static Option splitOption(const std::string &str);
|
||||
|
||||
/* Set textlist-like options, columns and data */
|
||||
void setTextList(const std::vector<std::string> &content,
|
||||
bool transparent);
|
||||
|
||||
/* Set generic table options, columns and content */
|
||||
// Adds empty strings to end of content if there is an incomplete row
|
||||
void setTable(const TableOptions &options,
|
||||
const TableColumns &columns,
|
||||
std::vector<std::string> &content);
|
||||
|
||||
/* Clear the table */
|
||||
void clear();
|
||||
|
||||
/* Get info about last event (string such as "CHG:1:2") */
|
||||
// Call this after EGET_TABLE_CHANGED
|
||||
std::string checkEvent();
|
||||
|
||||
/* Get index of currently selected row (first=1; 0 if none selected) */
|
||||
s32 getSelected() const;
|
||||
|
||||
/* Set currently selected row (first=1; 0 if none selected) */
|
||||
// If given index is not visible at the moment, select its parent
|
||||
// Autoscroll to make the selected row fully visible
|
||||
void setSelected(s32 index);
|
||||
|
||||
/* Get selection, scroll position and opened (sub)trees */
|
||||
DynamicData getDynamicData() const;
|
||||
|
||||
/* Set selection, scroll position and opened (sub)trees */
|
||||
void setDynamicData(const DynamicData &dyndata);
|
||||
|
||||
/* Returns "GUITable" */
|
||||
virtual const c8* getTypeName() const;
|
||||
|
||||
/* Must be called when position or size changes */
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
/* Irrlicht draw method */
|
||||
virtual void draw();
|
||||
|
||||
/* Irrlicht event handler */
|
||||
virtual bool OnEvent(const SEvent &event);
|
||||
|
||||
protected:
|
||||
enum ColumnType {
|
||||
COLUMN_TYPE_TEXT,
|
||||
COLUMN_TYPE_IMAGE,
|
||||
COLUMN_TYPE_COLOR,
|
||||
COLUMN_TYPE_INDENT,
|
||||
COLUMN_TYPE_TREE,
|
||||
};
|
||||
|
||||
struct Cell {
|
||||
s32 xmin;
|
||||
s32 xmax;
|
||||
s32 xpos;
|
||||
ColumnType content_type;
|
||||
s32 content_index;
|
||||
s32 tooltip_index;
|
||||
video::SColor color;
|
||||
bool color_defined;
|
||||
s32 reported_column;
|
||||
};
|
||||
|
||||
struct Row {
|
||||
Cell *cells;
|
||||
s32 cellcount;
|
||||
s32 indent;
|
||||
// visible_index >= 0: is index of row in m_visible_rows
|
||||
// visible_index == -1: parent open but other ancestor closed
|
||||
// visible_index == -2: parent closed
|
||||
s32 visible_index;
|
||||
};
|
||||
|
||||
// Texture source
|
||||
ISimpleTextureSource *m_tsrc;
|
||||
|
||||
// Table content (including hidden rows)
|
||||
std::vector<Row> m_rows;
|
||||
// Table content (only visible; indices into m_rows)
|
||||
std::vector<s32> m_visible_rows;
|
||||
bool m_is_textlist = false;
|
||||
bool m_has_tree_column = false;
|
||||
|
||||
// Selection status
|
||||
s32 m_selected = -1; // index of row (1...n), or 0 if none selected
|
||||
s32 m_sel_column = 0;
|
||||
bool m_sel_doubleclick = false;
|
||||
|
||||
// Keyboard navigation stuff
|
||||
u64 m_keynav_time = 0;
|
||||
core::stringw m_keynav_buffer = L"";
|
||||
|
||||
// Drawing and geometry information
|
||||
bool m_border = true;
|
||||
video::SColor m_color = video::SColor(255, 255, 255, 255);
|
||||
video::SColor m_background = video::SColor(255, 0, 0, 0);
|
||||
video::SColor m_highlight = video::SColor(255, 70, 100, 50);
|
||||
video::SColor m_highlight_text = video::SColor(255, 255, 255, 255);
|
||||
s32 m_rowheight = 1;
|
||||
gui::IGUIFont *m_font = nullptr;
|
||||
gui::IGUIScrollBar *m_scrollbar = nullptr;
|
||||
|
||||
// Allocated strings and images
|
||||
std::vector<core::stringw> m_strings;
|
||||
std::vector<video::ITexture*> m_images;
|
||||
std::map<std::string, s32> m_alloc_strings;
|
||||
std::map<std::string, s32> m_alloc_images;
|
||||
|
||||
s32 allocString(const std::string &text);
|
||||
s32 allocImage(const std::string &imagename);
|
||||
void allocationComplete();
|
||||
|
||||
// Helper for draw() that draws a single cell
|
||||
void drawCell(const Cell *cell, video::SColor color,
|
||||
const core::rect<s32> &rowrect,
|
||||
const core::rect<s32> &client_clip);
|
||||
|
||||
// Returns the i-th visible row (NULL if i is invalid)
|
||||
const Row *getRow(s32 i) const;
|
||||
|
||||
// Key navigation helper
|
||||
bool doesRowStartWith(const Row *row, const core::stringw &str) const;
|
||||
|
||||
// Returns the row at a given screen Y coordinate
|
||||
// Returns index i such that m_rows[i] is valid (or -1 on error)
|
||||
s32 getRowAt(s32 y, bool &really_hovering) const;
|
||||
|
||||
// Returns the cell at a given screen X coordinate within m_rows[row_i]
|
||||
// Returns index j such that m_rows[row_i].cells[j] is valid
|
||||
// (or -1 on error)
|
||||
s32 getCellAt(s32 x, s32 row_i) const;
|
||||
|
||||
// Make the selected row fully visible
|
||||
void autoScroll();
|
||||
|
||||
// Should be called when m_rowcount or m_rowheight changes
|
||||
void updateScrollBar();
|
||||
|
||||
// Sends EET_GUI_EVENT / EGET_TABLE_CHANGED to parent
|
||||
void sendTableEvent(s32 column, bool doubleclick);
|
||||
|
||||
// Functions that help deal with hidden rows
|
||||
// The following functions take raw row indices (hidden rows not skipped)
|
||||
void getOpenedTrees(std::set<s32> &opened_trees) const;
|
||||
void setOpenedTrees(const std::set<s32> &opened_trees);
|
||||
void openTree(s32 to_open);
|
||||
void closeTree(s32 to_close);
|
||||
// The following function takes a visible row index (hidden rows skipped)
|
||||
// dir: -1 = left (close), 0 = auto (toggle), 1 = right (open)
|
||||
void toggleVisibleTree(s32 row_i, int dir, bool move_selection);
|
||||
|
||||
// Aligns cell content in column according to alignment specification
|
||||
// align = 0: left aligned, 1: centered, 2: right aligned, 3: inline
|
||||
static void alignContent(Cell *cell, s32 xmax, s32 content_width,
|
||||
s32 align);
|
||||
};
|
196
src/gui/guiVolumeChange.cpp
Normal file
196
src/gui/guiVolumeChange.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
Part of Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2013 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||
Copyright (C) 2013 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "guiVolumeChange.h"
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIScrollBar.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "settings.h"
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
const int ID_soundText = 263;
|
||||
const int ID_soundExitButton = 264;
|
||||
const int ID_soundSlider = 265;
|
||||
const int ID_soundMuteButton = 266;
|
||||
|
||||
GUIVolumeChange::GUIVolumeChange(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr)
|
||||
{
|
||||
}
|
||||
|
||||
GUIVolumeChange::~GUIVolumeChange()
|
||||
{
|
||||
removeChildren();
|
||||
}
|
||||
|
||||
void GUIVolumeChange::removeChildren()
|
||||
{
|
||||
if (gui::IGUIElement *e = getElementFromId(ID_soundText))
|
||||
e->remove();
|
||||
|
||||
if (gui::IGUIElement *e = getElementFromId(ID_soundExitButton))
|
||||
e->remove();
|
||||
|
||||
if (gui::IGUIElement *e = getElementFromId(ID_soundSlider))
|
||||
e->remove();
|
||||
}
|
||||
|
||||
void GUIVolumeChange::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
/*
|
||||
Remove stuff
|
||||
*/
|
||||
removeChildren();
|
||||
|
||||
/*
|
||||
Calculate new sizes and positions
|
||||
*/
|
||||
DesiredRect = core::rect<s32>(
|
||||
screensize.X/2 - 380/2,
|
||||
screensize.Y/2 - 200/2,
|
||||
screensize.X/2 + 380/2,
|
||||
screensize.Y/2 + 200/2
|
||||
);
|
||||
recalculateAbsolutePosition(false);
|
||||
|
||||
v2s32 size = DesiredRect.getSize();
|
||||
int volume = (int)(g_settings->getFloat("sound_volume") * 100);
|
||||
|
||||
/*
|
||||
Add stuff
|
||||
*/
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 160, 20);
|
||||
rect = rect + v2s32(size.X / 2 - 80, size.Y / 2 - 70);
|
||||
|
||||
const wchar_t *text = wgettext("Sound Volume: ");
|
||||
core::stringw volume_text = text;
|
||||
delete [] text;
|
||||
|
||||
volume_text += core::stringw(volume) + core::stringw("%");
|
||||
Environment->addStaticText(volume_text.c_str(), rect, false,
|
||||
true, this, ID_soundText);
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 80, 30);
|
||||
rect = rect + v2s32(size.X/2-80/2, size.Y/2+55);
|
||||
const wchar_t *text = wgettext("Exit");
|
||||
Environment->addButton(rect, this, ID_soundExitButton,
|
||||
text);
|
||||
delete[] text;
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 300, 20);
|
||||
rect = rect + v2s32(size.X / 2 - 150, size.Y / 2);
|
||||
gui::IGUIScrollBar *e = Environment->addScrollBar(true,
|
||||
rect, this, ID_soundSlider);
|
||||
e->setMax(100);
|
||||
e->setPos(volume);
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 160, 20);
|
||||
rect = rect + v2s32(size.X / 2 - 80, size.Y / 2 - 35);
|
||||
const wchar_t *text = wgettext("Muted");
|
||||
Environment->addCheckBox(g_settings->getBool("mute_sound"), rect, this,
|
||||
ID_soundMuteButton, text);
|
||||
delete[] text;
|
||||
}
|
||||
}
|
||||
|
||||
void GUIVolumeChange::drawMenu()
|
||||
{
|
||||
gui::IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
video::SColor bgcolor(140, 0, 0, 0);
|
||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
bool GUIVolumeChange::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (event.EventType == EET_KEY_INPUT_EVENT) {
|
||||
if (event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown) {
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.KeyInput.Key == KEY_RETURN && event.KeyInput.PressedDown) {
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
} else if (event.EventType == EET_GUI_EVENT) {
|
||||
if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED) {
|
||||
gui::IGUIElement *e = getElementFromId(ID_soundMuteButton);
|
||||
if (e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) {
|
||||
g_settings->setBool("mute_sound", ((gui::IGUICheckBox*)e)->isChecked());
|
||||
}
|
||||
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) {
|
||||
if (event.GUIEvent.Caller->getID() == ID_soundExitButton) {
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
Environment->setFocus(this);
|
||||
}
|
||||
|
||||
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_SCROLL_BAR_CHANGED) {
|
||||
if (event.GUIEvent.Caller->getID() == ID_soundSlider) {
|
||||
s32 pos = ((gui::IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
|
||||
g_settings->setFloat("sound_volume", (float) pos / 100);
|
||||
|
||||
gui::IGUIElement *e = getElementFromId(ID_soundText);
|
||||
const wchar_t *text = wgettext("Sound Volume: ");
|
||||
core::stringw volume_text = text;
|
||||
delete [] text;
|
||||
|
||||
volume_text += core::stringw(pos) + core::stringw("%");
|
||||
e->setText(volume_text.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
45
src/gui/guiVolumeChange.h
Normal file
45
src/gui/guiVolumeChange.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Part of Minetest
|
||||
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2013 Ciaran Gultnieks <ciaran@ciarang.com>
|
||||
Copyright (C) 2013 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
#include <string>
|
||||
|
||||
class GUIVolumeChange : public GUIModalMenu
|
||||
{
|
||||
public:
|
||||
GUIVolumeChange(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr);
|
||||
~GUIVolumeChange();
|
||||
|
||||
void removeChildren();
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
bool OnEvent(const SEvent& event);
|
||||
|
||||
bool pausesGame() { return true; }
|
||||
};
|
1601
src/gui/intlGUIEditBox.cpp
Normal file
1601
src/gui/intlGUIEditBox.cpp
Normal file
File diff suppressed because it is too large
Load diff
198
src/gui/intlGUIEditBox.h
Normal file
198
src/gui/intlGUIEditBox.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
// Copyright (C) 2002-2013 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
//#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEditBox.h"
|
||||
#include "irrArray.h"
|
||||
#include "IOSOperator.h"
|
||||
#include "IGUIScrollBar.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class intlGUIEditBox : public IGUIEditBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
intlGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
|
||||
bool writable = true, bool has_vscrollbar = false);
|
||||
|
||||
//! destructor
|
||||
virtual ~intlGUIEditBox();
|
||||
|
||||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor() const;
|
||||
|
||||
//! Sets if the text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable);
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
//! Turns the border on or off
|
||||
virtual void setDrawBorder(bool border);
|
||||
|
||||
//! Enables or disables word wrap for using the edit box as multiline text editor.
|
||||
virtual void setWordWrap(bool enable);
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
//! \return true if word wrap is enabled, false otherwise
|
||||
virtual bool isWordWrapEnabled() const;
|
||||
|
||||
//! Enables or disables newlines.
|
||||
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
|
||||
instead a newline character will be inserted. */
|
||||
virtual void setMultiLine(bool enable);
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
//! \return true if mult-line is enabled, false otherwise
|
||||
virtual bool isMultiLineEnabled() const;
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
virtual void setAutoScroll(bool enable);
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
virtual bool isAutoScrollEnabled() const;
|
||||
|
||||
//! Gets the size area of the text in the edit box
|
||||
//! \return Returns the size in pixels of the text
|
||||
virtual core::dimension2du getTextDimension();
|
||||
|
||||
//! Sets text justification
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Sets the new caption of this element.
|
||||
virtual void setText(const wchar_t* text);
|
||||
|
||||
//! Sets the maximum amount of characters which may be entered in the box.
|
||||
//! \param max: Maximum amount of characters. If 0, the character amount is
|
||||
//! infinity.
|
||||
virtual void setMax(u32 max);
|
||||
|
||||
//! Returns maximum amount of characters, previously set by setMax();
|
||||
virtual u32 getMax() const;
|
||||
|
||||
//! Sets whether the edit box is a password box. Setting this to true will
|
||||
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
|
||||
\param passwordBox: true to enable password, false to disable
|
||||
\param passwordChar: the character that is displayed instead of letters */
|
||||
virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*');
|
||||
|
||||
//! Returns true if the edit box is currently a password box.
|
||||
virtual bool isPasswordBox() const;
|
||||
|
||||
//! Updates the absolute position, splits text if required
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
//! set true if this EditBox is writable
|
||||
virtual void setWritable(bool can_write_text);
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
//! sets the area of the given line
|
||||
void setTextRect(s32 line);
|
||||
//! returns the line number that the cursor is on
|
||||
s32 getLineFromPos(s32 pos);
|
||||
//! adds a letter to the edit box
|
||||
void inputChar(wchar_t c);
|
||||
//! calculates the current scroll position
|
||||
void calculateScrollPos();
|
||||
//! send some gui event to parent
|
||||
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
||||
//! set text markers
|
||||
void setTextMarkers(s32 begin, s32 end);
|
||||
|
||||
bool processKey(const SEvent& event);
|
||||
bool processMouse(const SEvent& event);
|
||||
s32 getCursorPos(s32 x, s32 y);
|
||||
|
||||
//! Create a vertical scrollbar
|
||||
void createVScrollBar();
|
||||
|
||||
//! Update the vertical scrollbar (visibilty & scroll position)
|
||||
void updateVScrollBar();
|
||||
|
||||
bool MouseMarking = false;
|
||||
bool Border;
|
||||
bool OverrideColorEnabled = false;
|
||||
s32 MarkBegin = 0;
|
||||
s32 MarkEnd = 0;
|
||||
|
||||
video::SColor OverrideColor = video::SColor(101,255,255,255);
|
||||
gui::IGUIFont *OverrideFont = nullptr;
|
||||
gui::IGUIFont *LastBreakFont = nullptr;
|
||||
IOSOperator *Operator = nullptr;
|
||||
|
||||
u64 BlinkStartTime = 0;
|
||||
s32 CursorPos = 0;
|
||||
s32 HScrollPos = 0;
|
||||
s32 VScrollPos = 0; // scroll position in characters
|
||||
u32 Max = 0;
|
||||
|
||||
bool WordWrap = false;
|
||||
bool MultiLine = false;
|
||||
bool AutoScroll = true;
|
||||
bool PasswordBox = false;
|
||||
wchar_t PasswordChar = L'*';
|
||||
EGUI_ALIGNMENT HAlign = EGUIA_UPPERLEFT;
|
||||
EGUI_ALIGNMENT VAlign = EGUIA_CENTER;
|
||||
|
||||
core::array<core::stringw> BrokenText;
|
||||
core::array<s32> BrokenTextPositions;
|
||||
|
||||
core::rect<s32> CurrentTextRect = core::rect<s32>(0,0,1,1);
|
||||
core::rect<s32> FrameRect; // temporary values
|
||||
u32 m_scrollbar_width;
|
||||
IGUIScrollBar *m_vscrollbar;
|
||||
bool m_writable;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
//#endif // _IRR_COMPILE_WITH_GUI_
|
166
src/gui/mainmenumanager.h
Normal file
166
src/gui/mainmenumanager.h
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
All kinds of stuff that needs to be exposed from main.cpp
|
||||
*/
|
||||
#include "modalMenu.h"
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
|
||||
class IGameCallback
|
||||
{
|
||||
public:
|
||||
virtual void exitToOS() = 0;
|
||||
virtual void keyConfig() = 0;
|
||||
virtual void disconnect() = 0;
|
||||
virtual void changePassword() = 0;
|
||||
virtual void changeVolume() = 0;
|
||||
|
||||
virtual void signalKeyConfigChange() = 0;
|
||||
};
|
||||
|
||||
extern gui::IGUIEnvironment *guienv;
|
||||
extern gui::IGUIStaticText *guiroot;
|
||||
|
||||
// Handler for the modal menus
|
||||
|
||||
class MainMenuManager : public IMenuManager
|
||||
{
|
||||
public:
|
||||
virtual void createdMenu(gui::IGUIElement *menu)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (gui::IGUIElement *i : m_stack) {
|
||||
assert(i != menu);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!m_stack.empty())
|
||||
m_stack.back()->setVisible(false);
|
||||
m_stack.push_back(menu);
|
||||
}
|
||||
|
||||
virtual void deletingMenu(gui::IGUIElement *menu)
|
||||
{
|
||||
// Remove all entries if there are duplicates
|
||||
bool removed_entry;
|
||||
do{
|
||||
removed_entry = false;
|
||||
for(std::list<gui::IGUIElement*>::iterator
|
||||
i = m_stack.begin();
|
||||
i != m_stack.end(); ++i)
|
||||
{
|
||||
if(*i == menu)
|
||||
{
|
||||
m_stack.erase(i);
|
||||
removed_entry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while(removed_entry);
|
||||
|
||||
/*core::list<GUIModalMenu*>::Iterator i = m_stack.getLast();
|
||||
assert(*i == menu);
|
||||
m_stack.erase(i);*/
|
||||
|
||||
if(!m_stack.empty())
|
||||
m_stack.back()->setVisible(true);
|
||||
}
|
||||
|
||||
// Returns true to prevent further processing
|
||||
virtual bool preprocessEvent(const SEvent& event)
|
||||
{
|
||||
if (m_stack.empty())
|
||||
return false;
|
||||
GUIModalMenu *mm = dynamic_cast<GUIModalMenu*>(m_stack.back());
|
||||
return mm && mm->preprocessEvent(event);
|
||||
}
|
||||
|
||||
u32 menuCount()
|
||||
{
|
||||
return m_stack.size();
|
||||
}
|
||||
|
||||
bool pausesGame()
|
||||
{
|
||||
for (gui::IGUIElement *i : m_stack) {
|
||||
GUIModalMenu *mm = dynamic_cast<GUIModalMenu*>(i);
|
||||
if (mm && mm->pausesGame())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::list<gui::IGUIElement*> m_stack;
|
||||
};
|
||||
|
||||
extern MainMenuManager g_menumgr;
|
||||
|
||||
extern bool isMenuActive();
|
||||
|
||||
class MainGameCallback : public IGameCallback
|
||||
{
|
||||
public:
|
||||
MainGameCallback() = default;
|
||||
virtual ~MainGameCallback() = default;
|
||||
|
||||
virtual void exitToOS()
|
||||
{
|
||||
shutdown_requested = true;
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
disconnect_requested = true;
|
||||
}
|
||||
|
||||
virtual void changePassword()
|
||||
{
|
||||
changepassword_requested = true;
|
||||
}
|
||||
|
||||
virtual void changeVolume()
|
||||
{
|
||||
changevolume_requested = true;
|
||||
}
|
||||
|
||||
virtual void keyConfig()
|
||||
{
|
||||
keyconfig_requested = true;
|
||||
}
|
||||
|
||||
virtual void signalKeyConfigChange()
|
||||
{
|
||||
keyconfig_changed = true;
|
||||
}
|
||||
|
||||
|
||||
bool disconnect_requested = false;
|
||||
bool changepassword_requested = false;
|
||||
bool changevolume_requested = false;
|
||||
bool keyconfig_requested = false;
|
||||
bool shutdown_requested = false;
|
||||
|
||||
bool keyconfig_changed = false;
|
||||
};
|
||||
|
||||
extern MainGameCallback *g_gamecallback;
|
137
src/gui/modalMenu.h
Normal file
137
src/gui/modalMenu.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
#include "touchscreengui.h"
|
||||
#endif
|
||||
|
||||
class GUIModalMenu;
|
||||
|
||||
class IMenuManager
|
||||
{
|
||||
public:
|
||||
// A GUIModalMenu calls these when this class is passed as a parameter
|
||||
virtual void createdMenu(gui::IGUIElement *menu) = 0;
|
||||
virtual void deletingMenu(gui::IGUIElement *menu) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
Remember to drop() the menu after creating, so that it can
|
||||
remove itself when it wants to.
|
||||
*/
|
||||
|
||||
class GUIModalMenu : public gui::IGUIElement
|
||||
{
|
||||
public:
|
||||
GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr):
|
||||
IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
|
||||
core::rect<s32>(0,0,100,100))
|
||||
{
|
||||
m_menumgr = menumgr;
|
||||
|
||||
setVisible(true);
|
||||
Environment->setFocus(this);
|
||||
m_menumgr->createdMenu(this);
|
||||
}
|
||||
|
||||
virtual ~GUIModalMenu()
|
||||
{
|
||||
m_menumgr->deletingMenu(this);
|
||||
}
|
||||
|
||||
void allowFocusRemoval(bool allow)
|
||||
{
|
||||
m_allow_focus_removal = allow;
|
||||
}
|
||||
|
||||
bool canTakeFocus(gui::IGUIElement *e)
|
||||
{
|
||||
return (e && (e == this || isMyChild(e))) || m_allow_focus_removal;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if(!IsVisible)
|
||||
return;
|
||||
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
v2u32 screensize = driver->getScreenSize();
|
||||
if(screensize != m_screensize_old /*|| m_force_regenerate_gui*/)
|
||||
{
|
||||
m_screensize_old = screensize;
|
||||
regenerateGui(screensize);
|
||||
//m_force_regenerate_gui = false;
|
||||
}
|
||||
|
||||
drawMenu();
|
||||
}
|
||||
|
||||
/*
|
||||
This should be called when the menu wants to quit.
|
||||
|
||||
WARNING: THIS DEALLOCATES THE MENU FROM MEMORY. Return
|
||||
immediately if you call this from the menu itself.
|
||||
|
||||
(More precisely, this decrements the reference count.)
|
||||
*/
|
||||
void quitMenu()
|
||||
{
|
||||
allowFocusRemoval(true);
|
||||
// This removes Environment's grab on us
|
||||
Environment->removeFocus(this);
|
||||
m_menumgr->deletingMenu(this);
|
||||
this->remove();
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
if (g_touchscreengui)
|
||||
g_touchscreengui->show();
|
||||
#endif
|
||||
}
|
||||
|
||||
void removeChildren()
|
||||
{
|
||||
const core::list<gui::IGUIElement*> &children = getChildren();
|
||||
core::list<gui::IGUIElement*> children_copy;
|
||||
for (gui::IGUIElement *i : children) {
|
||||
children_copy.push_back(i);
|
||||
}
|
||||
|
||||
for (gui::IGUIElement *i : children_copy) {
|
||||
i->remove();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void regenerateGui(v2u32 screensize) = 0;
|
||||
virtual void drawMenu() = 0;
|
||||
virtual bool preprocessEvent(const SEvent& event) { return false; };
|
||||
virtual bool OnEvent(const SEvent& event) { return false; };
|
||||
virtual bool pausesGame(){ return false; } // Used for pause menu
|
||||
|
||||
protected:
|
||||
//bool m_force_regenerate_gui;
|
||||
v2u32 m_screensize_old;
|
||||
private:
|
||||
IMenuManager *m_menumgr;
|
||||
// This might be necessary to expose to the implementation if it
|
||||
// wants to launch other menus
|
||||
bool m_allow_focus_removal = false;
|
||||
};
|
1063
src/gui/touchscreengui.cpp
Normal file
1063
src/gui/touchscreengui.cpp
Normal file
File diff suppressed because it is too large
Load diff
267
src/gui/touchscreengui.h
Normal file
267
src/gui/touchscreengui.h
Normal file
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
Copyright (C) 2014 sapier
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IEventReceiver.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIEnvironment.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "client/tile.h"
|
||||
#include "game.h"
|
||||
|
||||
using namespace irr;
|
||||
using namespace irr::core;
|
||||
using namespace irr::gui;
|
||||
|
||||
typedef enum {
|
||||
forward_id = 0,
|
||||
backward_id,
|
||||
left_id,
|
||||
right_id,
|
||||
jump_id,
|
||||
crunch_id,
|
||||
after_last_element_id,
|
||||
settings_starter_id,
|
||||
rare_controls_starter_id,
|
||||
fly_id,
|
||||
noclip_id,
|
||||
fast_id,
|
||||
debug_id,
|
||||
camera_id,
|
||||
range_id,
|
||||
chat_id,
|
||||
inventory_id,
|
||||
drop_id
|
||||
} touch_gui_button_id;
|
||||
|
||||
typedef enum {
|
||||
AHBB_Dir_Top_Bottom,
|
||||
AHBB_Dir_Bottom_Top,
|
||||
AHBB_Dir_Left_Right,
|
||||
AHBB_Dir_Right_Left
|
||||
} autohide_button_bar_dir;
|
||||
|
||||
#define MIN_DIG_TIME_MS 500
|
||||
#define MAX_TOUCH_COUNT 64
|
||||
#define BUTTON_REPEAT_DELAY 0.2f
|
||||
|
||||
#define SETTINGS_BAR_Y_OFFSET 6.5
|
||||
#define RARE_CONTROLS_BAR_Y_OFFSET 4
|
||||
|
||||
extern const char **touchgui_button_imagenames;
|
||||
|
||||
struct button_info
|
||||
{
|
||||
float repeatcounter;
|
||||
float repeatdelay;
|
||||
irr::EKEY_CODE keycode;
|
||||
std::vector<int> ids;
|
||||
IGUIButton *guibutton = nullptr;
|
||||
bool immediate_release;
|
||||
};
|
||||
|
||||
class AutoHideButtonBar
|
||||
{
|
||||
public:
|
||||
AutoHideButtonBar(IrrlichtDevice *device, IEventReceiver *receiver);
|
||||
|
||||
void init(ISimpleTextureSource *tsrc, const char *starter_img, int button_id,
|
||||
v2s32 UpperLeft, v2s32 LowerRight, autohide_button_bar_dir dir,
|
||||
float timeout);
|
||||
|
||||
~AutoHideButtonBar();
|
||||
|
||||
/* add button to be shown */
|
||||
void addButton(touch_gui_button_id id, const wchar_t *caption,
|
||||
const char *btn_image);
|
||||
|
||||
/* detect settings bar button events */
|
||||
bool isButton(const SEvent &event);
|
||||
|
||||
/* handle released hud buttons */
|
||||
bool isReleaseButton(int eventID);
|
||||
|
||||
/* step handler */
|
||||
void step(float dtime);
|
||||
|
||||
/* deactivate button bar */
|
||||
void deactivate();
|
||||
|
||||
/* hide the whole buttonbar */
|
||||
void hide();
|
||||
|
||||
/* unhide the buttonbar */
|
||||
void show();
|
||||
|
||||
private:
|
||||
ISimpleTextureSource *m_texturesource = nullptr;
|
||||
irr::video::IVideoDriver *m_driver;
|
||||
IGUIEnvironment *m_guienv;
|
||||
IEventReceiver *m_receiver;
|
||||
button_info m_starter;
|
||||
std::vector<button_info *> m_buttons;
|
||||
|
||||
v2s32 m_upper_left;
|
||||
v2s32 m_lower_right;
|
||||
|
||||
/* show settings bar */
|
||||
bool m_active = false;
|
||||
|
||||
bool m_visible = true;
|
||||
|
||||
/* settings bar timeout */
|
||||
float m_timeout = 0.0f;
|
||||
float m_timeout_value = 3.0f;
|
||||
bool m_initialized = false;
|
||||
autohide_button_bar_dir m_dir = AHBB_Dir_Right_Left;
|
||||
};
|
||||
|
||||
class TouchScreenGUI
|
||||
{
|
||||
public:
|
||||
TouchScreenGUI(IrrlichtDevice *device, IEventReceiver *receiver);
|
||||
~TouchScreenGUI();
|
||||
|
||||
void translateEvent(const SEvent &event);
|
||||
|
||||
void init(ISimpleTextureSource *tsrc);
|
||||
|
||||
double getYawChange()
|
||||
{
|
||||
double res = m_camera_yaw_change;
|
||||
m_camera_yaw_change = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
double getPitch() { return m_camera_pitch; }
|
||||
|
||||
/*!
|
||||
* Returns a line which describes what the player is pointing at.
|
||||
* The starting point and looking direction are significant,
|
||||
* the line should be scaled to match its length to the actual distance
|
||||
* the player can reach.
|
||||
* The line starts at the camera and ends on the camera's far plane.
|
||||
* The coordinates do not contain the camera offset.
|
||||
*/
|
||||
line3d<f32> getShootline() { return m_shootline; }
|
||||
|
||||
void step(float dtime);
|
||||
void resetHud();
|
||||
void registerHudItem(int index, const rect<s32> &rect);
|
||||
void Toggle(bool visible);
|
||||
|
||||
void hide();
|
||||
void show();
|
||||
|
||||
private:
|
||||
IrrlichtDevice *m_device;
|
||||
IGUIEnvironment *m_guienv;
|
||||
IEventReceiver *m_receiver;
|
||||
ISimpleTextureSource *m_texturesource;
|
||||
v2u32 m_screensize;
|
||||
std::map<int, rect<s32>> m_hud_rects;
|
||||
std::map<int, irr::EKEY_CODE> m_hud_ids;
|
||||
bool m_visible; // is the gui visible
|
||||
|
||||
/* value in degree */
|
||||
double m_camera_yaw_change = 0.0;
|
||||
double m_camera_pitch = 0.0;
|
||||
|
||||
/*!
|
||||
* A line starting at the camera and pointing towards the
|
||||
* selected object.
|
||||
* The line ends on the camera's far plane.
|
||||
* The coordinates do not contain the camera offset.
|
||||
*/
|
||||
line3d<f32> m_shootline;
|
||||
|
||||
int m_move_id = -1;
|
||||
bool m_move_has_really_moved = false;
|
||||
s64 m_move_downtime = 0;
|
||||
bool m_move_sent_as_mouse_event = false;
|
||||
v2s32 m_move_downlocation = v2s32(-10000, -10000);
|
||||
|
||||
button_info m_buttons[after_last_element_id];
|
||||
|
||||
/* gui button detection */
|
||||
touch_gui_button_id getButtonID(s32 x, s32 y);
|
||||
|
||||
/* gui button by eventID */
|
||||
touch_gui_button_id getButtonID(int eventID);
|
||||
|
||||
/* check if a button has changed */
|
||||
void handleChangedButton(const SEvent &event);
|
||||
|
||||
/* initialize a button */
|
||||
void initButton(touch_gui_button_id id, rect<s32> button_rect,
|
||||
std::wstring caption, bool immediate_release,
|
||||
float repeat_delay = BUTTON_REPEAT_DELAY);
|
||||
|
||||
struct id_status
|
||||
{
|
||||
int id;
|
||||
int X;
|
||||
int Y;
|
||||
};
|
||||
|
||||
/* vector to store known ids and their initial touch positions*/
|
||||
std::vector<id_status> m_known_ids;
|
||||
|
||||
/* handle a button event */
|
||||
void handleButtonEvent(touch_gui_button_id bID, int eventID, bool action);
|
||||
|
||||
/* handle pressed hud buttons */
|
||||
bool isHUDButton(const SEvent &event);
|
||||
|
||||
/* handle released hud buttons */
|
||||
bool isReleaseHUDButton(int eventID);
|
||||
|
||||
/* handle double taps */
|
||||
bool doubleTapDetection();
|
||||
|
||||
/* handle release event */
|
||||
void handleReleaseEvent(int evt_id);
|
||||
|
||||
/* get size of regular gui control button */
|
||||
int getGuiButtonSize();
|
||||
|
||||
/* doubleclick detection variables */
|
||||
struct key_event
|
||||
{
|
||||
unsigned int down_time;
|
||||
s32 x;
|
||||
s32 y;
|
||||
};
|
||||
|
||||
/* array for saving last known position of a pointer */
|
||||
v2s32 m_pointerpos[MAX_TOUCH_COUNT];
|
||||
|
||||
/* array for doubletap detection */
|
||||
key_event m_key_events[2];
|
||||
|
||||
/* settings bar */
|
||||
AutoHideButtonBar m_settingsbar;
|
||||
|
||||
/* rare controls bar */
|
||||
AutoHideButtonBar m_rarecontrolsbar;
|
||||
};
|
||||
extern TouchScreenGUI *g_touchscreengui;
|
Loading…
Add table
Add a link
Reference in a new issue