Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wc/snap to terrain - CsvSpawner: Make "snap to terrain" based on collision layer. #74

Merged
merged 15 commits into from
Nov 12, 2024
Merged
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.vscode/**
.idea/**

Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,19 @@ namespace CsvSpawner
AZ::TickBus ::Handler::BusDisconnect();
}

int CsvSpawnerComponent::GetTickOrder()
{
return AZ::TICK_LAST;
}

void CsvSpawnerComponent::Activate()
{
AZ::TickBus ::Handler::BusConnect();
AZ::TickBus::Handler::BusConnect();
}

void CsvSpawnerComponent::Deactivate()
{
AZ::TickBus ::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
}

} // namespace CsvSpawner
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace CsvSpawner
private:
// AZ::TickBus::Handler overrides
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
int GetTickOrder() override;

AZStd::unordered_map<AZStd::string, CsvSpawnableAssetConfiguration> m_spawnableAssetConfigurations; //!< List of assets to spawn
AZStd::vector<CsvSpawnableEntityInfo> m_spawnableEntityInfo; //!< List of entities to spawn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
#include "CsvSpawnerComponent.h"
#include "CsvSpawnerCsvParser.h"
#include "CsvSpawnerUtils.h"

#include <AzCore/Component/TransformBus.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzFramework/Physics/Common/PhysicsTypes.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <thread>

namespace CsvSpawner
{
Expand Down Expand Up @@ -83,18 +85,15 @@ namespace CsvSpawner
AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
}

AZ::TickBus::QueueFunction(
[this]()
{
SpawnEntities();
});
AZ::TickBus::Handler::BusConnect();
}

void CsvSpawnerEditorComponent::Deactivate()
{
m_spawnedTickets.clear();

AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
AzToolsFramework::Components::EditorComponentBase::Deactivate();
}

Expand Down Expand Up @@ -122,6 +121,23 @@ namespace CsvSpawner
m_spawnedTickets.clear();
}

void CsvSpawnerEditorComponent::OnTick(float deltaTime, AZ::ScriptTimePoint time)
{
++m_frameCounter;

if (m_frameCounter == 2)
{
SpawnEntities();
AZ::TickBus::Handler::BusDisconnect();
m_frameCounter = 0;
}
}

int CsvSpawnerEditorComponent::GetTickOrder()
{
return AZ::TICK_LAST;
}

void CsvSpawnerEditorComponent::SpawnEntities()
{
if (m_csvAssetId.IsValid() == false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

#pragma once

#include "API/ToolsApplicationAPI.h"
#include "CsvSpawnerUtils.h"

#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Component/TickBus.h>
#include <AzFramework/Entity/EntityContextBus.h>
Expand All @@ -28,6 +30,7 @@ namespace CsvSpawner
class CsvSpawnerEditorComponent
: public AzToolsFramework::Components::EditorComponentBase
, protected AzFramework::ViewportDebugDisplayEventBus::Handler
, protected AZ::TickBus::Handler
{
public:
AZ_EDITOR_COMPONENT(CsvSpawnerEditorComponent, CsvSpawnerEditorComponentTypeId);
Expand All @@ -40,6 +43,8 @@ namespace CsvSpawner
void Activate() override;
void Deactivate() override;
void BuildGameEntity(AZ::Entity* gameEntity) override;
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
int GetTickOrder() override;

private:
// EntityDebugDisplayEventBus::Handler overrides
Expand All @@ -50,6 +55,7 @@ namespace CsvSpawner
void OnOnShowLabelsChanged();

void SpawnEntities();
int m_frameCounter;

AZStd::vector<CsvSpawnerUtils::CsvSpawnableAssetConfiguration>
m_spawnableAssetConfigurations; //!< List of spawnable "types" (e.g. pineCsv, oakTre, mapleCsv, etc.)
Expand Down
54 changes: 45 additions & 9 deletions Gems/CsvSpawner/Code/Source/CsvSpawner/CsvSpawnerUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
*
* This source code is protected under international copyright law. All rights
* reserved and protected by the copyright holders.
* This file is confidential and only available to authorized individuals with the
* permission of the copyright holders. If you encounter this file and do not have
* permission, please contact the copyright holders and delete this file.
* This file is confidential and only available to authorized individuals with
* the permission of the copyright holders. If you encounter this file and do
* not have permission, please contact the copyright holders and delete this
* file.
*/

#include "CsvSpawnerUtils.h"

#include "AzFramework/Physics/CollisionBus.h"

#include <AzCore/Asset/AssetSerializer.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
Expand Down Expand Up @@ -49,7 +53,8 @@ namespace CsvSpawner::CsvSpawnerUtils
->Field("PositionStdDev", &CsvSpawnableAssetConfiguration::m_positionStdDev)
->Field("RotationStdDev", &CsvSpawnableAssetConfiguration::m_rotationStdDev)
->Field("ScaleStdDev", &CsvSpawnableAssetConfiguration::m_scaleStdDev)
->Field("PlaceOnTerrain", &CsvSpawnableAssetConfiguration::m_placeOnTerrain);
->Field("PlaceOnTerrain", &CsvSpawnableAssetConfiguration::m_placeOnTerrain)
->Field("CollisionGroup", &CsvSpawnableAssetConfiguration::m_selectedCollisionGroup);

if (auto* editContext = serializeContext->GetEditContext())
{
Expand Down Expand Up @@ -78,15 +83,32 @@ namespace CsvSpawner::CsvSpawnerUtils
&CsvSpawnableAssetConfiguration::m_placeOnTerrain,
"Place on Terrain",
"Perform scene query raytrace to place on terrain")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &CsvSpawnableAssetConfiguration::OnPlaceOnTerrainChanged)
->DataElement(
AZ::Edit::UIHandlers::Default,
&CsvSpawnableAssetConfiguration::m_scaleStdDev,
"Scale Std. Dev.",
"Scale standard deviation, in meters");
"Scale standard deviation, in meters")
->DataElement(
AZ::Edit::UIHandlers::Default,
&CsvSpawnableAssetConfiguration::m_selectedCollisionGroup,
"Collision Group",
"To which collision group this target will be attached")
->Attribute(AZ::Edit::Attributes::ReadOnly, &CsvSpawnableAssetConfiguration::IsCollisionLayerEnabled);
}
}
}

bool CsvSpawnableAssetConfiguration::IsCollisionLayerEnabled() const
{
return !m_placeOnTerrain;
}

AZ::Crc32 CsvSpawnableAssetConfiguration::OnPlaceOnTerrainChanged()
{
return AZ::Edit::PropertyRefreshLevels::EntireTree;
}

AZStd::unordered_map<AZStd::string, CsvSpawnableAssetConfiguration> GetSpawnableAssetFromVector(
AZStd::vector<CsvSpawnableAssetConfiguration> spawnableAssetConfigurations)
{
Expand Down Expand Up @@ -127,10 +149,15 @@ namespace CsvSpawner::CsvSpawnerUtils
}

AZStd::optional<AZ::Vector3> RaytraceTerrain(
const AZ::Vector3& location, const AzPhysics::SceneHandle sceneHandle, const AZ::Vector3& gravityDirection, float maxDistance)
const AZ::Vector3& location,
const AzPhysics::SceneHandle sceneHandle,
const AZ::Vector3& gravityDirection,
float maxDistance,
const AzPhysics::CollisionGroup& collisionGroup)
{
AZStd::optional<AZ::Vector3> hitPosition = AZStd::nullopt;

AZ_Assert(sceneHandle == AzPhysics::InvalidSceneHandle, "Unable to get scene handle");
if (sceneHandle == AzPhysics::InvalidSceneHandle)
michalpelka marked this conversation as resolved.
Show resolved Hide resolved
{
return hitPosition;
Expand All @@ -150,6 +177,7 @@ namespace CsvSpawner::CsvSpawnerUtils
request.m_start = location;
request.m_direction = gravityDirection;
request.m_distance = maxDistance;
request.m_collisionGroup = collisionGroup;

AzPhysics::SceneQueryHits result = sceneInterface->QueryScene(sceneHandle, &request);

Expand Down Expand Up @@ -211,21 +239,29 @@ namespace CsvSpawner::CsvSpawnerUtils

if (spawnConfig.m_placeOnTerrain)
{
// Get collision group chosen from editor
AzPhysics::CollisionGroup collisionGroup;
Physics::CollisionRequestBus::BroadcastResult(
collisionGroup, &Physics::CollisionRequests::GetCollisionGroupById, spawnConfig.m_selectedCollisionGroup);

const AZStd::optional<AZ::Vector3> hitPosition =
RaytraceTerrain(transform.GetTranslation(), sceneHandle, -AZ::Vector3::CreateAxisZ(), 1000.0f);
RaytraceTerrain(transform.GetTranslation(), sceneHandle, -AZ::Vector3::CreateAxisZ(), 1000.0f, collisionGroup);

if (hitPosition.has_value())
{
transform.SetTranslation(hitPosition.value());
}
else
{
continue; // Skip this entity if we can't find a valid position and place on terrain is enabled.
continue; // Skip this entity if we can't find a valid position and
// place on terrain is enabled.
}
}
AZ_Assert(spawner, "Unable to get spawnable entities definition");
AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs;
AzFramework::EntitySpawnTicket ticket(spawnable);
// Set the pre-spawn callback to set the name of the root entity to the name of the spawnable
// Set the pre-spawn callback to set the name of the root entity to the name
// of the spawnable
optionalArgs.m_preInsertionCallback = [transform](auto id, auto view)
{
if (view.empty())
Expand Down
48 changes: 32 additions & 16 deletions Gems/CsvSpawner/Code/Source/CsvSpawner/CsvSpawnerUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
*
* This source code is protected under international copyright law. All rights
* reserved and protected by the copyright holders.
* This file is confidential and only available to authorized individuals with the
* permission of the copyright holders. If you encounter this file and do not have
* permission, please contact the copyright holders and delete this file.
* This file is confidential and only available to authorized individuals with
* the permission of the copyright holders. If you encounter this file and do
* not have permission, please contact the copyright holders and delete this
* file.
*/

#pragma once

#include "AzFramework/Physics/Collision/CollisionGroups.h"
#include "AzFramework/Physics/Collision/CollisionLayers.h"
#include "CsvSpawner/CsvSpawnerTypeIds.h"

#include <AzCore/Asset/AssetCommon.h>
Expand All @@ -24,8 +27,8 @@ namespace CsvSpawner::CsvSpawnerUtils

//! Information about a locations to spawn an entity.
//! This information is generated from CSV file and is used to spawn the entity.
//! @param m_name is the name of the spawnable entity configuration and should be identical to name in @class
//! SpawnableAssetConfiguration.
//! @param m_name is the name of the spawnable entity configuration and should
//! be identical to name in @class SpawnableAssetConfiguration.
class CsvSpawnableEntityInfo
{
public:
Expand All @@ -37,15 +40,18 @@ namespace CsvSpawner::CsvSpawnerUtils
unsigned int m_id; //!< Optional ID for the entity
AZ::Transform m_transform; //!< Transform of the entity, mandatory
AZStd::string m_name; //!< Name of the spawnable entity configuration, mandatory
uint64_t m_seed{ 0 }; //!< Optional seed value for randomization, in the context of one spawnable entity configuration, optional
uint64_t m_seed{ 0 }; //!< Optional seed value for randomization, in the context
//!< of one spawnable entity configuration, optional
};

//! Configuration for a spawnable asset
//! This configuration is used to configure the spawnable asset before spawning it.
//! The @param m_name is used to identify the spawnable asset configuration and should be identical to name given in CSV file.
//! The class allows user to specify multiple spawnable assets for a given name and randomization parameters for position, rotation and
//! scale. If more then one spawnable asset is specified for a given name, then one of the spawnable assets is randomly selected for
//! spawning.
//! This configuration is used to configure the spawnable asset before spawning
//! it. The @param m_name is used to identify the spawnable asset configuration
//! and should be identical to name given in CSV file. The class allows user to
//! specify multiple spawnable assets for a given name and randomization
//! parameters for position, rotation and scale. If more then one spawnable
//! asset is specified for a given name, then one of the spawnable assets is
//! randomly selected for spawning.
class CsvSpawnableAssetConfiguration
{
public:
Expand All @@ -59,12 +65,21 @@ namespace CsvSpawner::CsvSpawnerUtils
AZ::Vector3 m_positionStdDev{ 0.f }; //!< Standard deviation for position
AZ::Vector3 m_rotationStdDev{ 0.f }; //!< Standard deviation for rotation
float m_scaleStdDev{ 0.1f }; //!< Standard deviation for scale
bool m_placeOnTerrain{ false }; //!< Whether to raytrace to terrain and place the entity on the terrain
bool m_placeOnTerrain{ false }; //!< Whether to raytrace to terrain and place
//!< the entity on the terrain
AzPhysics::CollisionGroups::Id m_selectedCollisionGroup; //!< To which collision group this target will
//!< be attached

private:
[[nodiscard]] bool IsCollisionLayerEnabled() const;
static AZ::Crc32 OnPlaceOnTerrainChanged();
};

//! This function create map of spawnable asset configuration from vector of spawnable asset configuration, where
//! the key is the name of the spawnable asset configuration
//! @param spawnableAssetConfigurations - vector of spawnable asset configuration
//! This function create map of spawnable asset configuration from vector of
//! spawnable asset configuration, where the key is the name of the spawnable
//! asset configuration
//! @param spawnableAssetConfigurations - vector of spawnable asset
//! configuration
//! @return map of spawnable asset configuration
AZStd::unordered_map<AZStd::string, CsvSpawnableAssetConfiguration> GetSpawnableAssetFromVector(
AZStd::vector<CsvSpawnableAssetConfiguration> spawnableAssetConfigurations);
Expand All @@ -74,7 +89,8 @@ namespace CsvSpawner::CsvSpawnerUtils
//! @param spawnableAssetConfiguration - map of spawnable asset configuration
//! @param defaultSeed - default seed value
//! @param parentId - parent entity id to set for new entities
//! @param physicsSceneName - physics scene name (AzPhysics::DefaultPhysicsSceneName or AzPhysics::EditorPhysicsSceneName)
//! @param physicsSceneName - physics scene name
//! (AzPhysics::DefaultPhysicsSceneName or AzPhysics::EditorPhysicsSceneName)
//! @return map of spawn created tickets
AZStd::unordered_map<int, AzFramework::EntitySpawnTicket> SpawnEntities(
const AZStd::vector<CsvSpawnableEntityInfo>& entitiesToSpawn,
Expand Down