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:
Gee 2004-10-14 10:09:26 +00:00
parent 1d4ebcca24
commit f4b410ff82
11 changed files with 144 additions and 54 deletions

View File

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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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
};
/**

View File

@ -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)

View File

@ -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

View File

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

View File

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

View File

@ -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

View File

@ -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") ||