A bunch of updates:
- Added *unfinished* control input. - The GUI captures the events now, so that you can't press anything in the game if the GUI is infront of it. The GUI needs some cleaning up though. - Made the type 'empty' unpressable, because all those "0 0 100% 100%" empties were just like pieces of glass making the user unable to select anything in the game. - A bunch of other updates I made like weeks ago and never committed. This was SVN commit r1234.
This commit is contained in:
parent
1d4ebcca24
commit
f4b410ff82
@ -17,6 +17,7 @@ using namespace std;
|
||||
//-------------------------------------------------------------------
|
||||
CButton::CButton()
|
||||
{
|
||||
AddSetting(GUIST_float, "buffer-zone");
|
||||
AddSetting(GUIST_CGUIString, "caption");
|
||||
AddSetting(GUIST_CStr, "font");
|
||||
AddSetting(GUIST_CStr, "sprite");
|
||||
@ -61,40 +62,42 @@ void CButton::SetupText()
|
||||
// Check which alignment to use!
|
||||
EAlign align;
|
||||
EVAlign valign;
|
||||
float bz;
|
||||
GUI<EAlign>::GetSetting(this, "text-align", align);
|
||||
GUI<EVAlign>::GetSetting(this, "text-valign", valign);
|
||||
|
||||
m_TextPos = m_CachedActualSize.TopLeft();
|
||||
GUI<float>::GetSetting(this, "buffer-zone", bz);
|
||||
|
||||
switch (align)
|
||||
{
|
||||
case EAlign_Left:
|
||||
m_TextPos.x = m_CachedActualSize.left;
|
||||
m_TextPos.x = m_CachedActualSize.left + bz;
|
||||
break;
|
||||
case EAlign_Center:
|
||||
// Round to integer pixel values, else the fonts look awful
|
||||
m_TextPos.x = floorf(m_CachedActualSize.CenterPoint().x - m_GeneratedTexts[0]->m_Size.cx/2.f);
|
||||
break;
|
||||
case EAlign_Right:
|
||||
m_TextPos.x = m_CachedActualSize.right - m_GeneratedTexts[0]->m_Size.cx;
|
||||
m_TextPos.x = m_CachedActualSize.right - m_GeneratedTexts[0]->m_Size.cx - bz;
|
||||
break;
|
||||
default:
|
||||
debug_warn("Broken EAlign in CButton::SetupText()");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (valign)
|
||||
{
|
||||
case EVAlign_Top:
|
||||
m_TextPos.y = m_CachedActualSize.top;
|
||||
m_TextPos.y = m_CachedActualSize.top + bz;
|
||||
break;
|
||||
case EVAlign_Center:
|
||||
// Round to integer pixel values, else the fonts look awful
|
||||
m_TextPos.y = floorf(m_CachedActualSize.CenterPoint().y - m_GeneratedTexts[0]->m_Size.cy/2.f);
|
||||
break;
|
||||
case EVAlign_Bottom:
|
||||
m_TextPos.y = m_CachedActualSize.bottom - m_GeneratedTexts[0]->m_Size.cy;
|
||||
m_TextPos.y = m_CachedActualSize.bottom - m_GeneratedTexts[0]->m_Size.cy - bz;
|
||||
break;
|
||||
default:
|
||||
debug_warn("Broken EVAlign in CButton::SetupText()");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ gee@pyro.nu
|
||||
#include "CText.h"
|
||||
#include "CCheckBox.h"
|
||||
#include "CRadioButton.h"
|
||||
#include "CInput.h"
|
||||
#include "CProgressBar.h"
|
||||
#include "MiniMap.h"
|
||||
|
||||
@ -49,9 +50,9 @@ JSClass GUIClass = {
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
||||
};
|
||||
|
||||
|
||||
// Globals used.
|
||||
extern int g_xres, g_yres;
|
||||
|
||||
extern bool keys[SDLK_LAST];
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// called from main loop when (input) events are received.
|
||||
@ -65,6 +66,8 @@ int gui_handler(const SDL_Event* ev)
|
||||
|
||||
int CGUI::HandleEvent(const SDL_Event* ev)
|
||||
{
|
||||
int ret = EV_PASS;
|
||||
|
||||
// MT: If something's gone wrong, check this block... (added for hotkey support)
|
||||
|
||||
if( ev->type == SDL_GUIHOTKEYPRESS )
|
||||
@ -102,6 +105,7 @@ int CGUI::HandleEvent(const SDL_Event* ev)
|
||||
// Only one object can be hovered
|
||||
IGUIObject *pNearest = NULL;
|
||||
|
||||
// TODO Gee: (2004-09-08) Big TODO, don't do the below if the SDL_Event is something like a keypress!
|
||||
try
|
||||
{
|
||||
// TODO Gee: Optimizations needed!
|
||||
@ -130,8 +134,20 @@ int CGUI::HandleEvent(const SDL_Event* ev)
|
||||
case SDL_BUTTON_LEFT:
|
||||
if (pNearest)
|
||||
{
|
||||
if (pNearest != m_FocusedObject)
|
||||
{
|
||||
// Update focused object
|
||||
if (m_FocusedObject)
|
||||
m_FocusedObject->HandleMessage(SGUIMessage(GUIM_LOST_FOCUS));
|
||||
m_FocusedObject = pNearest;
|
||||
m_FocusedObject->HandleMessage(SGUIMessage(GUIM_GOT_FOCUS));
|
||||
}
|
||||
|
||||
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_PRESS_LEFT));
|
||||
pNearest->ScriptEvent("mouseleftpress");
|
||||
|
||||
// Block event, so things on the map (behind the GUI) won't be pressed
|
||||
LOG(ERROR, LOG_CATEGORY, "Left click blocked");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -155,6 +171,7 @@ int CGUI::HandleEvent(const SDL_Event* ev)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = EV_HANDLED;
|
||||
}
|
||||
else
|
||||
if (ev->type == SDL_MOUSEBUTTONUP)
|
||||
@ -165,6 +182,8 @@ int CGUI::HandleEvent(const SDL_Event* ev)
|
||||
{
|
||||
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_RELEASE_LEFT));
|
||||
pNearest->ScriptEvent("mouseleftrelease");
|
||||
|
||||
ret = EV_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,7 +222,19 @@ int CGUI::HandleEvent(const SDL_Event* ev)
|
||||
m_MouseButtons &= ~(1 << ev->button.button);
|
||||
}
|
||||
|
||||
return EV_PASS;
|
||||
// Handle keys for input boxes
|
||||
if (GetFocusedObject() && ev->type == SDL_KEYDOWN)
|
||||
{
|
||||
if( (ev->key.keysym.sym != SDLK_ESCAPE ) &&
|
||||
!keys[SDLK_LCTRL] && !keys[SDLK_RCTRL] &&
|
||||
!keys[SDLK_LALT] && !keys[SDLK_RALT])
|
||||
{
|
||||
ret = GetFocusedObject()->ManuallyHandleEvent(ev);
|
||||
}
|
||||
// else will return EV_PASS because we never used the button.
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CGUI::TickObjects()
|
||||
@ -216,7 +247,7 @@ void CGUI::TickObjects()
|
||||
//-------------------------------------------------------------------
|
||||
// Constructor / Destructor
|
||||
//-------------------------------------------------------------------
|
||||
CGUI::CGUI() : m_InternalNameNumber(0), m_MouseButtons(0)
|
||||
CGUI::CGUI() : m_InternalNameNumber(0), m_MouseButtons(0), m_FocusedObject(NULL)
|
||||
{
|
||||
m_BaseObject = new CGUIDummyObject;
|
||||
m_BaseObject->SetGUI(this);
|
||||
@ -267,6 +298,7 @@ void CGUI::Initialize()
|
||||
AddObjectType("radiobutton", &CRadioButton::ConstructObject);
|
||||
AddObjectType("progressbar", &CProgressBar::ConstructObject);
|
||||
AddObjectType("minimap", &CMiniMap::ConstructObject);
|
||||
AddObjectType("input", &CInput::ConstructObject);
|
||||
}
|
||||
|
||||
void CGUI::Process()
|
||||
@ -469,8 +501,10 @@ void CGUI::DrawSprite(const CStr& SpriteName,
|
||||
}
|
||||
else
|
||||
{
|
||||
//glDisable(GL_TEXTURE_2D);
|
||||
|
||||
// TODO Gee: (2004-09-04) Shouldn't untextured sprites be able to be transparent too?
|
||||
glColor3f(cit->m_BackColor.r, cit->m_BackColor.g, cit->m_BackColor.b);
|
||||
glColor4f(cit->m_BackColor.r, cit->m_BackColor.g, cit->m_BackColor.b, cit->m_BackColor.a);
|
||||
|
||||
CRect real = cit->m_Size.GetClientArea(Rect);
|
||||
|
||||
@ -940,7 +974,8 @@ void CGUI::DrawText(const SGUIText &Text, const CColor &DefaultColor,
|
||||
|
||||
}
|
||||
|
||||
delete font;
|
||||
if (font)
|
||||
delete font;
|
||||
|
||||
for (list<SGUIText::SSpriteCall>::const_iterator it=Text.m_SpriteCalls.begin();
|
||||
it!=Text.m_SpriteCalls.end();
|
||||
@ -999,6 +1034,7 @@ void CGUI::LoadXMLFile(const string &Filename)
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
if (root_name == "objects")
|
||||
{
|
||||
Xeromyces_ReadRootObjects(node, &XeroFile);
|
||||
|
@ -274,6 +274,11 @@ private:
|
||||
*/
|
||||
IGUIObject *ConstructObject(const CStr& str);
|
||||
|
||||
/**
|
||||
* Get Focused Object.
|
||||
*/
|
||||
IGUIObject *GetFocusedObject() { return m_FocusedObject; }
|
||||
|
||||
//--------------------------------------------------------
|
||||
/** @name XML Reading Xeromyces specific subroutines
|
||||
*
|
||||
@ -512,6 +517,13 @@ private:
|
||||
*/
|
||||
IGUIObject* m_BaseObject;
|
||||
|
||||
/**
|
||||
* Focused object!
|
||||
* Say an input box that is selected. That one is focused.
|
||||
* There can only be one focused object.
|
||||
*/
|
||||
IGUIObject* m_FocusedObject;
|
||||
|
||||
/**
|
||||
* Just pointers for fast name access, each object
|
||||
* is really constructed within its parent for easy
|
||||
|
@ -119,6 +119,9 @@ void CText::HandleMessage(const SGUIMessage &Message)
|
||||
GUI<CStr>::GetSetting(this, Message.value, scrollbar_style);
|
||||
|
||||
GetScrollBar(0).SetScrollBarStyle( scrollbar_style );
|
||||
|
||||
// Update text
|
||||
SetupText();
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -57,8 +57,8 @@ public: \
|
||||
*/
|
||||
enum EGUIMessageType
|
||||
{
|
||||
GUIM_PREPROCESS, // questionable
|
||||
GUIM_POSTPROCESS, // questionable
|
||||
GUIM_PREPROCESS, // TODO questionable
|
||||
GUIM_POSTPROCESS, // TODO questionable
|
||||
GUIM_MOUSE_OVER,
|
||||
GUIM_MOUSE_ENTER,
|
||||
GUIM_MOUSE_LEAVE,
|
||||
@ -73,7 +73,9 @@ enum EGUIMessageType
|
||||
GUIM_SETTINGS_UPDATED, // SGUIMessage.m_Value = name of setting
|
||||
GUIM_PRESSED,
|
||||
GUIM_MOUSE_MOTION,
|
||||
GUIM_LOAD // Called when an object is added to the GUI.
|
||||
GUIM_LOAD, // Called when an object is added to the GUI.
|
||||
GUIM_GOT_FOCUS,
|
||||
GUIM_LOST_FOCUS
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -201,6 +201,16 @@ bool __ParseString<CGUIString>(const CStr& Value, CGUIString &Output)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool __ParseString<CStrW>(const CStr& Value, CStrW &Output)
|
||||
{
|
||||
// Translate the Value and retrieve the locilised string in
|
||||
// Unicode.
|
||||
|
||||
Output = translate((CStrW)Value);
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Help Classes/Structs for the GUI implementation
|
||||
//--------------------------------------------------------
|
||||
@ -387,6 +397,7 @@ TYPE(int)
|
||||
TYPE(float)
|
||||
TYPE(CClientArea)
|
||||
TYPE(CStr)
|
||||
TYPE(CStrW)
|
||||
TYPE(CColor)
|
||||
TYPE(CGUIString)
|
||||
TYPE(EAlign)
|
||||
|
@ -66,6 +66,9 @@ bool __ParseString<EVAlign>(const CStr& Value, EVAlign &Output);
|
||||
template <>
|
||||
bool __ParseString<CGUIString>(const CStr& Value, CGUIString &Output);
|
||||
|
||||
template <>
|
||||
bool __ParseString<CStrW>(const CStr& Value, CStrW &Output);
|
||||
|
||||
|
||||
// Icon, you create them in the XML file with root element <setup>
|
||||
// you use them in text owned by different objects... Such as CText.
|
||||
@ -133,7 +136,7 @@ class IGUIObject;
|
||||
* Base class to only the class GUI. This superclass is
|
||||
* kind of a templateless extention of the class GUI.
|
||||
* Used for other functions to friend with, because it
|
||||
* it can't friend with GUI since it's templated (at least
|
||||
* can't friend with GUI since it's templated (at least
|
||||
* not on all compilers we're using).
|
||||
*/
|
||||
class CInternalCGUIAccessorBase
|
||||
|
@ -53,12 +53,6 @@ void IGUIButtonBehavior::HandleMessage(const SGUIMessage &Message)
|
||||
}
|
||||
} break;
|
||||
|
||||
case GUIM_SETTINGS_UPDATED:
|
||||
// If it's hidden, then it can't be pressed
|
||||
//if (GetBaseSettings().m_Hidden)
|
||||
// m_Pressed = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ IGUIObject::~IGUIObject()
|
||||
TYPE(CClientArea);
|
||||
TYPE(CGUIString);
|
||||
TYPE(CStr);
|
||||
TYPE(CStrW);
|
||||
TYPE(EAlign);
|
||||
TYPE(EVAlign);
|
||||
default:
|
||||
@ -168,6 +169,7 @@ void IGUIObject::AddSetting(const EGUISettingType &Type, const CStr& Name)
|
||||
CASE_TYPE(float)
|
||||
CASE_TYPE(CClientArea)
|
||||
CASE_TYPE(CStr)
|
||||
CASE_TYPE(CStrW)
|
||||
CASE_TYPE(CColor)
|
||||
CASE_TYPE(CGUIString)
|
||||
CASE_TYPE(EAlign)
|
||||
@ -232,7 +234,7 @@ bool IGUIObject::SettingExists(const CStr& Setting) const
|
||||
return (m_Settings.count(Setting) >= 1);
|
||||
}
|
||||
|
||||
#define ADD_TYPE(type, type_name) \
|
||||
#define ADD_TYPE(type) \
|
||||
else \
|
||||
if (set.m_Type == GUIST_##type) \
|
||||
{ \
|
||||
@ -257,14 +259,15 @@ void IGUIObject::SetSetting(const CStr& Setting, const CStr& Value)
|
||||
{
|
||||
GUI<CStr>::SetSetting(this, Setting, Value);
|
||||
}
|
||||
ADD_TYPE(bool, "bool")
|
||||
ADD_TYPE(float, "float")
|
||||
ADD_TYPE(int, "int")
|
||||
ADD_TYPE(CColor, "color")
|
||||
ADD_TYPE(CClientArea, "client area")
|
||||
ADD_TYPE(CGUIString, "text")
|
||||
ADD_TYPE(EAlign, "align")
|
||||
ADD_TYPE(EVAlign, "valign")
|
||||
ADD_TYPE(CStrW)
|
||||
ADD_TYPE(bool)
|
||||
ADD_TYPE(float)
|
||||
ADD_TYPE(int)
|
||||
ADD_TYPE(CColor)
|
||||
ADD_TYPE(CClientArea)
|
||||
ADD_TYPE(CGUIString)
|
||||
ADD_TYPE(EAlign)
|
||||
ADD_TYPE(EVAlign)
|
||||
else
|
||||
{
|
||||
throw PS_FAIL;
|
||||
@ -365,8 +368,9 @@ void IGUIObject::LoadStyle(const SGUIStyle &Style)
|
||||
catch (PS_RESULT e)
|
||||
{
|
||||
UNUSED(e);
|
||||
// debug_warn("IGUIObject::LoadStyle failed"); // (this happens)
|
||||
// TODO Gee: was ist das?
|
||||
// The beauty with styles is that it can contain more settings
|
||||
// than exists for the objects using it. So if the SetSetting
|
||||
// fails, don't care.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -462,7 +466,7 @@ void IGUIObject::ScriptEvent(const CStr& Action)
|
||||
mouseParams[1] = INT_TO_JSVAL(m_pGUI->m_MousePos.y);
|
||||
mouseParams[2] = INT_TO_JSVAL(m_pGUI->m_MouseButtons);
|
||||
JSObject* mouseObj = JS_ConstructObjectWithArguments(g_ScriptingHost.getContext(), &JSI_GUIMouse::JSI_class, NULL, m_pGUI->m_ScriptObject, 3, mouseParams);
|
||||
assert(mouseObj); // need better error handling
|
||||
assert(mouseObj); // TODO need better error handling
|
||||
|
||||
// Don't garbage collect the mouse
|
||||
JS_AddRoot(g_ScriptingHost.getContext(), &mouseObj);
|
||||
@ -494,4 +498,14 @@ CStr IGUIObject::GetPresentableName() const
|
||||
return CStr("[unnamed object]");
|
||||
else
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
void IGUIObject::SetFocus()
|
||||
{
|
||||
GetGUI()->m_FocusedObject = this;
|
||||
}
|
||||
|
||||
bool IGUIObject::IsFocused() const
|
||||
{
|
||||
return GetGUI()->m_FocusedObject == this;
|
||||
}
|
@ -34,6 +34,7 @@ gee@pyro.nu
|
||||
#include "GUI.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "input.h" // just for EV_PASS
|
||||
|
||||
#include "gui/scripting/JSInterface_IGUIObject.h"
|
||||
|
||||
@ -76,6 +77,7 @@ enum EGUISettingType
|
||||
GUIST_CClientArea,
|
||||
GUIST_CGUIString,
|
||||
GUIST_CStr,
|
||||
GUIST_CStrW,
|
||||
GUIST_EAlign,
|
||||
GUIST_EVAlign
|
||||
};
|
||||
@ -325,6 +327,18 @@ protected:
|
||||
*/
|
||||
virtual void Draw()=0;
|
||||
|
||||
/**
|
||||
* Some objects need to handle the SDL_Event manually.
|
||||
* For instance the input box.
|
||||
*
|
||||
* Only the object with focus will have this function called.
|
||||
*
|
||||
* Returns either EV_PASS or EV_HANDLED. If EV_HANDLED, then
|
||||
* the key won't be passed on and processed by other handlers.
|
||||
* This is used for keys that the GUI uses.
|
||||
*/
|
||||
virtual int ManuallyHandleEvent(const SDL_Event* ev) { return EV_PASS; }
|
||||
|
||||
/**
|
||||
* Loads a style.
|
||||
*
|
||||
@ -362,6 +376,16 @@ protected:
|
||||
m_MouseHovering = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take focus!
|
||||
*/
|
||||
void SetFocus();
|
||||
|
||||
/**
|
||||
* Check if object is focused.
|
||||
*/
|
||||
bool IsFocused() const;
|
||||
|
||||
/**
|
||||
* <b>NOTE!</b> This will not just return m_pParent, when that is
|
||||
* need use it! There is one exception to it, when the parent is
|
||||
@ -442,24 +466,19 @@ private:
|
||||
*/
|
||||
void UpdateMouseOver(IGUIObject * const &pMouseOver);
|
||||
|
||||
//@}
|
||||
|
||||
// Variables
|
||||
|
||||
protected:
|
||||
/// Name of object
|
||||
// Name of object
|
||||
CStr m_Name;
|
||||
|
||||
/// Constructed on the heap, will be destroyed along with the the object
|
||||
// Constructed on the heap, will be destroyed along with the the object
|
||||
// TODO Gee: really the above?
|
||||
vector_pObjects m_Children;
|
||||
|
||||
/// Pointer to parent
|
||||
// Pointer to parent
|
||||
IGUIObject *m_pParent;
|
||||
|
||||
/// Base settings
|
||||
//SGUIBaseSettings m_BaseSettings;
|
||||
|
||||
/**
|
||||
* This is an array of true or false, each element is associated with
|
||||
* a string representing a setting. Number of elements is equal to
|
||||
@ -474,19 +493,9 @@ protected:
|
||||
|
||||
// More variables
|
||||
|
||||
/// Is mouse hovering the object? used with the function MouseOver()
|
||||
// Is mouse hovering the object? used with the function MouseOver()
|
||||
bool m_MouseHovering;
|
||||
|
||||
/**
|
||||
* Tells us where a variable by a string name is
|
||||
* located hardcoded, in order to acquire a pointer
|
||||
* for that variable... Say "frozen" gives
|
||||
* the offset from IGUIObject to m_Frozen.
|
||||
* <b>note!</b> @uNOT from SGUIBaseSettings to
|
||||
* m_Frozen!
|
||||
*/
|
||||
//static map_Settings ms_SettingsInfo;
|
||||
|
||||
/**
|
||||
* Settings pool, all an object's settings are located here
|
||||
* If a derived object has got more settings that the base
|
||||
@ -499,7 +508,7 @@ protected:
|
||||
std::map<CStr, SGUISetting> m_Settings;
|
||||
|
||||
private:
|
||||
/// An object can't function stand alone
|
||||
// An object can't function stand alone
|
||||
CGUI *m_pGUI;
|
||||
};
|
||||
|
||||
@ -517,6 +526,8 @@ class CGUIDummyObject : public IGUIObject
|
||||
public:
|
||||
virtual void HandleMessage(const SGUIMessage& UNUSEDPARAM(Message)) {}
|
||||
virtual void Draw() {}
|
||||
// Empty can never be hovered. It is only a category.
|
||||
virtual bool MouseOver() { return false; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -40,6 +40,7 @@ void IGUITextOwner::HandleMessage(const SGUIMessage &Message)
|
||||
// it is assumed that the text of the object will be dependent on
|
||||
// these. Although that is not certain, but one will have to manually
|
||||
// change it and disregard this function.
|
||||
// TODO Gee: (2004-09-07) Make sure this is all options that can affect the text.
|
||||
if (Message.value == CStr("size") || Message.value == CStr("z") ||
|
||||
Message.value == CStr("absolute") || Message.value == CStr("caption") ||
|
||||
Message.value == CStr("font") || Message.value == CStr("textcolor") ||
|
||||
|
Loading…
Reference in New Issue
Block a user