diff --git a/src/xrEngine/CameraManager.cpp b/src/xrEngine/CameraManager.cpp index d53017ec3a5..4d9b1ce042e 100644 --- a/src/xrEngine/CameraManager.cpp +++ b/src/xrEngine/CameraManager.cpp @@ -86,7 +86,7 @@ void CCameraManager::UpdateDeffered() RemoveCamEffector((*it)->eType); if ((*it)->AbsolutePositioning()) - m_EffectorsCam.insert(m_EffectorsCam.begin(), *it); + m_EffectorsCam.push_front(*it); else m_EffectorsCam.push_back(*it); } @@ -222,23 +222,19 @@ void CCameraManager::Update(const Fvector& P, const Fvector& D, const Fvector& N bool CCameraManager::ProcessCameraEffector(CEffectorCam* eff) { + // Do NOT delete effector here! It's unsafe because: + // 1. Leads to failed iterators in UpdateCamEffectors + // 2. Child classes with overrided ProcessCameraEffector would be surprised if eff becames invalid pointer + // The best way - return 'false' when the effector should be deleted, and delete it in ProcessCameraEffector + bool res = false; if (eff->Valid() && eff->ProcessCam(m_cam_info)) { res = true; } - else + else if (eff->AllowProcessingIfInvalid()) { - if (eff->AllowProcessingIfInvalid()) - { - eff->ProcessIfInvalid(m_cam_info); - res = true; - } - - EffectorCamVec::iterator it = std::find(m_EffectorsCam.begin(), m_EffectorsCam.end(), eff); - - m_EffectorsCam.erase(it); - OnEffectorReleased(eff); + eff->ProcessIfInvalid(m_cam_info); } return res; } @@ -247,8 +243,22 @@ void CCameraManager::UpdateCamEffectors() { if (m_EffectorsCam.empty()) return; - for (int i = m_EffectorsCam.size() - 1; i >= 0; --i) - ProcessCameraEffector(m_EffectorsCam[i]); + + auto r_it = m_EffectorsCam.rbegin(); + while (r_it != m_EffectorsCam.rend()) + { + if (ProcessCameraEffector(*r_it)) + ++r_it; + else + { + // Dereferencing reverse iterator returns previous element of the list, r_it.base() returns current element + // So, we should use base()-1 iterator to delete just processed element. 'Previous' element would be + // automatically changed after deletion, so r_it would dereferencing to another value, no need to change it + OnEffectorReleased(*r_it); + auto r_to_del = r_it.base(); + m_EffectorsCam.erase(--r_to_del); + } + } m_cam_info.d.normalize(); m_cam_info.n.normalize(); diff --git a/src/xrEngine/CameraManager.h b/src/xrEngine/CameraManager.h index d69bd6a0ea4..6d5ccdeec5a 100644 --- a/src/xrEngine/CameraManager.h +++ b/src/xrEngine/CameraManager.h @@ -3,7 +3,7 @@ #include "CameraDefs.h" #include "xrCore/PostProcess/PPInfo.hpp" -using EffectorCamVec = xr_vector; +using EffectorCamVec = xr_list; using EffectorPPVec = xr_vector; #define effCustomEffectorStartID 10000