Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/gui/src/story_entities/simple_game_menu.cc @ 7984

Last change on this file since 7984 was 7980, checked in by bensch, 19 years ago

orxonox/trunk: Better Signal definition

File size: 18.1 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11### File Specific:
12   main-programmer: Patrick Boenzli
13
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD
17
18
19#include "simple_game_menu.h"
20
21#include "event_handler.h"
22
23#include "state.h"
24#include "class_list.h"
25
26#include "util/loading/load_param.h"
27#include "fast_factory.h"
28#include "util/loading/factory.h"
29
30#include "world_entity.h"
31#include "elements/image_entity.h"
32#include "terrain.h"
33#include "camera.h"
34
35#include "graphics_engine.h"
36#include "object_manager.h"
37#include "sound_engine.h"
38#include "sound_source.h"
39
40#include "cd_engine.h"
41
42#include "glgui.h"
43
44//! This creates a Factory to fabricate a SimpleGameMenu
45CREATE_FACTORY(SimpleGameMenu, CL_SIMPLE_GAME_MENU);
46
47
48
49SimpleGameMenu::SimpleGameMenu(const TiXmlElement* root)
50    : GameWorld()
51{
52  this->setClassID(CL_SIMPLE_GAME_MENU, "SimpleGameMenu");
53  this->setName("SimpleGameMenu uninitialized");
54
55  this->dataTank = new SimpleGameMenuData();
56
57  this->cameraVector = Vector(50.0, 0.0, 0.0);
58  this->menuLayers.push_back(MenuLayer());
59  this->menuLayers.push_back(MenuLayer());
60
61  this->layerIndex = 0;
62  this->menuSelectedIndex = 0;
63  this->selectorSource = NULL;
64
65
66  /// GUI
67  ///(this is as modular as it is possible).
68  OrxGui::GLGuiPushButton* pb = new OrxGui::GLGuiPushButton("PUSH ME");
69  pb->connectSignal(OrxGui::Signal_release, this, createExecutor<SimpleGameMenu>(&SimpleGameMenu::enterGui));
70  pb->show();
71  pb->setAbsCoor2D(50, 50);
72
73  OrxGui::GLGuiHandler::getInstance()->activateCursor();
74  OrxGui::GLGuiHandler::getInstance()->activate();
75  /////
76
77  if (root != NULL)
78    this->loadParams(root);
79
80  State::setMenuID(this->getNextStoryID());
81}
82
83/// HACK only for testing.
84void SimpleGameMenu::enterGui()
85{
86  ///
87  OrxGui::GLGuiButton* dnpb = new OrxGui::GLGuiCheckButton("Push the button");
88  dnpb->show();
89  dnpb->setAbsCoor2D(350, 50);
90  dnpb->connectSignal(OrxGui::Signal_release, this, createExecutor<SimpleGameMenu>(&SimpleGameMenu::execURL));
91
92  OrxGui::GLGuiPushButton* rdnpb = new OrxGui::GLGuiPushButton("Quit ORXONOX!!");
93  rdnpb->show();
94  rdnpb->setAbsCoor2D(200, 180);
95  rdnpb->connectSignal(OrxGui::Signal_release, this, SLOT(SimpleGameMenu, quitMenu));
96
97  OrxGui::GLGuiInputLine* input = new OrxGui::GLGuiInputLine();
98  input->setText("input some text here");
99  input->show();
100  input->setAbsCoor2D(200, 230);
101
102  OrxGui::GLGuiSlider* slider = new OrxGui::GLGuiSlider();
103  slider->connect(SIGNAL(slider, valueChanged), this, SLOT(SimpleGameMenu, TEST));
104  slider->setRange(-1, 10);
105  slider->setValue(slider->min());
106  slider->show();
107  slider->setAbsCoor2D(200, 270);
108
109  /////
110}
111
112
113#include "threading.h"
114void SimpleGameMenu::execURL() const
115{
116  std::string URL = "http://www.orxonox.net";
117  SDL_CreateThread(startURL, (void*)&URL);
118}
119
120#ifdef __OSX__
121#include <ApplicationServices/ApplicationServices.h>
122#elif defined __WIN32__
123#include <shellapi.h>
124#endif
125
126int SimpleGameMenu::startURL(void* url)
127{
128  std::string URL = *(std::string*)url;
129#ifdef __linux__
130  system ((std::string("firefox ") + URL).c_str());
131#elif defined __OSX__
132    CFURLRef url_handle = CFURLCreateWithBytes (NULL, (UInt8 *)URL.c_str(), URL.size(),
133                                         kCFStringEncodingASCII, NULL);
134    LSOpenCFURLRef (url_handle, NULL);
135    CFRelease (url_handle);
136#elif defined __WIN32__
137    ShellExecute(GetActiveWindow(),
138                 "open", URL.c_str(), NULL, NULL, SW_SHOWNORMAL);
139  }
140#endif
141  PRINTF(3)("loaded external webpage %s\n", URL.c_str());
142}
143
144/**
145*  @brief remove the SimpleGameMenu from memory
146*
147*  delete everything explicitly, that isn't contained in the parenting tree!
148*  things contained in the tree are deleted automaticaly
149*/
150SimpleGameMenu::~SimpleGameMenu ()
151{
152  PRINTF(3)("SimpleGameMenu::~SimpleGameMenu() - deleting current world\n");
153
154  if( this->dataTank)
155    delete this->dataTank;
156  delete OrxGui::GLGuiHandler::getInstance( );
157}
158
159
160/**
161* @brief loads the parameters of a SimpleGameMenu from an XML-element
162* @param root the XML-element to load from
163*/
164void SimpleGameMenu::loadParams(const TiXmlElement* root)
165{
166  /* skip the GameWorld, since it does not define any useful loadParams for this class */
167  //static_cast<GameWorld*>(this)->loadParams(root);
168  GameWorld::loadParams(root);
169
170  PRINTF(4)("Loaded SimpleGameMenu specific stuff\n");
171}
172
173
174/**
175* @brief this is executed just before load
176*
177* since the load function sometimes needs data, that has been initialized
178* before the load and after the proceeding storyentity has finished
179*/
180ErrorMessage SimpleGameMenu::init()
181{
182  /* call underlying init funciton */
183  GameWorld::init();
184
185  this->subscribeEvent(ES_MENU, SDLK_UP);
186  this->subscribeEvent(ES_MENU, SDLK_DOWN);
187  this->subscribeEvent(ES_MENU, SDLK_RETURN);
188  this->subscribeEvent(ES_MENU, SDLK_SPACE);
189  this->subscribeEvent(ES_MENU, SDLK_ESCAPE);
190
191  this->dataTank->localCamera->setRelCoor(this->cameraVector);
192
193  GraphicsEngine::getInstance()->displayFPS(false);
194
195  this->layerIndex = 0;
196  this->menuSelectedIndex = 0;
197}
198
199
200/**
201* @brief load the data
202*/
203ErrorMessage SimpleGameMenu::loadData()
204{
205  GameWorld::loadData();
206
207  if (this->dataXML != NULL)
208  {
209    LoadParam(dataXML, "selector-sound", this, SimpleGameMenu, setSelectorSound);
210
211    TiXmlElement* element = this->dataXML->FirstChildElement("Elements");
212
213
214    if( element == NULL)
215    {
216      PRINTF(1)("SimpleGameMenu is missing 'Elements'\n");
217    }
218    else
219    {
220      element = element->FirstChildElement();
221      // load Players/Objects/Whatever
222      PRINTF(4)("Loading Elements\n");
223      while( element != NULL)
224      {
225        BaseObject* created = Factory::fabricate(element);
226        if( created != NULL )
227        {
228          PRINTF(4)("Created a %s::%s\n", created->getClassName(), created->getName());
229          if (!created->isA(CL_ELEMENT_2D))
230            PRINTF(2)("Error the Created Entity is not an Element2D but an %s::%s\n", created->getClassName(), created->getName());
231        }
232        element = element->NextSiblingElement();
233      }
234      PRINTF(4)("Done loading Elements\n");
235    }
236  }
237
238  /* get the menu list */
239  const std::list<BaseObject*>* imageEntityList = ClassList::getList(CL_IMAGE_ENTITY);
240  std::list<BaseObject*>::const_iterator entity;
241  for (entity = imageEntityList->begin(); entity != imageEntityList->end(); entity++)
242  {
243
244    if( !strcmp("Selector_Menu", (*entity)->getName()))
245    {
246      this->menuSelector = dynamic_cast<ImageEntity*>(*entity);
247      this->menuSelector->setBindNode((const PNode*)NULL);
248    }
249  }
250
251  imageEntityList = ClassList::getList(CL_TEXT_ELEMENT);
252  for (entity = imageEntityList->begin(); entity != imageEntityList->end(); entity++)
253  {
254    if( !strcmp( "StartGame_Menu", (*entity)->getName()))
255    {
256      this->menuStartGame = dynamic_cast<TextElement*>(*entity);
257      this->menuStartGame->setBindNode((const PNode*)NULL);
258      this->menuStartGame->setRelCoor2D(State::getResX() / 2.0f,
259                                        State::getResY() / 2.0f - 60.0f);
260      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
261
262    }
263    else if( !strcmp( "Multiplayer_Menu", (*entity)->getName()))
264    {
265      this->menuStartMultiplayerGame = dynamic_cast<TextElement*>(*entity);
266      this->menuStartMultiplayerGame->setBindNode((const PNode*)NULL);
267      this->menuStartMultiplayerGame->setRelCoor2D(State::getResX() / 2.0f,
268          State::getResY() / 2.0f + ((this->menuLayers[0].menuList.size() -1 ) * 60.0f));
269      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
270    }
271    else if( !strcmp( "Quit_Menu", (*entity)->getName()))
272    {
273      this->menuQuitGame = dynamic_cast<TextElement*>(*entity);
274      this->menuQuitGame->setBindNode((const PNode*)NULL);
275      this->menuQuitGame->setRelCoor2D(State::getResX() / 2.0f,
276                                       State::getResY() / 2.0f + ((this->menuLayers[0].menuList.size() -1 )* 60.0f));
277      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
278    }
279  }
280  this->menuSelected->getNullElement()->update2D(0.1f);
281  this->menuSelectedIndex = 0;
282  this->menuSelected = this->menuLayers[0].menuList[this->menuSelectedIndex];
283  this->sliderTo(this->menuSelected, 0.0f);
284
285
286  // loading the storyentities submenu (singleplayer)
287  const std::list<BaseObject*>* storyEntities = ClassList::getList(CL_STORY_ENTITY);
288  std::list<BaseObject*>::const_iterator it;
289  for( it = storyEntities->begin(); it != storyEntities->end(); it++)
290  {
291    StoryEntity* se = dynamic_cast<StoryEntity*>(*it);
292    if( se->isContainedInMenu())
293    {
294      this->menuLayers[1].storyList.push_back(se);
295
296      // generating menu item
297      TextElement* te = new TextElement();
298      te->setVisibility(false);
299      te->setText(se->getName());
300      te->setRelCoor2D(State::getResX() / 2.0f - 200.0f, State::getResY() / 2.0f + ((this->menuLayers[1].menuList.size() - 2.0f) * 60.0f));
301      this->menuLayers[1].menuList.push_back(te);
302
303      // generating screenshoot item
304      ImageEntity* ie = new ImageEntity();
305      ie->setVisibility(false);
306      ie->setBindNode((const PNode*)NULL);
307      ie->setTexture(se->getMenuScreenshoot());
308      ie->setRelCoor2D(State::getResX() / 2.0f + 250.0f, State::getResY() / 2.0f);
309      ie->setSize2D(140.0f, 105.0f);
310      this->menuLayers[1].screenshootList.push_back(ie);
311    }
312  }
313}
314
315/**
316* @brief set the Sound to play when switching menu entry.
317* @param selectorSound the sound to load.
318*/
319void SimpleGameMenu::setSelectorSound(const std::string& selectorSound)
320{
321  this->selectorSource = OrxSound::SoundEngine::getInstance()->createSource(selectorSound, NULL);
322}
323
324ErrorMessage SimpleGameMenu::unloadData()
325{
326  this->unsubscribeEvents(ES_MENU);
327
328  std::vector<MenuLayer>::iterator mit;
329  for(mit = this->menuLayers.begin(); mit != this->menuLayers.end(); mit++)
330  {
331    while(!(*mit).menuList.empty())
332    {
333      delete (*mit).menuList.back();
334      (*mit).menuList.pop_back();
335    }
336
337    (*mit).menuList.clear();
338    (*mit).storyList.clear();
339    (*mit).screenshootList.clear();
340  }
341
342  // delete the SoundSource.
343  if (this->selectorSource != NULL)
344    delete this->selectorSource;
345  this->selectorSource = NULL;
346
347  GameWorld::unloadData();
348}
349
350
351/**
352* @brief start the menu
353*/
354bool SimpleGameMenu::start()
355{
356  EventHandler::getInstance()->pushState(ES_MENU);
357
358  /* now call the underlying*/
359  GameWorld::start();
360}
361
362
363
364/**
365* stop the menu
366*/
367bool SimpleGameMenu::stop()
368{
369  EventHandler::getInstance()->popState();
370
371  /* now call the underlying*/
372  GameWorld::stop();
373}
374
375
376/**
377*  override the standard tick for more functionality
378*/
379void SimpleGameMenu::tick()
380{
381  GameWorld::tick();
382
383  // Make the GLGui tick.
384  OrxGui::GLGuiHandler::getInstance()->tick(this->dtS);
385
386  this->animateScene(this->dtS);
387}
388
389
390/**
391* @brief no collision detection in the menu
392*/
393void SimpleGameMenu::collide()
394{
395  //   this->dataTank->localCamera->
396}
397
398
399/**
400* @brief animate the scene
401*/
402void SimpleGameMenu::animateScene(float dt)
403{
404  Quaternion q(/*0.00005*/ dt * .1, Vector(0.0, 1.0, 0.0));
405  this->cameraVector = q.apply(this->cameraVector);
406  this->dataTank->localCamera->setRelCoor(this->cameraVector);
407  this->dataTank->localCamera->getTarget()->setRelCoorSoft(0,0,0);
408}
409
410void SimpleGameMenu::quitMenu()
411{
412  this->setNextStoryID(WORLD_ID_GAMEEND);
413  this->stop();
414}
415
416
417/**
418* @brief event dispatcher funciton
419* @param event the incoming event
420*/
421void SimpleGameMenu::process(const Event &event)
422{
423  /* ----------------- LAYER 1 ---------------*/
424  if( this->layerIndex == 0)
425  {
426    if( event.type == SDLK_RETURN && event.bPressed == true)
427    {
428      if( this->menuSelected == this->menuQuitGame)
429      {
430        this->setNextStoryID(WORLD_ID_GAMEEND);
431        this->stop();
432      }
433      if( this->menuSelected == this->menuStartGame)
434      {
435        // switch to first submenu
436        if( this->menuLayers[1].menuList.size() == 0)
437        {
438          PRINTF(1)("Haven't got any StoryEntities to play!\n");
439          return;
440        }
441
442        this->switchMenuLayer(this->layerIndex, 1);
443      }
444    }
445    if( event.type == SDLK_ESCAPE && event.bPressed == true)
446    {
447      this->setNextStoryID(WORLD_ID_GAMEEND);
448      this->stop();
449    }
450  }  /* ----------------- LAYER 2 ---------------*/
451  else if( this->layerIndex == 1)
452  {
453    if( event.type == SDLK_RETURN && event.bPressed == true)
454    {
455      this->setNextStoryID( this->menuLayers[1].storyList[this->menuSelectedIndex]->getStoryID());
456      this->stop();
457    }
458    if( event.type == SDLK_ESCAPE && event.bPressed == true)
459    {
460      this->switchMenuLayer(this->layerIndex, 0);
461    }
462  }
463
464
465
466  // The menu selction cursor
467  if( event.type == SDLK_DOWN && event.bPressed == true)
468  {
469    if(this->menuSelectedIndex < (this->menuLayers[this->layerIndex].menuList.size() - 1))
470    {
471      this->menuSelected = this->menuLayers[this->layerIndex].menuList[++this->menuSelectedIndex];
472      this->sliderTo(this->menuSelected, 5.0f);
473      if (this->selectorSource != NULL)
474        this->selectorSource->play();
475
476      if( this->layerIndex == 1)
477      {
478        this->menuLayers[1].screenshootList[this->menuSelectedIndex]->setVisibility(true);
479        this->menuLayers[1].screenshootList[this->menuSelectedIndex-1]->setVisibility(false);
480      }
481    }
482  }
483  else if( event.type == SDLK_UP && event.bPressed == true)
484  {
485    if(this->menuSelectedIndex > 0)
486    {
487      this->menuSelected = this->menuLayers[this->layerIndex].menuList[--this->menuSelectedIndex];
488      this->sliderTo(this->menuSelected, 5.0f);
489      if (this->selectorSource != NULL)
490        this->selectorSource->play();
491
492      if( this->layerIndex == 1)
493      {
494        this->menuLayers[1].screenshootList[this->menuSelectedIndex]->setVisibility(true);
495        this->menuLayers[1].screenshootList[this->menuSelectedIndex+1]->setVisibility(false);
496      }
497    }
498  }
499}
500
501
502/**
503* @brief switches to from one meny layer to an other
504* @param layer1 from layer
505* @param layer2 to layer
506*/
507void SimpleGameMenu::switchMenuLayer(int layer1, int layer2)
508{
509  // wrong sizes
510  if(layer1 >= this->menuLayers.size() || layer2 >= this->menuLayers.size())
511    return;
512
513
514  PRINTF(0)("Removing layer %i\n", layer1);
515  std::vector<TextElement*>::iterator te;
516  // fade old menu
517  for( te = this->menuLayers[layer1].menuList.begin(); te != this->menuLayers[layer1].menuList.end(); te++)
518  {
519    (*te)->setVisibility(false);
520  }
521
522  std::vector<ImageEntity*>::iterator it;
523
524  //also fade the screenshots if in level choosement mode
525  for( it = this->menuLayers[layer1].screenshootList.begin(); it != this->menuLayers[layer1].screenshootList.end(); it++)
526  {
527    (*it)->setVisibility(false);
528  }
529
530
531  PRINTF(0)("Showing layer %i\n", layer1);
532  // beam here the new menu
533  for( te = this->menuLayers[layer2].menuList.begin(); te != this->menuLayers[layer2].menuList.end(); te++ )
534  {
535    (*te)->setVisibility(true);
536  }
537
538
539  this->layerIndex = layer2;
540  this->menuSelected = this->menuLayers[layer2].menuList[0];
541  this->menuSelector->setAbsCoor2D(this->menuSelected->getAbsCoor2D() + Vector2D(0, this->menuSelected->getSizeY2D() *.5));
542  this->menuSelector->setSize2D(this->menuSelected->getSizeX2D()*.7, this->menuSelected->getSizeY2D());
543  this->menuSelectedIndex = 0;
544
545  if( layer2 == 1)
546    this->menuLayers[layer2].screenshootList[0]->setVisibility(true);
547}
548
549void SimpleGameMenu::sliderTo(const Element2D* element, float bias)
550{
551  if (bias > 0.0)
552  {
553    this->menuSelector->setAbsCoorSoft2D(element->getAbsCoor2D() + Vector2D(0, element->getSizeY2D() *.5), bias);
554    this->menuSelector->setSizeSoft2D(element->getSizeX2D()*.7, element->getSizeY2D(), bias);
555  }
556  else
557  {
558    this->menuSelector->setAbsCoor2D(element->getAbsCoor2D() + Vector2D(0, element->getSizeY2D() *.5));
559    this->menuSelector->setSize2D(element->getSizeX2D()*.7, element->getSizeY2D());
560  }
561}
562
563
564
565/**********************************************************************************************
566SimpleGameMenuData
567**********************************************************************************************/
568
569
570/**
571* SimpleGameMenuData constructor
572*/
573SimpleGameMenuData::SimpleGameMenuData()
574{}
575
576/**
577* SimpleGameMenuData decontructor
578*/
579SimpleGameMenuData::~SimpleGameMenuData()
580{}
581
582
583/**
584*  initialize the GameWorldDataData
585*/
586ErrorMessage SimpleGameMenuData::init()
587{
588  /* call underlying function */
589  GameWorldData::init();
590}
591
592
593/**
594*  loads the GUI data
595* @param root reference to the xml root element
596*/
597ErrorMessage SimpleGameMenuData::loadGUI(const TiXmlElement* root)
598{
599  /* call underlying function */
600  GameWorldData::loadGUI(root);
601}
602
603
604/**
605*  unloads the GUI data
606*/
607ErrorMessage SimpleGameMenuData::unloadGUI()
608{
609  /* call underlying function */
610  GameWorldData::unloadGUI();
611}
612
613
614/**
615*  overloads the GameWorld::loadWorldEntities(...) class since the menu WorldEntity loading is different (less loading stuff)
616* @param root reference to the xml root parameter
617*/
618ErrorMessage SimpleGameMenuData::loadWorldEntities(const TiXmlElement* root)
619{
620  GameWorldData::loadWorldEntities(root);
621  /*
622  const TiXmlElement* element = root->FirstChildElement("WorldEntities");
623
624  if( element != NULL)
625  {
626  element = element->FirstChildElement();
627  PRINTF(4)("Loading WorldEntities\n");
628  while(element != NULL)
629  {
630  BaseObject* created = Factory::fabricate(element);
631  if( created != NULL )
632  printf("Created a %s: %s\n", created->getClassName(), created->getName());
633
634  if( element->Value() == "SkyBox")
635  this->sky = dynamic_cast<WorldEntity*>(created);
636  if( element->Value() == "Terrain")
637  this->terrain = dynamic_cast<Terrain*>(created);
638  element = element->NextSiblingElement();
639  }
640
641  PRINTF(4)("Done loading WorldEntities\n");
642  }
643
644  // init the pnode tree
645  PNode::getNullParent()->init();
646  */
647}
648
649
650/**
651*  unloads the world entities from the xml file
652*/
653ErrorMessage SimpleGameMenuData::unloadWorldEntities()
654{
655  /* call underlying function */
656  GameWorldData::unloadWorldEntities();
657}
658
659
660/**
661*  loads the scene data
662* @param root reference to the xml root element
663*/
664ErrorMessage SimpleGameMenuData::loadScene(const TiXmlElement* root)
665{
666  /* call underlying function */
667  GameWorldData::loadScene(root);
668}
669
670
671/**
672*  unloads the scene data
673*/
674ErrorMessage SimpleGameMenuData::unloadScene()
675{
676  /* call underlying function */
677  GameWorldData::unloadScene();
678}
679
680
681
Note: See TracBrowser for help on using the repository browser.