mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-05-02 02:23:56 +00:00
Fix crash when performer's child ROIs are left dangling in ScenePlayer
NotifyROIDestroyed now walks the parent chain to also invalidate child ROIs of the destroyed performer (head, limbs, etc.) that were placed into the roiMap by BuildROIMap. The ancestor walk happens once; all other fields are cleaned with simple pointer equality.
This commit is contained in:
parent
3cf1a38600
commit
ac4cd6b979
@ -594,38 +594,66 @@ void ScenePlayer::NotifyROIDestroyed(LegoROI* p_roi)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& p : m_participants) {
|
// Walk the m_roiMap once to find p_roi and all its descendants (child ROIs
|
||||||
if (p.roi == p_roi) {
|
// are destroyed together with their parent). Collect them so every other
|
||||||
p.roi = nullptr;
|
// field can be cleaned with simple pointer equality — the ancestor walk
|
||||||
}
|
// happens in exactly one place.
|
||||||
if (p.vehicleROI == p_roi) {
|
std::vector<LegoROI*> destroyed;
|
||||||
p.vehicleROI = nullptr;
|
destroyed.push_back(p_roi);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_roiMap) {
|
if (m_roiMap) {
|
||||||
for (MxU32 i = 0; i < m_roiMapSize; i++) {
|
for (MxU32 i = 0; i < m_roiMapSize; i++) {
|
||||||
if (m_roiMap[i] == p_roi) {
|
if (!m_roiMap[i]) {
|
||||||
m_roiMap[i] = nullptr;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (OrientableROI* cur = m_roiMap[i]; cur != nullptr; cur = cur->GetParentROI()) {
|
||||||
|
if (cur == p_roi) {
|
||||||
|
if (m_roiMap[i] != p_roi) {
|
||||||
|
destroyed.push_back(m_roiMap[i]);
|
||||||
|
}
|
||||||
|
m_roiMap[i] = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto isDestroyed = [&destroyed](LegoROI* roi) {
|
||||||
|
for (LegoROI* d : destroyed) {
|
||||||
|
if (roi == d) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto& p : m_participants) {
|
||||||
|
if (p.roi && isDestroyed(p.roi)) {
|
||||||
|
p.roi = nullptr;
|
||||||
|
}
|
||||||
|
if (p.vehicleROI && isDestroyed(p.vehicleROI)) {
|
||||||
|
p.vehicleROI = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& roi : m_ptAtCamROIs) {
|
for (auto& roi : m_ptAtCamROIs) {
|
||||||
if (roi == p_roi) {
|
if (roi && isDestroyed(roi)) {
|
||||||
roi = nullptr;
|
roi = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_animRootROI == p_roi) {
|
if (m_animRootROI && isDestroyed(m_animRootROI)) {
|
||||||
m_animRootROI = nullptr;
|
m_animRootROI = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_vehicleROI == p_roi) {
|
if (m_vehicleROI && isDestroyed(m_vehicleROI)) {
|
||||||
m_vehicleROI = nullptr;
|
m_vehicleROI = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_phonemePlayer.NotifyROIDestroyed(p_roi);
|
for (LegoROI* d : destroyed) {
|
||||||
|
m_phonemePlayer.NotifyROIDestroyed(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScenePlayer::CleanupProps()
|
void ScenePlayer::CleanupProps()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user