Desterrando el parámetro covered de update y draw
[angry-tux:angry-tux.git] / src / stateManager.cpp
1 /**
2  * @file stateManager.cpp
3  * 
4  * @author José Tomás Tocino García
5  * @date 2010
6  *
7  * Copyright (C) 2010 José Tomás Tocino García <theom3ga@gmail.com>
8  * 
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301, USA.
23  */
24
25
26 #include "stateManager.h"
27 #include "state.h"
28 #include "log.h"
29
30 #include <algorithm>
31 #include <boost/bind.hpp>
32
33
34 StateManager::StateManager (int width, int height, bool fullscreen, double updateInterval)
35     : Gosu::Window(width, height, fullscreen, updateInterval){
36     lDEBUG << Log::CON("StateManager");
37     numStates = 0;
38 }
39
40 void StateManager::update(){
41     performOperations();
42
43     for_each(states.rbegin(), states.rend(), boost::bind(&State::update, _1));
44
45     // if(!states.empty()){
46     //  StateRevIt it, itEnd = states.rend();
47     //  bool covered = false;
48     //  for(it = states.rbegin(); it != itEnd; ++it){
49     //      (*it) -> update(covered);
50     //      covered = true;
51     //  }
52     // }
53 }
54
55
56 void StateManager::draw(){
57     for_each(states.rbegin(), states.rend(), boost::bind(&State::draw, _1));
58
59     // if(!states.empty()){
60     //  StateRevIt it, itEnd = states.rend();
61     //  bool covered = false;
62     //  for(it = states.rbegin(); it != itEnd; ++it){
63     //      (*it) -> draw(covered);
64     //      covered = true;
65     //  }
66     // }
67 }
68
69 void StateManager::buttonDown(Gosu::Button B){
70     if(!states.empty())
71         states[numStates - 1] -> buttonDown(B);
72 }
73
74 void StateManager::buttonUp(Gosu::Button B){
75     if(!states.empty())
76         states[numStates - 1] -> buttonUp(B);
77 }
78
79 void StateManager::changeState(StatePointer state){
80     if(!states.empty()){
81         popState();
82     }
83     pushState(state);
84 }
85
86 void StateManager::pushState(StatePointer state){
87     lDEBUG << "Push requested";
88     pendingOperations.push(StateOp(opPUSH, state));
89     ++numStates;
90 }
91
92 void StateManager::popState(){
93     lDEBUG << "Pop requested";
94     pendingOperations.push(StateOp(opPOP));
95     --numStates;
96 }
97
98 void StateManager::popAllStates(){
99     lDEBUG << "Pop all states requested";
100     while(numStates > 0){
101         popState();
102     }    
103 }
104
105 /**
106  * @brief Perform the pending push and pop operations on the states queue
107  *
108  * The stateManager holds a queue called pendingOperations, where all
109  * the push and pop operations are stored. This function is called at
110  * the beginning of the game loop so each iteration starts with the
111  * appropiate states, instead of loading and unloading states at the
112  * middle of the loop.
113  *
114  * The calls to the focus setting functions are also locally defered,
115  * so only the actual front state and covered states get their focus
116  * functions called.
117  *
118  * @return 
119  *
120  */
121
122 void StateManager::performOperations(){
123     if(!pendingOperations.empty())
124         lDEBUG << "Performing " << pendingOperations.size() << " operations...";
125
126     while(!pendingOperations.empty()){
127         StateOp currentOperation = pendingOperations.front();
128
129         if(currentOperation.opType == opPUSH){
130             currentOperation.involvedState -> assignStateManager(this);
131             currentOperation.involvedState -> loadResources();
132
133             states.push_back(currentOperation.involvedState);
134             lDEBUG << "Performed push";
135         }
136
137         else if(currentOperation.opType == opPOP){
138             states.back() -> cleanup();
139             states.pop_back();
140             lDEBUG << "Performed pop";
141         }
142
143         pendingOperations.pop();
144     }    
145
146
147     if(!states.empty()){
148         StateRevIt it, itEnd = states.rend();
149         bool covered = false;
150         for(it = states.rbegin(); it != itEnd; ++it){
151
152             if(!covered && (*it) -> getCoverage()){
153                 (*it) -> setCoverage(false);
154                 (*it) -> focusSet();
155             }
156
157             else if(covered && !(*it) -> getCoverage()){
158                 (*it) -> setCoverage(true);
159                 (*it) -> focusLost();
160             }
161
162             covered = true;
163         }
164     }    
165 }
166
167 StateManager::~StateManager(){
168     lDEBUG << Log::DES("StateManager");
169
170     popAllStates();
171     performOperations();
172
173 }
174