1
1
forked from 0ad/0ad

Updates, mostly about centering text.

This was SVN commit r1099.
This commit is contained in:
Gee 2004-09-02 03:02:32 +00:00
parent 72e730be3a
commit f2a615f0a3
16 changed files with 187 additions and 79 deletions

View File

@ -23,6 +23,8 @@ CButton::CButton()
AddSetting(GUIST_CStr, "sprite-over");
AddSetting(GUIST_CStr, "sprite-pressed");
AddSetting(GUIST_CStr, "sprite-disabled");
AddSetting(GUIST_EAlign, "text-align");
AddSetting(GUIST_EVAlign, "text-valign");
AddSetting(GUIST_CColor, "textcolor");
AddSetting(GUIST_CColor, "textcolor-over");
AddSetting(GUIST_CColor, "textcolor-pressed");
@ -55,8 +57,45 @@ void CButton::SetupText()
*m_GeneratedTexts[0] = GetGUI()->GenerateText(caption, font, m_CachedActualSize.GetWidth(), 0, this);
// Set position of text
//m_TextPos = m_CachedActualSize.CenterPoint() - m_GeneratedTexts[0]->m_Size/2;
// Check which alignment to use!
EAlign align;
EVAlign valign;
GUI<EAlign>::GetSetting(this, "text-align", align);
GUI<EVAlign>::GetSetting(this, "text-valign", valign);
m_TextPos = m_CachedActualSize.TopLeft();
switch (align)
{
case EAlign_Left:
m_TextPos.x = m_CachedActualSize.left;
break;
case EAlign_Center:
m_TextPos.x = m_CachedActualSize.CenterPoint().x - m_GeneratedTexts[0]->m_Size.cx/2;
break;
case EAlign_Right:
m_TextPos.x = m_CachedActualSize.right - m_GeneratedTexts[0]->m_Size.cx;
break;
default:
break;
}
switch (valign)
{
case EVAlign_Top:
m_TextPos.y = m_CachedActualSize.top;
break;
case EVAlign_Center:
m_TextPos.y = m_CachedActualSize.CenterPoint().y - m_GeneratedTexts[0]->m_Size.cy/2;
break;
case EVAlign_Bottom:
m_TextPos.y = m_CachedActualSize.bottom - m_GeneratedTexts[0]->m_Size.cy;
break;
default:
break;
}
}
void CButton::HandleMessage(const SGUIMessage &Message)

View File

@ -39,7 +39,6 @@ gee@pyro.nu
* Button
*
* @see IGUIObject
* @see IGUISettingsObject
* @see IGUIButtonBehavior
*/
class CButton : public IGUIButtonBehavior, public IGUITextOwner

View File

@ -31,7 +31,7 @@ CCheckBox::CCheckBox()
CColor m_TextColorDisabled;
CColor m_TextColorOver;
CColor m_TextColorPressed;
EValign m_TextValign;
EVAlign m_TextValign;
CStr m_ToolTip;
CStr m_ToolTipStyle;
*/

View File

@ -10,6 +10,7 @@ gee@pyro.nu
// Types - when including them into the engine.
#include "CButton.h"
#include "CImage.h"
#include "CText.h"
#include "CCheckBox.h"
#include "CRadioButton.h"
@ -81,11 +82,6 @@ int CGUI::HandleEvent(const SDL_Event* ev)
SGUIMessage(GUIM_MOUSE_MOTION));
}
// TODO Gee: temp-stuff
// char buf[30];
// sprintf(buf, "type = %d", ev->type);
//TEMPmessage = buf;
// Update m_MouseButtons. (BUTTONUP is handled later.)
if (ev->type == SDL_MOUSEBUTTONDOWN)
{
@ -247,8 +243,7 @@ IGUIObject *CGUI::ConstructObject(const CStr& str)
return (*m_ObjectTypes[str])();
else
{
debug_warn("CGUI::ConstructObject error");
// TODO Gee: Report in log
// Error reporting will be handled with the NULL return.
return NULL;
}
}
@ -260,6 +255,7 @@ void CGUI::Initialize()
// Prometheus though will have all the object types inserted from here.
AddObjectType("empty", &CGUIDummyObject::ConstructObject);
AddObjectType("button", &CButton::ConstructObject);
AddObjectType("image", &CImage::ConstructObject);
AddObjectType("text", &CText::ConstructObject);
AddObjectType("checkbox", &CCheckBox::ConstructObject);
AddObjectType("radiobutton", &CRadioButton::ConstructObject);
@ -422,19 +418,41 @@ void CGUI::DrawSprite(const CStr& SpriteName,
// Get the screen position/size of a single tiling of the texture
CRect TexSize = cit->m_TextureSize.GetClientArea(real);
float TexLeft = (float)(TexSize.left - real.left) / (float)TexSize.GetWidth();
float TexRight = TexLeft + (float)real.GetWidth() / (float)TexSize.GetWidth();
// Actual texture coordinates we'll send to OGL.
CRect TexCoords;
TexCoords.left = (TexSize.left - real.left) / TexSize.GetWidth();
TexCoords.right = TexCoords.left + real.GetWidth() / TexSize.GetWidth();
// 'Bottom' is actually the top in screen-space (I think),
// because the GUI puts (0,0) at the top-left
float TexBottom = (float)(TexSize.bottom - real.bottom) / (float)TexSize.GetHeight();
float TexTop = TexBottom + (float)real.GetHeight() / (float)TexSize.GetHeight();
TexCoords.bottom = (TexSize.bottom - real.bottom) / TexSize.GetHeight();
TexCoords.top = TexCoords.bottom + real.GetHeight() / TexSize.GetHeight();
if (cit->m_TexturePlacementInFile != CRect())
{
// Save the width/height, because we'll change the values one at a time and need
// to be able to use the unchanged width/height
float width = TexCoords.GetWidth(),
height = TexCoords.GetHeight();
// Get texture width/height
int t_w, t_h;
tex_info(cit->m_Texture, &t_w, &t_h, NULL, NULL, NULL);
// notice left done after right, so that left is still unchanged, that is important.
TexCoords.right = TexCoords.left + width * cit->m_TexturePlacementInFile.right/(float)t_w;
TexCoords.left += width * cit->m_TexturePlacementInFile.left/(float)t_w;
TexCoords.bottom = TexCoords.top + height * cit->m_TexturePlacementInFile.bottom/(float)t_h;
TexCoords.top += height * cit->m_TexturePlacementInFile.top/(float)t_h;
}
glBegin(GL_QUADS);
glTexCoord2f(TexRight, TexBottom); glVertex3f((float)real.right, (float)real.bottom, cit->m_DeltaZ);
glTexCoord2f(TexLeft, TexBottom); glVertex3f((float)real.left, (float)real.bottom, cit->m_DeltaZ);
glTexCoord2f(TexLeft, TexTop); glVertex3f((float)real.left, (float)real.top, cit->m_DeltaZ);
glTexCoord2f(TexRight, TexTop); glVertex3f((float)real.right, (float)real.top, cit->m_DeltaZ);
glTexCoord2f(TexCoords.right, TexCoords.bottom); glVertex3f(real.right, real.bottom, cit->m_DeltaZ);
glTexCoord2f(TexCoords.left, TexCoords.bottom); glVertex3f(real.left, real.bottom, cit->m_DeltaZ);
glTexCoord2f(TexCoords.left, TexCoords.top); glVertex3f(real.left, real.top, cit->m_DeltaZ);
glTexCoord2f(TexCoords.right, TexCoords.top); glVertex3f(real.right, real.top, cit->m_DeltaZ);
glEnd();
glDisable(GL_TEXTURE_2D);
@ -607,8 +625,6 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
// Easier to read.
bool WordWrapping = (Width != 0);
size_t TEMP = string.m_Words.size();
// Go through string word by word
for (int i=0; i<(int)string.m_Words.size()-1 && !done; ++i)
{
@ -634,9 +650,6 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
// Loop left/right
for (int j=0; j<2; ++j)
{
// TEMP
int TEMPsize = Feedback.m_Images[j].size();
for (vector<CStr>::const_iterator it = Feedback.m_Images[j].begin();
it != Feedback.m_Images[j].end();
++it)
@ -1496,6 +1509,16 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
else image.m_TextureSize = ca;
}
else
if (attr_name == "real-texture-placement")
{
CRect rect;
if (!GUI<CRect>::ParseString(attr_value, rect))
{
ReportParseError("TODO");
}
else image.m_TexturePlacementInFile = rect;
}
else
if (attr_name == "z-level")
{
int z_level;

View File

@ -81,9 +81,6 @@ public:
CGUI();
~CGUI();
// TODO Gee: (MEGA) Extremely temporary.
std::string TEMPmessage;
/**
* Initializes the GUI, needs to be called before the GUI is used
*/

View File

@ -53,7 +53,7 @@ gee@pyro.nu
*/
struct SGUIImage
{
SGUIImage() : m_Texture(0), m_Border(false), m_DeltaZ(0.f) {}
SGUIImage() : m_Texture(0), m_Border(false), m_DeltaZ(0.f), m_TexturePlacementInFile() {}
~SGUIImage() {
if (m_Texture)
tex_free(m_Texture);
@ -69,6 +69,7 @@ struct SGUIImage
C(Size); C(TextureSize);
C(BackColor); C(BorderColor);
C(Border); C(DeltaZ);
C(TexturePlacementInFile);
#undef C
// 'Load' the texture (but don't do any work because it's cached)
if (m_Texture)
@ -84,6 +85,11 @@ struct SGUIImage
// Texture placement
CClientArea m_TextureSize;
// Because OpenGL wants textures in squares with a power of 2 (64x64, 256x256)
// it's sometimes tediuos to adjust this. So this value simulates which area
// is the real texture
CRect m_TexturePlacementInFile;
// Color
CColor m_BackColor;
CColor m_BorderColor;

View File

@ -100,6 +100,7 @@ void CText::HandleMessage(const SGUIMessage &Message)
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
// Update scroll-bar
// TODO Gee: (2004-09-01) Is this really updated each time it should?
if (scrollbar &&
(Message.value == CStr("size") || Message.value == CStr("z") ||
Message.value == CStr("absolute")))
@ -143,10 +144,6 @@ void CText::HandleMessage(const SGUIMessage &Message)
void CText::Draw()
{
////////// Gee: janwas, this is just temp to see it
glDisable(GL_TEXTURE_2D);
//////////
float bz = GetBufferedZ();
// First call draw on ScrollBarOwner

View File

@ -42,7 +42,6 @@ class IGUIScrollBar;
* Text field that just displays static text.
*
* @see IGUIObject
* @see IGUISettingsObject
*/
class CText : public IGUIScrollBarOwner, public IGUITextOwner
{

View File

@ -11,6 +11,7 @@ gee@pyro.nu
//--------------------------------------------------------
// Error definitions
//--------------------------------------------------------
// TODO Gee: (2004-09-01) Keeper? The PS_NAME_ABIGUITY for instance doesn't let the user know which objects.
DEFINE_ERROR(PS_NAME_TAKEN, "Reference name is taken");
DEFINE_ERROR(PS_OBJECT_FAIL, "Object provided is null");
DEFINE_ERROR(PS_SETTING_FAIL, "Setting does not exist");

View File

@ -128,23 +128,14 @@ enum EGUISettingsStruct
GUISS_EXTENDED
};
// Text alignments
enum EAlign { EAlign_Left, EAlign_Right, EAlign_Center };
enum EVAlign { EVAlign_Top, EVAlign_Bottom, EVAlign_Center };
// Typedefs
typedef std::map<CStr, IGUIObject*> map_pObjects;
typedef std::vector<IGUIObject*> vector_pObjects;
// Smaller structs that don't deserve their own files :)
// Icon, you create them in the XML file with root element <setup>
// you use them in text owned by different objects... Such as CText.
struct SGUIIcon
{
// Texture name of icon
CStr m_TextureName;
// Size
CSize m_Size;
};
//--------------------------------------------------------
// Error declarations
//--------------------------------------------------------

View File

@ -69,7 +69,7 @@ void CGUIString::GenerateTextCall(SFeedback &Feedback,
// it's in the end of one word, and the icon
// should really belong to the beginning of the next one
if (_to == to)
if (_to == to && to >= 1)
{
if (GetRawString()[to-1] == ' ' ||
GetRawString()[to-1] == '-' ||
@ -203,7 +203,7 @@ void CGUIString::GenerateTextCall(SFeedback &Feedback,
Feedback.m_Size.cx += size.cx;
Feedback.m_Size.cy = max(Feedback.m_Size.cy, size.cy);
// These are also needed later
// These are also ne eded later
TextCall.m_Size = size;
if (TextCall.m_String.Length() >= 1)

View File

@ -156,6 +156,40 @@ bool __ParseString<CSize>(const CStr& Value, CSize &Output)
return true;
}
template <>
bool __ParseString<EAlign>(const CStr &Value, EAlign &Output)
{
if (Value == (CStr)"left")
Output = EAlign_Left;
else
if (Value == (CStr)"center")
Output = EAlign_Center;
else
if (Value == (CStr)"right")
Output = EAlign_Right;
else
return false;
return true;
}
template <>
bool __ParseString<EVAlign>(const CStr &Value, EVAlign &Output)
{
if (Value == (CStr)"top")
Output = EVAlign_Top;
else
if (Value == (CStr)"center")
Output = EVAlign_Center;
else
if (Value == (CStr)"bottom")
Output = EVAlign_Bottom;
else
return false;
return true;
}
template <>
bool __ParseString<CGUIString>(const CStr& Value, CGUIString &Output)
{
@ -179,16 +213,16 @@ CClientArea::CClientArea(const CStr& Value)
CRect CClientArea::GetClientArea(const CRect &parent) const
{
// If it's a 0 0 100% 100% we need no calculations
if (percent == CRect(0,0,100,100) && pixel == CRect(0,0,0,0))
if (percent == CRect(0.f,0.f,100.f,100.f) && pixel == CRect(0.f,0.f,0.f,0.f))
return parent;
CRect client;
// This should probably be cached and not calculated all the time for every object.
client.left = parent.left + int(float((parent.right-parent.left)*percent.left)/100.f) + pixel.left;
client.top = parent.top + int(float((parent.bottom-parent.top)*percent.top)/100.f) + pixel.top;
client.right = parent.left + int(float((parent.right-parent.left)*percent.right)/100.f) + pixel.right;
client.bottom = parent.top + int(float((parent.bottom-parent.top)*percent.bottom)/100.f) + pixel.bottom;
client.left = parent.left + (parent.right-parent.left)*percent.left/100.f + pixel.left;
client.top = parent.top + (parent.bottom-parent.top)*percent.top/100.f + pixel.top;
client.right = parent.left + (parent.right-parent.left)*percent.right/100.f + pixel.right;
client.bottom = parent.top + (parent.bottom-parent.top)*percent.bottom/100.f + pixel.bottom;
return client;
}
@ -265,7 +299,9 @@ bool CClientArea::SetClientArea(const CStr& Value)
// 4 arguments = INVALID
// Default to 0
int values[4][2] = {{0,0},{0,0},{0,0},{0,0}};
//int values[4][2] = {{0,0},{0,0},{0,0},{0,0}};
int i_values[4] = {0,0,0,0};
float f_values[4] = {0.f, 0.f, 0.f, 0.f};
for (int v=0; v<4; ++v)
{
@ -274,20 +310,20 @@ bool CClientArea::SetClientArea(const CStr& Value)
string str;
line.GetArgString(arg_start[v], str);
if (!line.GetArgInt(arg_start[v], values[v][1]))
if (!line.GetArgInt(arg_start[v], i_values[v]))
return false;
}
else
if (arg_count[v] == 2)
{
if (!line.GetArgInt(arg_start[v], values[v][0]))
if (!line.GetArgFloat(arg_start[v], f_values[v]))
return false;
}
else
if (arg_count[v] == 3)
{
if (!line.GetArgInt(arg_start[v], values[v][0]) ||
!line.GetArgInt(arg_start[v]+2, values[v][1]))
if (!line.GetArgFloat(arg_start[v], f_values[v]) ||
!line.GetArgInt(arg_start[v]+2, i_values[v]))
return false;
}
@ -295,14 +331,14 @@ bool CClientArea::SetClientArea(const CStr& Value)
}
// Now store the values[][] in the right place
pixel.left = values[0][1];
pixel.top = values[1][1];
pixel.right = values[2][1];
pixel.bottom = values[3][1];
percent.left = values[0][0];
percent.top = values[1][0];
percent.right = values[2][0];
percent.bottom = values[3][0];
pixel.left = i_values[0];
pixel.top = i_values[1];
pixel.right = i_values[2];
pixel.bottom = i_values[3];
percent.left = f_values[0];
percent.top = f_values[1];
percent.right = f_values[2];
percent.bottom = f_values[3];
return true;
}

View File

@ -57,9 +57,28 @@ bool __ParseString<CColor>(const CStr& Value, CColor &Output);
template <>
bool __ParseString<CSize>(const CStr& Value, CSize &Output);
template <>
bool __ParseString<EAlign>(const CStr& Value, EAlign &Output);
template <>
bool __ParseString<EVAlign>(const CStr& Value, EVAlign &Output);
template <>
bool __ParseString<CGUIString>(const CStr& Value, CGUIString &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.
struct SGUIIcon
{
// Texture name of icon
CStr m_TextureName;
// Size
CSize m_Size;
};
/**
* @author Gustav Larsson
*
@ -77,7 +96,7 @@ public:
/// Pixel modifiers
CRect pixel;
/// Percent modifiers (I'll let this be integers, I don't think a greater precision is needed)
/// Percent modifiers
CRect percent;
/**
@ -88,9 +107,8 @@ public:
/**
* The ClientArea can be set from a string looking like:
*
* @code
* "0 0 100% 100%"
* "50%-10 50%-10 50%+10 50%+10" @endcode
* "50%-10 50%-10 50%+10 50%+10"
*
* i.e. First percent modifier, then + or - and the pixel modifier.
* Although you can use just the percent or the pixel modifier. Notice

View File

@ -71,6 +71,8 @@ IGUIObject::~IGUIObject()
TYPE(CClientArea);
TYPE(CGUIString);
TYPE(CStr);
TYPE(EAlign);
TYPE(EVAlign);
default:
assert(!"Invalid setting type");
}
@ -169,11 +171,11 @@ void IGUIObject::AddSetting(const EGUISettingType &Type, const CStr& Name)
CASE_TYPE(CStr)
CASE_TYPE(CColor)
CASE_TYPE(CGUIString)
CASE_TYPE(EAlign)
CASE_TYPE(EVAlign)
default:
debug_warn("IGUIObject::AddSetting failed");
// TODO Gee: Report in log, type is not recognized. This should be an assert, not in log
// because it's strictly hardcoded error
debug_warn("IGUIObject::AddSetting failed, type not recognized!");
break;
}
}
@ -262,6 +264,8 @@ void IGUIObject::SetSetting(const CStr& Setting, const CStr& Value)
ADD_TYPE(CColor, "color")
ADD_TYPE(CClientArea, "client area")
ADD_TYPE(CGUIString, "text")
ADD_TYPE(EAlign, "align")
ADD_TYPE(EVAlign, "valign")
else
{
throw PS_FAIL;
@ -329,7 +333,7 @@ void IGUIObject::UpdateCachedSize()
if (absolute == false && m_pParent)
m_CachedActualSize = ca.GetClientArea(m_pParent->m_CachedActualSize);
else
m_CachedActualSize = ca.GetClientArea(CRect(0, 0, g_xres, g_yres));
m_CachedActualSize = ca.GetClientArea(CRect(0.f, 0.f, (float)g_xres, (float)g_yres));
}

View File

@ -60,11 +60,6 @@ typedef std::map<CStr, SGUISetting> map_Settings;
// Declarations
//--------------------------------------------------------
// Text alignments
enum EAlign { EAlign_Left, EAlign_Right, EAlign_Center };
enum EValign { EValign_Top, EValign_Bottom, EValign_Center };
/**
* Setting Type
* @see SGUISetting
@ -80,7 +75,9 @@ enum EGUISettingType
GUIST_CColor,
GUIST_CClientArea,
GUIST_CGUIString,
GUIST_CStr
GUIST_CStr,
GUIST_EAlign,
GUIST_EVAlign
};
/**

View File

@ -42,7 +42,8 @@ void IGUITextOwner::HandleMessage(const SGUIMessage &Message)
// change it and disregard this function.
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"))
Message.value == CStr("font") || Message.value == CStr("textcolor") ||
Message.value == CStr("buffer-zone"))
{
SetupText();
}