fysxasteroids/engine/IMGUIControls.cc

303 lines
8.1 KiB
C++

#include "IMGUIControls.h"
#include "Engine.h"
#include "ControllerBase.h"
#include "ViewBase.h"
#include <GL/gl.h>
#include "DrawingsGL.h"
#include "keytable.h"
Engine::ControllerBase *controller = NULL;
Engine::ViewBase *view = NULL;
namespace Engine {
namespace GUI {
/** \brief Checks whether the mouse is in the given rectangle */
bool regionhit (int x, int y, int w, int h) {
controller = EngineGetController();
assert (controller);
int mouse_pos[2];
controller->GetMouseScreenPosition(mouse_pos);
if (mouse_pos[0] < x ||
mouse_pos[1] < y ||
mouse_pos[0] >= x + w ||
mouse_pos[1] >= y + h)
return false;
return true;
}
/** \brief Draws a label with a given caption at the position (vertically centered)
*
* This function draws the label at the horizontal x position and centers the
* label with regard to the height of the rendered caption.
*
* \TODO [med] The vertical alignment around the center of the vertical height
* of the string is rather unfortunate as different contents will be rendered
* at different vertical positions (e.g. "aaa" and "ggg")
*/
void Label (int id, const char* caption, int x, int y) {
if (caption != NULL) {
float width, height;
view = EngineGetView ();
assert (view);
glColor3f (1., 1., 1.);
view->DrawGLStringMeasure(caption, &width, &height);
view->DrawGLString(x , y + height * 0.5, caption);
}
}
/** \brief Draws a button at the given position
*
* The area defined by the parameters defines the clickable area. However
* decorations might be drawn on a smaller or bigger area.
*
* \returns true if it was clicked
*
*/
bool Button (int id, const char* caption, int x, int y, int w, int h) {
controller = EngineGetController();
assert (controller);
// LogMessage ("id = %d hotitem = %d activeitem = %d kbditem = %d", id, controller->uistate.hotitem, controller->uistate.activeitem, controller->uistate.kbditem);
// Check for hotness
if (regionhit (x, y, w, h)) {
controller->uistate.hotitem = id;
if (controller->uistate.activeitem == 0
&& controller->GetButtonState(MouseButtonLeft))
controller->uistate.activeitem = id;
}
// If nothing is selected
if (controller->uistate.hotitem != 0) {
controller->uistate.kbditem = controller->uistate.hotitem;
}
if (controller->uistate.kbditem == 0) {
controller->uistate.hotitem = id;
controller->uistate.kbditem = id;
}
// Render
glColor3f (0.2, 0.2, 0.2);
DrawRect2D (x + 4, y + 4, w, h);
if (controller->uistate.hotitem == id
|| controller->uistate.kbditem == id) {
if (controller->uistate.activeitem == id) {
glColor3f (0.8, 0.8, 0.8);
DrawRect2D (x, y, w, h);
} else {
glColor3f (0.7, 0.7, 0.7);
DrawRect2D (x, y, w, h);
}
} else {
glColor3f (0.4, 0.4, 0.4);
DrawRect2D (x, y, w, h);
}
// Caption
if (caption != NULL) {
float width, height;
view = EngineGetView ();
assert (view);
glColor3f (1., 1., 1.);
view->DrawGLStringMeasure(caption, &width, &height);
view->DrawGLString(x + w * 0.5 - width * 0.5, y + h * 0.5 - height * 0.5, caption);
}
// Mouse Logic
if (controller->GetButtonState(MouseButtonLeft) == false
&& controller->uistate.hotitem == id
&& controller->uistate.activeitem == id) {
controller->uistate.lastwidget = id;
return true;
}
// Keyboard Logic
if (controller->uistate.kbditem == id) {
// Any unicode keys that were sent get cleared
controller->uistate.last_unicode = 0;
// We have to make sure, that we always clear the uistate.last_keysym
// value, otherwise the same action might be repeated over and over.
switch (controller->uistate.last_keysym) {
case SDLK_DOWN:
controller->uistate.kbditem = 0;
controller->uistate.hotitem = 0;
controller->uistate.last_keysym = SDLK_CLEAR;
break;
case SDLK_UP:
controller->uistate.kbditem = controller->uistate.lastwidget;
controller->uistate.hotitem = controller->uistate.lastwidget;
controller->uistate.last_keysym = SDLK_CLEAR;
break;
case SDLK_RETURN:
controller->uistate.last_keysym = SDLK_CLEAR;
// As we (probably) exit the current set of widgets, we have to clear
// the uistate.kbditem value.
controller->uistate.kbditem = 0;
return true;
break;
}
}
controller->uistate.lastwidget = id;
return false;
}
/** \brief An Edit widget that allows editing of a string consisting of one line
*
* \TODO [med] vertical alignment (especially of text) is a bit whacky
*
* \returns true if it was clicked
*
*/
bool LineEdit (int id, int x, int y, std::string &text_value, const int &maxlength) {
controller = EngineGetController();
assert (controller);
int w = maxlength * 16;
int h = 16;
// LogMessage ("id = %d hotitem = %d activeitem = %d kbditem = %d key = %s", id, controller->uistate.hotitem, controller->uistate.activeitem, controller->uistate.kbditem, convert_keycode (controller->uistate.last_keysym));
// Check for hotness
if (regionhit (x, y, w, h)) {
controller->uistate.hotitem = id;
if (controller->uistate.activeitem == 0
&& controller->GetButtonState(MouseButtonLeft)) {
controller->uistate.activeitem = id;
}
}
if (controller->uistate.kbditem == 0) {
controller->uistate.hotitem = id;
controller->uistate.kbditem = id;
controller->uistate.last_unicode = 0;
return false;
}
// Render
glColor3f (0.2, 0.2, 0.2);
DrawRect2D (x + 4, y + 4, w, h);
// If we have keyboard focus, we highlight the widget
if ( controller->uistate.kbditem == id) {
if (controller->uistate.activeitem == id) {
glColor3f (0.8, 0.8, 0.8);
DrawRect2D (x, y, w, h);
} else {
glColor3f (0.7, 0.7, 0.7);
DrawRect2D (x, y, w, h);
}
} else {
glColor3f (0.4, 0.4, 0.4);
DrawRect2D (x, y, w, h);
}
// Rendering of the current value
float width, height;
view = EngineGetView ();
assert (view);
glColor3f (1., 1., 1.);
std::string text_output = text_value;
if (controller->uistate.kbditem == id && SDL_GetTicks() >> 9 & 1)
text_output += "_";
view->DrawGLStringMeasure(text_value.c_str(), &width, &height);
view->DrawGLString(x + 16, y + 12, text_output.c_str());
// Keyboard Logic
if (controller->uistate.kbditem == id) {
switch (controller->uistate.last_keysym) {
case SDLK_DOWN:
controller->uistate.kbditem = 0;
controller->uistate.hotitem = 0;
controller->uistate.last_keysym = SDLK_CLEAR;
break;
case SDLK_UP:
controller->uistate.kbditem = controller->uistate.lastwidget;
controller->uistate.hotitem = controller->uistate.lastwidget;
controller->uistate.last_keysym = SDLK_CLEAR;
break;
case SDLK_CLEAR:
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
return false;
break;
case SDLK_ESCAPE:
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
controller->uistate.hotitem = 0;
controller->uistate.kbditem = 0;
return false;
break;
case SDLK_RETURN:
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
controller->uistate.hotitem = 0;
controller->uistate.kbditem = 0;
return true;
break;
case SDLK_BACKSPACE:
if (text_value.size() > 0) {
text_value = text_value.substr(0, text_value.size() - 1);
controller->uistate.last_keysym = SDLK_CLEAR;
controller->uistate.last_unicode = 0;
return true;
}
break;
default:
// The raw input processing
if (maxlength > 0 && text_value.size() < maxlength) {
if (controller->uistate.last_unicode) {
if ((controller->uistate.last_unicode & 0xFF80) == 0) {
text_value += controller->uistate.last_unicode & 0x7F;
controller->uistate.last_unicode = 0;
return true;
} else {
LogWarning ("Input key not supported!");
return false;
}
}
}
break;
}
}
controller->uistate.lastwidget = id;
// Mouse Logic
if (controller->GetButtonState(MouseButtonLeft) == false
&& controller->uistate.hotitem == id
&& controller->uistate.activeitem == id) {
controller->uistate.kbditem = id;
controller->uistate.last_unicode = 0;
}
return false;
}
bool CheckKeyPress (int keycode) {
if (controller->uistate.last_keysym == keycode)
return true;
return false;
}
};
};