Crystal Hammer
21-08-2014 18:56:28
Ok so, this is our code that does iterate all widgets and resizes them to have the same view size on different screen resolutions.
It first saves original pos and sizes so it can be used (in setToolTips).
In editor .layout windows are for 800x600.
Same is done for fonts, but yeah they will be a bit different at various sizes. Still does the job.
Is a bit buggy, but I hope you can use it and maybe even improve it or merge into MyGUI, would be cool.
In the Gui init code we have:
And those are the methods that take care of all that
Here is the method that creates the fonts (size based on screen height, char range based on other font's char range, found in xml).
It first saves original pos and sizes so it can be used (in setToolTips).
In editor .layout windows are for 800x600.
Same is done for fonts, but yeah they will be a bit different at various sizes. Still does the job.
Is a bit buggy, but I hope you can use it and maybe even improve it or merge into MyGUI, would be cool.
In the Gui init code we have:
// common
using namespace MyGUI;
using namespace Ogre;
using namespace std;
// class members
CGuiCom* gcom;
App* app;
MyGUI::Gui* mGui;
//MyGUI::VectorWidgetPtr
std::vector<Widget*> vwGui; // all widgets to destroy
Widget* mToolTip; EditBox* mToolTipTxt;
// in Gui Init code
// load
app->vwGui = LayoutManager::getInstance().loadLayout("Editor.layout");
gcom->GuiInitTooltip(); // this sets original pos and size strings in widgets
// then in frameStarted
// bWindowResized is true at app start and
// after event virtual void windowResized (int x, int y);
if (bWindowResized)
{ bWindowResized = false;
gcom->SizeGUI();
//.. other custom, lists resizing code
}
}
And those are the methods that take care of all that
void CGuiCom::SizeGUI()
{
// call recursive method for all root widgets
for (VectorWidgetPtr::iterator it = app->vwGui.begin(); it != app->vwGui.end(); ++it)
doSizeGUI((*it)->getEnumerator());
}
void CGuiCom::doSizeGUI(EnumeratorWidgetPtr widgets)
{
while (widgets.next())
{
Widget* wp = widgets.current();
string relativeTo = wp->getUserString("RelativeTo");
if (relativeTo != "")
{
// position & size relative to the widget specified in "RelativeTo" property (or full screen)
IntSize relSize;
if (relativeTo == "Screen")
relSize = IntSize(app->mWindow->getWidth(), app->mWindow->getHeight());
else
{ Widget* window = mGui->findWidget<Widget>(relativeTo);
relSize = window->getSize(); }
// retrieve original size & pos
IntPoint origPos; IntSize origSize;
#define s2i(s) Ogre::StringConverter::parseInt(s)
origPos.left = s2i(wp->getUserString("origPosX"));
origPos.top = s2i(wp->getUserString("origPosY"));
origSize.width = s2i(wp->getUserString("origSizeX"));
origSize.height = s2i(wp->getUserString("origSizeY"));
// calc & apply new size & pos
float sx = relSize.width / 800.f, sy = relSize.height / 600.f;
wp->setPosition(IntPoint( int(origPos.left * sx), int(origPos.top * sy) ));
wp->setSize(IntSize( int(origSize.width * sx), int(origSize.height * sy) ));
}
doSizeGUI(wp->getEnumerator());
}
}
// used only for manually created widgets
void CGuiCom::setOrigPos(Widget* wp, const char* relToWnd)
{
if (!wp) return;
#define toStr(v) Ogre::StringConverter::toString(v)
wp->setUserString("origPosX", toStr(wp->getPosition().left));
wp->setUserString("origPosY", toStr(wp->getPosition().top));
wp->setUserString("origSizeX", toStr(wp->getSize().width));
wp->setUserString("origSizeY", toStr(wp->getSize().height));
wp->setUserString("RelativeTo", relToWnd);
}
/// Tooltips
//----------------------------------------------------------------------------------------------------------------
void CGuiCom::GuiInitTooltip()
{
mToolTip = mGui->findWidget<Widget>("ToolTip");
mToolTip->setVisible(false);
mToolTipTxt = mToolTip->getChildAt(0)->castType<Edit>();
for (VectorWidgetPtr::iterator it = app->vwGui.begin(); it != app->vwGui.end(); ++it)
setToolTips((*it)->getEnumerator());
}
void CGuiCom::setToolTips(EnumeratorWidgetPtr widgets)
{
while (widgets.next())
{
Widget* wp = widgets.current();
wp->setAlign(Align::Default);
IntPoint origPos = wp->getPosition();
IntSize origSize = wp->getSize();
wp->setUserString("origPosX", toStr(origPos.left));
wp->setUserString("origPosY", toStr(origPos.top));
wp->setUserString("origSizeX", toStr(origSize.width));
wp->setUserString("origSizeY", toStr(origSize.height));
// find parent window
Widget* p = wp->getParent();
while (p)
{
if (p->getTypeName() == "Window")
{
if (p->getUserString("NotSized").empty())
wp->setUserString("RelativeTo", p->getName());
break;
}
p = p->getParent();
}
bool tip = wp->isUserString("tip");
if (tip) // if has tooltip string
{
// needed for translation
wp->setUserString("tip", LanguageManager::getInstance().replaceTags(wp->getUserString("tip")));
wp->setNeedToolTip(true);
wp->eventToolTip += newDelegate(this, &CGuiCom::notifyToolTip);
}
setToolTips(wp->getEnumerator());
}
}
void CGuiCom::notifyToolTip(Widget* wp, const ToolTipInfo &info)
{
if (!mToolTip) return;
if (!app->bGuiFocus)
{ mToolTip->setVisible(false);
return;
}
if (info.type == ToolTipInfo::Show)
{
mToolTip->setSize(320, 128); // start size for wrap
mToolTipTxt->setSize(320, 128);
#define TR(s) MyGUI::LanguageManager::getInstance().replaceTags(s)
String s = TR(wp->getUserString("tip"));
mToolTipTxt->setCaption(s);
const IntSize &si = mToolTipTxt->getTextSize();
mToolTip->setSize(si.width +8, si.height +8);
mToolTipTxt->setSize(si.width, si.height);
mToolTip->setVisible(true);
boundedMove(mToolTip, info.point);
}
else if (info.type == ToolTipInfo::Hide)
mToolTip->setVisible(false);
}
// Move a widget to a point while making it stay in the viewport.
void CGuiCom::boundedMove(Widget* moving, const IntPoint& point)
{
const IntPoint offset(20, 20); // mouse cursor
IntPoint p = point + offset;
const IntSize& size = moving->getSize();
int w = app->mWindow->getWidth();
int h = app->mWindow->getHeight();
if (p.left + size.width > w) p.left = w - size.width;
if (p.top + size.height > h) p.top = h - size.height;
moving->setPosition(p);
}
Here is the method that creates the fonts (size based on screen height, char range based on other font's char range, found in xml).
void CGuiCom::CreateFonts()
{
MyGUI::ResourceManager& mgr = MyGUI::ResourceManager::getInstance();
MyGUI::IResource* resource = mgr.findByName("hud.text"); // based on this font - just for code ranges
MyGUI::ResourceTrueTypeFont* bfont = resource != nullptr ? resource->castType<MyGUI::ResourceTrueTypeFont>(false) : 0;
if (!bfont) LogO("Error !! Can't find font: hud.text");
const int cnt = 3;
string names[cnt] = {"font.small","font.normal","font.big"};
float sizes[cnt] = {26.f, 30.f, 34.f}; // par
for (int i=0; i < cnt; ++i)
{
// del old
const string name = names;
if (mgr.isExist(name))
mgr.removeByName(name);
// setup font // par
float size = sizes * (1.f - 1.5f * (GetGuiMargin(2000) - GetGuiMargin(pSet->windowy)));
LogO("-- "+name+" size: "+fToStr(size,2,4));
// create
#if 0 // mygui from svn
string cat = mgr.getCategoryName(); // createObject("Resource", "ResourceTrueTypeFont"));
ResourceTrueTypeFont* font = FactoryManager::getInstance().createObject<ResourceTrueTypeFont>(cat);
font->setResourceName(name);
font->setSource("DejaVuLGCSans.ttf");
font->setSize(size); font->setResolution(50); font->setAntialias(false); //font->setHinting("");
font->setTabWidth(8); font->setDistance(4); font->setOffsetHeight(0);
//font->setSubstituteCode(_data->getPropertyValue<int>("SubstituteCode"));
// char ranges
if (bfont)
{ const std::vector<pair<Char, Char> >& vv = bfont->getCodePointRanges();
for (std::vector<pair<Char, Char> >::const_iterator it = vv.begin(); it != vv.end(); ++it)
if ((*it).first > 10 && (*it).first < 10000)
font->addCodePointRange((*it).first, (*it).second);
}else
font->addCodePointRange(33,255);
font->initialise();
#else
ResourceTrueTypeFont* font = (ResourceTrueTypeFont*)FactoryManager::getInstance().createObject("Resource", "ResourceTrueTypeFont");
// Loading from XML, data members are private in MyGUI 3.2.0
xml::Document doc;
xml::ElementPtr root = doc.createRoot("ResourceTrueTypeFont"), e;
root->addAttribute("name", name);
#define AddE(key, val) e = root->createChild("Property"); e->addAttribute("key", key); e->addAttribute("value", val)
AddE("Source", "DejaVuLGCSans.ttf");
AddE("Size", toStr(size)); AddE("Resolution", "50"); AddE("Antialias", "false");
AddE("TabWidth", "8"); AddE("Distance", "4"); AddE("OffsetHeight", "0");
xml::ElementPtr codes = root->createChild("Codes"), c;
// char ranges
if (bfont)
{ const std::vector<pair<Char, Char> >& vv = bfont->getCodePointRanges();
for (std::vector<pair<Char, Char> >::const_iterator it = vv.begin(); it != vv.end(); ++it)
if ((*it).first > 10 && (*it).first < 10000)
{
c = codes->createChild("Code");
c->addAttribute("range", toStr((*it).first)+" "+toStr((*it).second));
}
}else
{ c = codes->createChild("Code");
c->addAttribute("range", "33 255");
}
//doc.save(string("aaa.txt")); // test
font->deserialization(root, Version(3,2,0));
#endif
// add
mgr.addResource(font);
}
}