00001
00002
00003
00004
00005
00006
00007
00009
00010 #include "utils.h"
00011 #include "gui.h"
00012 #include "video.h"
00013
00014 using namespace std;
00015 using namespace hoa_utils;
00016
00017 template<> hoa_video::private_video::GUISupervisor* Singleton<hoa_video::private_video::GUISupervisor>::_singleton_reference = NULL;
00018
00019 namespace hoa_video {
00020
00021 namespace private_video {
00022
00023 GUISupervisor* GUIManager = NULL;
00024
00025
00026
00027
00028
00029 GUIElement::GUIElement() :
00030 _xalign(VIDEO_X_LEFT),
00031 _yalign(VIDEO_Y_TOP),
00032 _x_position(0.0f),
00033 _y_position(0.0f),
00034 _initialized(false)
00035 {}
00036
00037
00038
00039 void GUIElement::SetAlignment(int32 xalign, int32 yalign) {
00040 if (_xalign != VIDEO_X_LEFT && _xalign != VIDEO_X_CENTER && _xalign != VIDEO_X_RIGHT) {
00041 if (VIDEO_DEBUG)
00042 cerr << "VIDEO ERROR: Invalid xalign value (" << xalign << ") passed to GUIElement::SetAlignment()" << endl;
00043 return;
00044 }
00045
00046 if (_yalign != VIDEO_Y_TOP && _yalign != VIDEO_Y_CENTER && _yalign != VIDEO_Y_BOTTOM) {
00047 if (VIDEO_DEBUG)
00048 cerr << "VIDEO ERROR: Invalid yalign value (" << yalign << ") passed to GUIElement::SetAlignment()" << endl;
00049 return;
00050 }
00051
00052 _xalign = xalign;
00053 _yalign = yalign;
00054 }
00055
00056
00057
00058 void GUIElement::CalculateAlignedRect(float &left, float &right, float &bottom, float &top) {
00059 float width = right - left;
00060 float height = top - bottom;
00061
00062 if (width < 0.0f)
00063 width = -width;
00064
00065 if (height < 0.0f)
00066 height = -height;
00067
00068 if (VideoManager->_coord_sys.GetVerticalDirection() < 0.0f)
00069 top = -top;
00070
00071 if (VideoManager->_coord_sys.GetHorizontalDirection() < 0.0f)
00072 right = -right;
00073
00074 float x_off, y_off;
00075
00076 x_off = _x_position + ((VideoManager->_x_align + 1) * width) * 0.5f * -VideoManager->_coord_sys.GetHorizontalDirection();
00077 y_off = _y_position + ((VideoManager->_y_align + 1) * height) * 0.5f * -VideoManager->_coord_sys.GetVerticalDirection();
00078
00079 left += x_off;
00080 right += x_off;
00081
00082 top += y_off;
00083 bottom += y_off;
00084 }
00085
00086
00087
00088
00089
00090 void GUIControl::CalculateAlignedRect(float &left, float &right, float &bottom, float &top) {
00091 GUIElement::CalculateAlignedRect(left, right, bottom, top);
00092
00093
00094 if (_owner) {
00095
00096 float menu_left, menu_right, menu_bottom, menu_top;
00097 float menu_height, menu_width;
00098
00099 _owner->GetDimensions(menu_width, menu_height);
00100 menu_left = 0.0f;
00101 menu_right = menu_width;
00102 menu_bottom = 0.0f;
00103 menu_top = menu_height;
00104 VideoManager->PushState();
00105
00106 int32 xalign, yalign;
00107 _owner->GetAlignment(xalign, yalign);
00108
00109 VideoManager->SetDrawFlags(xalign, yalign, 0);
00110 _owner->CalculateAlignedRect(menu_left, menu_right, menu_bottom, menu_top);
00111 VideoManager->PopState();
00112
00113
00114 if (menu_left < menu_right) {
00115 left += menu_left;
00116 right += menu_left;
00117 }
00118 else {
00119 left += menu_right;
00120 right += menu_right;
00121 }
00122
00123 if (menu_top < menu_bottom) {
00124 top += menu_top;
00125 bottom += menu_top;
00126 }
00127 else {
00128 top += menu_bottom;
00129 bottom += menu_bottom;
00130 }
00131 }
00132 }
00133
00134
00135
00136
00137
00138 GUISupervisor::GUISupervisor() {
00139 _fps_sum = 0;
00140 _current_sample = 0;
00141 _number_samples = 0;
00142
00143 for (uint32 sample = 0; sample < FPS_SAMPLES; sample++)
00144 _fps_samples[sample] = 0;
00145 }
00146
00147
00148
00149 GUISupervisor::~GUISupervisor() {
00150
00151 if (_menu_windows.empty() == false) {
00152 if (VIDEO_DEBUG)
00153 cerr << "VIDEO WARNING: When GUISupervison destructor was invoked, there were still undestroyed MenuWindows" << endl;
00154 std::map<uint32, MenuWindow*> window_copies = _menu_windows;
00155 for (std::map<uint32, MenuWindow*>::iterator i = window_copies.begin(); i != window_copies.end(); i++) {
00156 i->second->Destroy();
00157 }
00158 window_copies.clear();
00159 }
00160
00161
00162 for (map<string, MenuSkin>::iterator i = _menu_skins.begin(); i != _menu_skins.end(); i++) {
00163
00164 for (uint32 x = 0; x < 3; x++) {
00165 for (uint32 y = 0; y < 3; y++) {
00166 VideoManager->DeleteImage(i->second.borders[x][y]);
00167 }
00168 }
00169
00170 for (uint32 x = 0; x < 5; x++) {
00171 VideoManager->DeleteImage(i->second.connectors[x]);
00172 }
00173
00174
00175 if (i->second.background.GetWidth() != 0) {
00176 VideoManager->DeleteImage(i->second.background);
00177 }
00178 }
00179
00180 _menu_skins.clear();
00181 }
00182
00183
00184 bool GUISupervisor::SingletonInitialize() {
00185 return true;
00186 }
00187
00188
00189
00190 bool GUISupervisor::LoadMenuSkin(string skin_name, string border_image, string background_image,
00191 Color top_left, Color top_right, Color bottom_left, Color bottom_right, bool make_default)
00192 {
00193
00194 if (_menu_skins.find(skin_name) != _menu_skins.end()) {
00195 cerr << "VIDEO ERROR: In GUI::LoadMenuSkin(), the skin name " << skin_name << " is already used by another skin" << endl;
00196 return false;
00197 }
00198
00199 _menu_skins.insert(make_pair(skin_name, MenuSkin()));
00200 MenuSkin& new_skin = _menu_skins[skin_name];
00201
00202
00203 std::vector<StillImage> skin_borders;
00204 if (VideoManager->LoadMultiImageFromNumberElements(skin_borders, border_image, 3, 6) == false) {
00205 _menu_skins.erase(skin_name);
00206 return false;
00207 }
00208
00209
00210 new_skin.borders[0][0] = skin_borders[0];
00211 new_skin.borders[0][1] = skin_borders[1];
00212 new_skin.borders[0][2] = skin_borders[2];
00213 new_skin.borders[1][0] = skin_borders[6];
00214 new_skin.borders[1][2] = skin_borders[8];
00215 new_skin.borders[2][0] = skin_borders[12];
00216 new_skin.borders[2][1] = skin_borders[13];
00217 new_skin.borders[2][2] = skin_borders[14];
00218
00219 new_skin.connectors[0] = skin_borders[4];
00220 new_skin.connectors[1] = skin_borders[16];
00221 new_skin.connectors[2] = skin_borders[9];
00222 new_skin.connectors[3] = skin_borders[11];
00223 new_skin.connectors[4] = skin_borders[10];
00224
00225
00226 new_skin.borders[1][1].SetVertexColors(top_left, top_right, bottom_left, bottom_right);
00227
00228 VideoManager->DeleteImage(skin_borders[3]);
00229 VideoManager->DeleteImage(skin_borders[5]);
00230 VideoManager->DeleteImage(skin_borders[7]);
00231 VideoManager->DeleteImage(skin_borders[15]);
00232 VideoManager->DeleteImage(skin_borders[17]);
00233
00234
00235 if (background_image != "") {
00236 new_skin.background.SetFilename(background_image);
00237 if (VideoManager->LoadImage(new_skin.background) == false) {
00238 cerr << "VIDEO ERROR: In GUI::LoadMenuSkin(), the background image file could not be loaded" << endl;
00239 _menu_skins.erase(skin_name);
00240 return false;
00241 }
00242 }
00243
00244
00245 if (make_default == true || _menu_skins.size() == 1) {
00246 _default_skin = &new_skin;
00247 }
00248
00249 return true;
00250 }
00251
00252
00253
00254 void GUISupervisor::SetDefaultMenuSkin(std::string& skin_name) {
00255 if (_menu_skins.find(skin_name) == _menu_skins.end()) {
00256 if (VIDEO_DEBUG)
00257 cerr << "VIDEO WARNING: In GUI::SetDefaultMenuSkin(), the skin name " << skin_name << " was not registered" << endl;
00258 return;
00259 }
00260
00261 _default_skin = &_menu_skins[skin_name];
00262 }
00263
00264
00265
00266 void GUISupervisor::DeleteMenuSkin(std::string& skin_name) {
00267 if (_menu_skins.find(skin_name) == _menu_skins.end()) {
00268 if (VIDEO_DEBUG)
00269 cerr << "VIDEO WARNING: In GUI::DeleteMenuSkin(), the skin name " << skin_name << " was not registered" << endl;
00270 return;
00271 }
00272
00273 MenuSkin* dead_skin = &_menu_skins[skin_name];
00274
00275 map<uint32, MenuWindow*>::iterator i = _menu_windows.begin();
00276 while (i != _menu_windows.end()) {
00277 if (dead_skin == i->second->_skin) {
00278 if (VIDEO_DEBUG)
00279 cerr << "VIDEO ERROR: In GUI::DeleteMenuSkin(), the MenuSkin \"" << skin_name <<
00280 "\" was not deleted because a MenuWindow object was found to be using it" << endl;
00281 return;
00282 }
00283 ++i;
00284 }
00285
00286 _menu_skins.erase(skin_name);
00287 }
00288
00289
00290
00291 void GUISupervisor::AddMenuWindow(MenuWindow* new_window) {
00292 if (_menu_windows.find(new_window->_id) != _menu_windows.end()) {
00293 if (VIDEO_DEBUG)
00294 cerr << "VIDEO WARNING: GUISupervisor::AddMenuWindow() failed because there already existed a window with the same ID" << endl;
00295 return;
00296 }
00297 _menu_windows.insert(std::make_pair(new_window->_id, new_window));
00298 }
00299
00300
00301
00302 void GUISupervisor::RemoveMenuWindow(MenuWindow* old_window) {
00303 map<uint32, MenuWindow*>::iterator i = _menu_windows.find(old_window->_id);
00304
00305 if (i != _menu_windows.end()) {
00306 _menu_windows.erase(i);
00307 }
00308 else {
00309 if (VIDEO_DEBUG)
00310 cerr << "VIDEO WARNING: GUISupervisor::RemoveMenuWindow() did not find a corresponding entry in the menu windows map" << endl;
00311 }
00312 }
00313
00314
00315
00316 void GUISupervisor::DrawFPS(uint32 frame_time) {
00317 VideoManager->SetTextColor(Color::white);
00318 VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, VIDEO_X_NOFLIP, VIDEO_Y_NOFLIP, VIDEO_BLEND, 0);
00319
00320
00321 uint32 current_fps = 1000;
00322 if (frame_time) {
00323 current_fps /= frame_time;
00324 }
00325
00326
00327 uint32 number_insertions;
00328
00329 if (_number_samples == 0) {
00330
00331 _number_samples = FPS_SAMPLES;
00332 number_insertions = FPS_SAMPLES;
00333 }
00334 else if (current_fps >= 500) {
00335
00336 number_insertions = 1;
00337 }
00338 else {
00339
00340
00341 float avg_frame_time = 1000.0f * FPS_SAMPLES / _fps_sum;
00342 int32 time_difference = static_cast<int32>(avg_frame_time) - static_cast<int32>(frame_time);
00343
00344 if (time_difference < 0)
00345 time_difference = -time_difference;
00346
00347 if (time_difference <= static_cast<int32>(MAX_FTIME_DIFF))
00348 number_insertions = 1;
00349 else
00350 number_insertions = FPS_CATCHUP;
00351 }
00352
00353
00354 for (uint32 j = 0; j < number_insertions; j++) {
00355 _fps_sum -= _fps_samples[_current_sample];
00356 _fps_sum += current_fps;
00357 _fps_samples[_current_sample] = current_fps;
00358 _current_sample = (_current_sample + 1) % FPS_SAMPLES;
00359 }
00360
00361 uint32 avg_fps = _fps_sum / FPS_SAMPLES;
00362
00363
00364 char fps_text[16];
00365 sprintf(fps_text, "FPS: %d", avg_fps);
00366
00367 if (!VideoManager->SetFont("debug_font")) {
00368 if (VIDEO_DEBUG)
00369 cerr << "VIDEO WARNING: In GUISupervisor::DrawFPS(), the font \"debug_font\" could not be set and the FPS was not drawn" << endl;
00370 return;
00371 }
00372
00373 VideoManager->Move(930.0f, 720.0f);
00374 VideoManager->DrawText(fps_text);
00375 }
00376
00377 }
00378
00379 }