1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Move files to subdirectories (#6599)

* Move files around
This commit is contained in:
Vitaliy 2017-11-09 01:56:20 +03:00 committed by Loïc Blot
parent fc9747eb4b
commit 20a85d76d9
118 changed files with 236 additions and 221 deletions

13
src/gui/CMakeLists.txt Normal file
View 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
View 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
View 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;
};

File diff suppressed because it is too large Load diff

View 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
View 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> &current_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
View 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

File diff suppressed because it is too large Load diff

565
src/gui/guiFormSpecMenu.h Normal file
View 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 &current_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;
};

View 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");
}

View 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
View 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;
};

View 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;
}

View 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"";
};

View 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;
}

View 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

File diff suppressed because it is too large Load diff

256
src/gui/guiTable.h Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

198
src/gui/intlGUIEditBox.h Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

267
src/gui/touchscreengui.h Normal file
View 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;