Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7894 was 7893, checked in by bensch, 19 years ago

gui: InputLine appends

File size: 16.8 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->show();
70  pb->setAbsCoor2D(50, 50);
71
72  OrxGui::GLGuiPushButton* dnpb = new OrxGui::GLGuiPushButton("DO NOT PUSH ME");
73  dnpb->show();
74  dnpb->setAbsCoor2D(350, 50);
75
76  OrxGui::GLGuiPushButton* rdnpb = new OrxGui::GLGuiPushButton("REALLY DO NOT PUSH ME!!");
77  rdnpb->show();
78  rdnpb->setAbsCoor2D(200, 180);
79  rdnpb->connectSignal(OrxGui::Signal_release, this, createExecutor<SimpleGameMenu>(&SimpleGameMenu::quitMenu));
80
81  OrxGui::GLGuiInputLine* input = new OrxGui::GLGuiInputLine();
82  input->show();
83  input->setAbsCoor2D(200, 230);
84
85  OrxGui::GLGuiHandler::getInstance()->activateCursor();
86  /////
87  if (root != NULL)
88    this->loadParams(root);
89
90  State::setMenuID(this->getNextStoryID());
91}
92
93
94/**
95 *  @brief remove the SimpleGameMenu from memory
96 *
97 *  delete everything explicitly, that isn't contained in the parenting tree!
98 *  things contained in the tree are deleted automaticaly
99 */
100SimpleGameMenu::~SimpleGameMenu ()
101{
102  PRINTF(3)("SimpleGameMenu::~SimpleGameMenu() - deleting current world\n");
103
104  if( this->dataTank)
105    delete this->dataTank;
106  delete OrxGui::GLGuiHandler::getInstance( );
107}
108
109
110/**
111 * @brief loads the parameters of a SimpleGameMenu from an XML-element
112 * @param root the XML-element to load from
113 */
114void SimpleGameMenu::loadParams(const TiXmlElement* root)
115{
116  /* skip the GameWorld, since it does not define any useful loadParams for this class */
117  //static_cast<GameWorld*>(this)->loadParams(root);
118  GameWorld::loadParams(root);
119
120  PRINTF(4)("Loaded SimpleGameMenu specific stuff\n");
121}
122
123
124/**
125 * @brief this is executed just before load
126 *
127 * since the load function sometimes needs data, that has been initialized
128 * before the load and after the proceeding storyentity has finished
129 */
130ErrorMessage SimpleGameMenu::init()
131{
132  /* call underlying init funciton */
133  GameWorld::init();
134
135  this->subscribeEvent(ES_MENU, SDLK_UP);
136  this->subscribeEvent(ES_MENU, SDLK_DOWN);
137  this->subscribeEvent(ES_MENU, SDLK_RETURN);
138  this->subscribeEvent(ES_MENU, SDLK_SPACE);
139  this->subscribeEvent(ES_MENU, SDLK_ESCAPE);
140
141  this->dataTank->localCamera->setRelCoor(this->cameraVector);
142
143  GraphicsEngine::getInstance()->displayFPS(false);
144
145  this->layerIndex = 0;
146  this->menuSelectedIndex = 0;
147}
148
149
150/**
151 * @brief load the data
152 */
153ErrorMessage SimpleGameMenu::loadData()
154{
155  GameWorld::loadData();
156
157  if (this->dataXML != NULL)
158  {
159    LoadParam(dataXML, "selector-sound", this, SimpleGameMenu, setSelectorSound);
160
161    TiXmlElement* element = this->dataXML->FirstChildElement("Elements");
162
163
164    if( element == NULL)
165    {
166      PRINTF(1)("SimpleGameMenu is missing 'Elements'\n");
167    }
168    else
169    {
170      element = element->FirstChildElement();
171    // load Players/Objects/Whatever
172      PRINTF(4)("Loading Elements\n");
173      while( element != NULL)
174      {
175        BaseObject* created = Factory::fabricate(element);
176        if( created != NULL )
177        {
178          PRINTF(4)("Created a %s::%s\n", created->getClassName(), created->getName());
179          if (!created->isA(CL_ELEMENT_2D))
180            PRINTF(2)("Error the Created Entity is not an Element2D but an %s::%s\n", created->getClassName(), created->getName());
181        }
182        element = element->NextSiblingElement();
183      }
184      PRINTF(4)("Done loading Elements\n");
185    }
186  }
187
188  /* get the menu list */
189  const std::list<BaseObject*>* imageEntityList = ClassList::getList(CL_IMAGE_ENTITY);
190  std::list<BaseObject*>::const_iterator entity;
191  for (entity = imageEntityList->begin(); entity != imageEntityList->end(); entity++)
192  {
193
194    if( !strcmp("Selector_Menu", (*entity)->getName()))
195    {
196      this->menuSelector = dynamic_cast<ImageEntity*>(*entity);
197      this->menuSelector->setBindNode((const PNode*)NULL);
198    }
199  }
200
201  imageEntityList = ClassList::getList(CL_TEXT_ELEMENT);
202  for (entity = imageEntityList->begin(); entity != imageEntityList->end(); entity++)
203  {
204    if( !strcmp( "StartGame_Menu", (*entity)->getName()))
205    {
206      this->menuStartGame = dynamic_cast<TextElement*>(*entity);
207      this->menuStartGame->setBindNode((const PNode*)NULL);
208      this->menuStartGame->setRelCoor2D(State::getResX() / 2.0f,
209                                        State::getResY() / 2.0f - 60.0f);
210      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
211
212    }
213    else if( !strcmp( "Multiplayer_Menu", (*entity)->getName()))
214    {
215      this->menuStartMultiplayerGame = dynamic_cast<TextElement*>(*entity);
216      this->menuStartMultiplayerGame->setBindNode((const PNode*)NULL);
217      this->menuStartMultiplayerGame->setRelCoor2D(State::getResX() / 2.0f,
218                                                   State::getResY() / 2.0f + ((this->menuLayers[0].menuList.size() -1 ) * 60.0f));
219      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
220    }
221    else if( !strcmp( "Quit_Menu", (*entity)->getName()))
222    {
223      this->menuQuitGame = dynamic_cast<TextElement*>(*entity);
224      this->menuQuitGame->setBindNode((const PNode*)NULL);
225      this->menuQuitGame->setRelCoor2D(State::getResX() / 2.0f,
226                                       State::getResY() / 2.0f + ((this->menuLayers[0].menuList.size() -1 )* 60.0f));
227      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
228    }
229  }
230  this->menuSelected->getNullElement()->update2D(0.1f);
231  this->menuSelectedIndex = 0;
232  this->menuSelected = this->menuLayers[0].menuList[this->menuSelectedIndex];
233  this->sliderTo(this->menuSelected, 0.0f);
234
235
236  // loading the storyentities submenu (singleplayer)
237  const std::list<BaseObject*>* storyEntities = ClassList::getList(CL_STORY_ENTITY);
238  std::list<BaseObject*>::const_iterator it;
239  for( it = storyEntities->begin(); it != storyEntities->end(); it++)
240  {
241    StoryEntity* se = dynamic_cast<StoryEntity*>(*it);
242    if( se->isContainedInMenu())
243    {
244      this->menuLayers[1].storyList.push_back(se);
245
246      // generating menu item
247      TextElement* te = new TextElement();
248      te->setVisibility(false);
249      te->setText(se->getName());
250      te->setRelCoor2D(State::getResX() / 2.0f - 200.0f, State::getResY() / 2.0f + ((this->menuLayers[1].menuList.size() - 2.0f) * 60.0f));
251      this->menuLayers[1].menuList.push_back(te);
252
253      // generating screenshoot item
254      ImageEntity* ie = new ImageEntity();
255      ie->setVisibility(false);
256      ie->setBindNode((const PNode*)NULL);
257      ie->setTexture(se->getMenuScreenshoot());
258      ie->setRelCoor2D(State::getResX() / 2.0f + 250.0f, State::getResY() / 2.0f);
259      ie->setSize2D(140.0f, 105.0f);
260      this->menuLayers[1].screenshootList.push_back(ie);
261    }
262  }
263}
264
265/**
266 * @brief set the Sound to play when switching menu entry.
267 * @param selectorSound the sound to load.
268 */
269void SimpleGameMenu::setSelectorSound(const std::string& selectorSound)
270{
271  this->selectorSource = OrxSound::SoundEngine::getInstance()->createSource(selectorSound, NULL);
272}
273
274ErrorMessage SimpleGameMenu::unloadData()
275{
276  this->unsubscribeEvents(ES_MENU);
277
278  std::vector<MenuLayer>::iterator mit;
279  for(mit = this->menuLayers.begin(); mit != this->menuLayers.end(); mit++)
280  {
281    while(!(*mit).menuList.empty())
282    {
283      delete (*mit).menuList.back();
284      (*mit).menuList.pop_back();
285    }
286
287    (*mit).menuList.clear();
288    (*mit).storyList.clear();
289    (*mit).screenshootList.clear();
290  }
291
292  // delete the SoundSource.
293  if (this->selectorSource != NULL)
294    delete this->selectorSource;
295  this->selectorSource = NULL;
296
297  GameWorld::unloadData();
298}
299
300
301/**
302 * @brief start the menu
303 */
304bool SimpleGameMenu::start()
305{
306  EventHandler::getInstance()->pushState(ES_MENU);
307
308  /* now call the underlying*/
309  GameWorld::start();
310}
311
312
313
314/**
315 * stop the menu
316 */
317bool SimpleGameMenu::stop()
318{
319  EventHandler::getInstance()->popState();
320
321  /* now call the underlying*/
322  GameWorld::stop();
323}
324
325
326/**
327 *  override the standard tick for more functionality
328 */
329void SimpleGameMenu::tick()
330{
331  GameWorld::tick();
332
333  // Make the GLGui tick.
334  OrxGui::GLGuiHandler::getInstance()->tick(this->dtS);
335
336  this->animateScene(this->dtS);
337}
338
339
340/**
341 * @brief no collision detection in the menu
342 */
343void SimpleGameMenu::collide()
344{
345//   this->dataTank->localCamera->
346}
347
348
349/**
350 * @brief animate the scene
351 */
352void SimpleGameMenu::animateScene(float dt)
353{
354  Quaternion q(/*0.00005*/ dt * .1, Vector(0.0, 1.0, 0.0));
355  this->cameraVector = q.apply(this->cameraVector);
356  this->dataTank->localCamera->setRelCoor(this->cameraVector);
357  this->dataTank->localCamera->getTarget()->setRelCoorSoft(0,0,0);
358}
359
360void SimpleGameMenu::quitMenu()
361{
362  this->setNextStoryID(WORLD_ID_GAMEEND);
363  this->stop();
364}
365
366
367/**
368 * @brief event dispatcher funciton
369 * @param event the incoming event
370 */
371void SimpleGameMenu::process(const Event &event)
372{
373  /* ----------------- LAYER 1 ---------------*/
374  if( this->layerIndex == 0)
375  {
376    if( event.type == SDLK_RETURN && event.bPressed == true)
377    {
378      if( this->menuSelected == this->menuQuitGame)
379      {
380        this->setNextStoryID(WORLD_ID_GAMEEND);
381        this->stop();
382      }
383      if( this->menuSelected == this->menuStartGame)
384      {
385        // switch to first submenu
386        if( this->menuLayers[1].menuList.size() == 0)
387        {
388          PRINTF(1)("Haven't got any StoryEntities to play!\n");
389          return;
390        }
391
392        this->switchMenuLayer(this->layerIndex, 1);
393      }
394    }
395    if( event.type == SDLK_ESCAPE && event.bPressed == true)
396    {
397      this->setNextStoryID(WORLD_ID_GAMEEND);
398      this->stop();
399    }
400  }  /* ----------------- LAYER 2 ---------------*/
401  else if( this->layerIndex == 1)
402  {
403    if( event.type == SDLK_RETURN && event.bPressed == true)
404    {
405      this->setNextStoryID( this->menuLayers[1].storyList[this->menuSelectedIndex]->getStoryID());
406      this->stop();
407    }
408    if( event.type == SDLK_ESCAPE && event.bPressed == true)
409    {
410      this->switchMenuLayer(this->layerIndex, 0);
411    }
412  }
413
414
415
416  // The menu selction cursor
417  if( event.type == SDLK_DOWN && event.bPressed == true)
418  {
419    if(this->menuSelectedIndex < (this->menuLayers[this->layerIndex].menuList.size() - 1))
420    {
421      this->menuSelected = this->menuLayers[this->layerIndex].menuList[++this->menuSelectedIndex];
422      this->sliderTo(this->menuSelected, 5.0f);
423      if (this->selectorSource != NULL)
424        this->selectorSource->play();
425
426      if( this->layerIndex == 1)
427      {
428        this->menuLayers[1].screenshootList[this->menuSelectedIndex]->setVisibility(true);
429        this->menuLayers[1].screenshootList[this->menuSelectedIndex-1]->setVisibility(false);
430      }
431    }
432  }
433  else if( event.type == SDLK_UP && event.bPressed == true)
434  {
435    if(this->menuSelectedIndex > 0)
436    {
437      this->menuSelected = this->menuLayers[this->layerIndex].menuList[--this->menuSelectedIndex];
438      this->sliderTo(this->menuSelected, 5.0f);
439      if (this->selectorSource != NULL)
440        this->selectorSource->play();
441
442      if( this->layerIndex == 1)
443      {
444        this->menuLayers[1].screenshootList[this->menuSelectedIndex]->setVisibility(true);
445        this->menuLayers[1].screenshootList[this->menuSelectedIndex+1]->setVisibility(false);
446      }
447    }
448  }
449}
450
451
452/**
453 * @brief switches to from one meny layer to an other
454 * @param layer1 from layer
455 * @param layer2 to layer
456 */
457void SimpleGameMenu::switchMenuLayer(int layer1, int layer2)
458{
459  // wrong sizes
460  if(layer1 >= this->menuLayers.size() || layer2 >= this->menuLayers.size())
461    return;
462
463
464  PRINTF(0)("Removing layer %i\n", layer1);
465  std::vector<TextElement*>::iterator te;
466  // fade old menu
467  for( te = this->menuLayers[layer1].menuList.begin(); te != this->menuLayers[layer1].menuList.end(); te++)
468  {
469    (*te)->setVisibility(false);
470  }
471
472  std::vector<ImageEntity*>::iterator it;
473
474  //also fade the screenshots if in level choosement mode
475  for( it = this->menuLayers[layer1].screenshootList.begin(); it != this->menuLayers[layer1].screenshootList.end(); it++)
476  {
477    (*it)->setVisibility(false);
478  }
479
480
481  PRINTF(0)("Showing layer %i\n", layer1);
482  // beam here the new menu
483  for( te = this->menuLayers[layer2].menuList.begin(); te != this->menuLayers[layer2].menuList.end(); te++ )
484  {
485    (*te)->setVisibility(true);
486  }
487
488
489  this->layerIndex = layer2;
490  this->menuSelected = this->menuLayers[layer2].menuList[0];
491  this->menuSelector->setAbsCoor2D(this->menuSelected->getAbsCoor2D() + Vector2D(0, this->menuSelected->getSizeY2D() *.5));
492  this->menuSelector->setSize2D(this->menuSelected->getSizeX2D()*.7, this->menuSelected->getSizeY2D());
493  this->menuSelectedIndex = 0;
494
495  if( layer2 == 1)
496    this->menuLayers[layer2].screenshootList[0]->setVisibility(true);
497}
498
499void SimpleGameMenu::sliderTo(const Element2D* element, float bias)
500{
501  if (bias > 0.0)
502  {
503    this->menuSelector->setAbsCoorSoft2D(element->getAbsCoor2D() + Vector2D(0, element->getSizeY2D() *.5), bias);
504    this->menuSelector->setSizeSoft2D(element->getSizeX2D()*.7, element->getSizeY2D(), bias);
505  }
506  else
507  {
508    this->menuSelector->setAbsCoor2D(element->getAbsCoor2D() + Vector2D(0, element->getSizeY2D() *.5));
509    this->menuSelector->setSize2D(element->getSizeX2D()*.7, element->getSizeY2D());
510  }
511}
512
513
514
515/**********************************************************************************************
516    SimpleGameMenuData
517 **********************************************************************************************/
518
519
520/**
521 * SimpleGameMenuData constructor
522 */
523SimpleGameMenuData::SimpleGameMenuData()
524{}
525
526/**
527 * SimpleGameMenuData decontructor
528 */
529SimpleGameMenuData::~SimpleGameMenuData()
530{}
531
532
533/**
534 *  initialize the GameWorldDataData
535 */
536ErrorMessage SimpleGameMenuData::init()
537{
538  /* call underlying function */
539  GameWorldData::init();
540}
541
542
543/**
544 *  loads the GUI data
545 * @param root reference to the xml root element
546 */
547ErrorMessage SimpleGameMenuData::loadGUI(const TiXmlElement* root)
548{
549  /* call underlying function */
550  GameWorldData::loadGUI(root);
551}
552
553
554/**
555 *  unloads the GUI data
556 */
557ErrorMessage SimpleGameMenuData::unloadGUI()
558{
559  /* call underlying function */
560  GameWorldData::unloadGUI();
561}
562
563
564/**
565 *  overloads the GameWorld::loadWorldEntities(...) class since the menu WorldEntity loading is different (less loading stuff)
566 * @param root reference to the xml root parameter
567 */
568ErrorMessage SimpleGameMenuData::loadWorldEntities(const TiXmlElement* root)
569{
570  GameWorldData::loadWorldEntities(root);
571  /*
572  const TiXmlElement* element = root->FirstChildElement("WorldEntities");
573
574  if( element != NULL)
575  {
576    element = element->FirstChildElement();
577    PRINTF(4)("Loading WorldEntities\n");
578    while(element != NULL)
579    {
580      BaseObject* created = Factory::fabricate(element);
581      if( created != NULL )
582        printf("Created a %s: %s\n", created->getClassName(), created->getName());
583
584      if( element->Value() == "SkyBox")
585        this->sky = dynamic_cast<WorldEntity*>(created);
586      if( element->Value() == "Terrain")
587        this->terrain = dynamic_cast<Terrain*>(created);
588      element = element->NextSiblingElement();
589    }
590
591    PRINTF(4)("Done loading WorldEntities\n");
592  }
593
594  // init the pnode tree
595  PNode::getNullParent()->init();
596  */
597}
598
599
600/**
601 *  unloads the world entities from the xml file
602 */
603ErrorMessage SimpleGameMenuData::unloadWorldEntities()
604{
605  /* call underlying function */
606  GameWorldData::unloadWorldEntities();
607}
608
609
610/**
611 *  loads the scene data
612 * @param root reference to the xml root element
613 */
614ErrorMessage SimpleGameMenuData::loadScene(const TiXmlElement* root)
615{
616  /* call underlying function */
617  GameWorldData::loadScene(root);
618}
619
620
621/**
622 *  unloads the scene data
623 */
624ErrorMessage SimpleGameMenuData::unloadScene()
625{
626  /* call underlying function */
627  GameWorldData::unloadScene();
628}
629
630
631
Note: See TracBrowser for help on using the repository browser.