Added terrain surface data notifications (#5067)
* Fix notifications for surface data changes. Separated the notifications from the surface component and the height component to add a reason to a RefreshArea request. This makes it possible to distinguish between surface changes and height changes and provide the appropriate OnTerrainDataChanged flags. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Reworked to use a changeMask instead of separate calls. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * PR Feedback Judicious use of "using" to reduce a bunch of bulky namespaces. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>
This commit is contained in:
@@ -76,6 +76,7 @@ void TerrainSystem::Activate()
|
||||
m_dirtyRegion = AZ::Aabb::CreateNull();
|
||||
m_terrainHeightDirty = true;
|
||||
m_terrainSettingsDirty = true;
|
||||
m_terrainSurfacesDirty = true;
|
||||
m_requestedSettings.m_systemActive = true;
|
||||
|
||||
{
|
||||
@@ -115,6 +116,7 @@ void TerrainSystem::Deactivate()
|
||||
m_dirtyRegion = AZ::Aabb::CreateNull();
|
||||
m_terrainHeightDirty = true;
|
||||
m_terrainSettingsDirty = true;
|
||||
m_terrainSurfacesDirty = true;
|
||||
m_requestedSettings.m_systemActive = false;
|
||||
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Broadcast(
|
||||
@@ -549,6 +551,7 @@ void TerrainSystem::RegisterArea(AZ::EntityId areaId)
|
||||
m_registeredAreas[areaId] = aabb;
|
||||
m_dirtyRegion.AddAabb(aabb);
|
||||
m_terrainHeightDirty = true;
|
||||
m_terrainSurfacesDirty = true;
|
||||
}
|
||||
|
||||
void TerrainSystem::UnregisterArea(AZ::EntityId areaId)
|
||||
@@ -567,14 +570,17 @@ void TerrainSystem::UnregisterArea(AZ::EntityId areaId)
|
||||
{
|
||||
m_dirtyRegion.AddAabb(aabb);
|
||||
m_terrainHeightDirty = true;
|
||||
m_terrainSurfacesDirty = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void TerrainSystem::RefreshArea(AZ::EntityId areaId)
|
||||
void TerrainSystem::RefreshArea(AZ::EntityId areaId, AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask changeMask)
|
||||
{
|
||||
using Terrain = AzFramework::Terrain::TerrainDataNotifications;
|
||||
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
|
||||
|
||||
auto areaAabb = m_registeredAreas.find(areaId);
|
||||
@@ -588,11 +594,18 @@ void TerrainSystem::RefreshArea(AZ::EntityId areaId)
|
||||
expandedAabb.AddAabb(newAabb);
|
||||
|
||||
m_dirtyRegion.AddAabb(expandedAabb);
|
||||
m_terrainHeightDirty = true;
|
||||
|
||||
// Keep track of which types of data have changed so that we can send out the appropriate notifications later.
|
||||
|
||||
m_terrainHeightDirty = m_terrainHeightDirty || ((changeMask & Terrain::HeightData) == Terrain::HeightData);
|
||||
|
||||
m_terrainSurfacesDirty = m_terrainSurfacesDirty || ((changeMask & Terrain::SurfaceData) == Terrain::SurfaceData);
|
||||
}
|
||||
|
||||
void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
|
||||
{
|
||||
using Terrain = AzFramework::Terrain::TerrainDataNotifications;
|
||||
|
||||
bool terrainSettingsChanged = false;
|
||||
|
||||
if (m_terrainSettingsDirty)
|
||||
@@ -607,6 +620,7 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
|
||||
m_dirtyRegion = m_currentSettings.m_worldBounds;
|
||||
m_dirtyRegion.AddAabb(m_requestedSettings.m_worldBounds);
|
||||
m_terrainHeightDirty = true;
|
||||
m_terrainSurfacesDirty = true;
|
||||
m_currentSettings.m_worldBounds = m_requestedSettings.m_worldBounds;
|
||||
}
|
||||
|
||||
@@ -614,12 +628,13 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
|
||||
{
|
||||
m_dirtyRegion = AZ::Aabb::CreateNull();
|
||||
m_terrainHeightDirty = true;
|
||||
m_terrainSurfacesDirty = true;
|
||||
}
|
||||
|
||||
m_currentSettings = m_requestedSettings;
|
||||
}
|
||||
|
||||
if (terrainSettingsChanged || m_terrainHeightDirty)
|
||||
if (terrainSettingsChanged || m_terrainHeightDirty || m_terrainSurfacesDirty)
|
||||
{
|
||||
// Block other threads from accessing the surface data bus while we are in GetValue (which may call into the SurfaceData bus).
|
||||
// We lock our surface data mutex *before* checking / setting "isRequestInProgress" so that we prevent race conditions
|
||||
@@ -629,24 +644,27 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
|
||||
auto& surfaceDataContext = SurfaceData::SurfaceDataSystemRequestBus::GetOrCreateContext(false);
|
||||
typename SurfaceData::SurfaceDataSystemRequestBus::Context::DispatchLockGuard scopeLock(surfaceDataContext.m_contextMutex);
|
||||
|
||||
AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask changeMask =
|
||||
AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask::None;
|
||||
Terrain::TerrainDataChangedMask changeMask = Terrain::TerrainDataChangedMask::None;
|
||||
|
||||
if (terrainSettingsChanged)
|
||||
{
|
||||
changeMask = static_cast<AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask>(
|
||||
changeMask | AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask::Settings);
|
||||
changeMask = static_cast<Terrain::TerrainDataChangedMask>(changeMask | Terrain::TerrainDataChangedMask::Settings);
|
||||
}
|
||||
if (m_terrainHeightDirty)
|
||||
{
|
||||
changeMask = static_cast<AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask>(
|
||||
changeMask | AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask::HeightData);
|
||||
changeMask = static_cast<Terrain::TerrainDataChangedMask>(changeMask | Terrain::TerrainDataChangedMask::HeightData);
|
||||
}
|
||||
|
||||
if (m_terrainSurfacesDirty)
|
||||
{
|
||||
changeMask = static_cast<Terrain::TerrainDataChangedMask>(changeMask | Terrain::TerrainDataChangedMask::SurfaceData);
|
||||
}
|
||||
|
||||
// Make sure to set these *before* calling OnTerrainDataChanged, since it's possible that subsystems reacting to that call will
|
||||
// cause the data to become dirty again.
|
||||
AZ::Aabb dirtyRegion = m_dirtyRegion;
|
||||
m_terrainHeightDirty = false;
|
||||
m_terrainSurfacesDirty = false;
|
||||
m_dirtyRegion = AZ::Aabb::CreateNull();
|
||||
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Broadcast(
|
||||
|
||||
Reference in New Issue
Block a user