|
JK2eA
|
00001 #pragma once 00002 00003 00004 #include "Controller.h" 00005 #include <vector> 00006 #include <utility> 00007 #include <algorithm> 00008 00017 template<class CntType, class ParamType> 00018 class CControllerPriorityMixer : public CController { 00019 protected: 00023 struct MIX_NODE { 00024 CntType* controller; 00025 float* weight; 00026 char priority; 00027 00028 bool operator>(const MIX_NODE& rNode) const 00029 { 00030 return priority > rNode.priority; 00031 } 00032 bool operator<(const MIX_NODE& rNode) const 00033 { 00034 return priority < rNode.priority; 00035 } 00036 bool operator==(const MIX_NODE& rNode) const 00037 { 00038 return priority == rNode.priority; 00039 } 00040 }; 00041 00042 std::vector<MIX_NODE> m_controllers; 00043 ParamType m_accumulated_param; 00044 00045 00046 00047 public: 00052 CControllerPriorityMixer(const std::string& name); 00056 virtual ~CControllerPriorityMixer(void); 00061 inline bool IsEmpty(); 00072 void RegisterController(CntType* cnt, float* weight, char priority); 00077 void UnRegisterController(CntType* cnt); 00081 void Normalize(); 00082 00087 inline ParamType* GetParameter(); 00094 virtual void Update(float dt); 00095 00096 CNTRL_CLASS_NAME(CControllerMixer); 00097 }; 00098 00099 template<class CntType, class ParamType> 00100 CControllerPriorityMixer<CntType, ParamType>::CControllerPriorityMixer(const std::string& name) : CController(name) 00101 { 00102 } 00103 00104 template<class CntType, class ParamType> 00105 CControllerPriorityMixer<CntType, ParamType>::~CControllerPriorityMixer() 00106 { 00107 } 00108 00109 template<class CntType, class ParamType> 00110 void CControllerPriorityMixer<CntType, ParamType>::RegisterController(CntType* cnt, float* weight, char priority) 00111 { 00112 if(!m_controllers.empty()) { 00113 if(cnt->GetParameter() != m_controllers[0].controller->GetParameter()) { 00114 LOGErr("CControllerPriorityMixer::RegisterController - parameters don't match"); 00115 return; 00116 } 00117 } 00118 00119 MIX_NODE new_node; 00120 cnt->SetPassive(true); 00121 new_node.controller = cnt; 00122 new_node.weight = weight; 00123 new_node.priority = priority; 00124 00125 m_controllers.push_back(new_node); 00126 00127 std::sort(m_controllers.begin(), m_controllers.end(), std::greater<MIX_NODE>()); 00128 } 00129 template<class CntType, class ParamType> 00130 void CControllerPriorityMixer<CntType, ParamType>::UnRegisterController(CntType* cnt) 00131 { 00132 for(size_t i = 0; i < m_controllers.size(); i++) { 00133 if(m_controllers[i].controller == cnt) { 00134 cnt->SetPassive(false); 00135 m_controllers.erase(m_controllers.begin() + i); 00136 break; 00137 } 00138 } 00139 } 00140 00141 template<class CntType, class ParamType> 00142 void CControllerPriorityMixer<CntType, ParamType>::Normalize() 00143 { 00144 float nTotalWeight = 0.0f; 00145 for(size_t i = 0; i < m_controllers.size(); i++) { 00146 nTotalWeight += *m_controllers[i].first; 00147 } 00148 00149 // Normalize 00150 for(size_t i = 0; i < m_controllers.size(); i++) { 00151 *m_controllers[i].first /= nTotalWeight; 00152 } 00153 } 00154 00155 template<class CntType, class ParamType> 00156 bool CControllerPriorityMixer<CntType, ParamType>::IsEmpty() 00157 { 00158 return m_controllers.empty(); 00159 } 00160 00161 template<class CntType, class ParamType> 00162 ParamType* CControllerPriorityMixer<CntType, ParamType>::GetParameter() 00163 { 00164 return &m_accumulated_param; 00165 } 00166 00167 /* 00168 Inherited 00169 */ 00170 template<class CntType, class ParamType> 00171 void CControllerPriorityMixer<CntType, ParamType>::Update(float dt) 00172 { 00173 float weight_remaining = 1.0f; // zbyvajici vaha, pokud nektery controller vypotrebuje vsechno (z 1.0f), na ostatni se jiz nedostane 00174 bool first = true; 00175 float curr_weight; 00176 00177 00178 for(size_t i = 0; i < m_controllers.size(); i++) { 00179 if(weight_remaining < 0.0f) break; 00180 00181 MIX_NODE& curr = m_controllers[i]; 00182 00183 // celkova vaha nesmi prekrocit 1 00184 if(weight_remaining - *curr.weight < 0.0f) { 00185 curr_weight = weight_remaining; 00186 } else { 00187 curr_weight = *curr.weight; 00188 } 00189 weight_remaining -= *curr.weight; 00190 // 00191 00192 if((*curr.weight) <= 0.0f) continue; 00193 00194 curr.controller->Update(dt); 00195 00196 if(first) { 00197 m_accumulated_param = (*curr.controller->GetParameter()) * (curr_weight); 00198 first = false; 00199 } else { 00200 m_accumulated_param += (*curr.controller->GetParameter()) * (curr_weight); 00201 } 00202 } 00203 if(!m_controllers.empty() && first == false) { 00204 *m_controllers[0].controller->GetParameter() = m_accumulated_param; 00205 } 00206 } 00207 00208 00209 00210 00211 00212 00213 00214 00215 00216 00217
1.8.0