Merge branch 'main' into mp_session_integ

This commit is contained in:
puvvadar
2021-06-07 13:46:18 -07:00
310 changed files with 16119 additions and 5290 deletions
@@ -28,7 +28,13 @@ namespace AZ
{
namespace IdUtils
{
template<typename IdType>
/**
* \param AllowDuplicates - If true allows the same id to be registered multiple times,
with the newer value overwriting the stored value. If false, duplicates are not allowed and
the first stored value is kept.The default is false.
*/
template<typename IdType, bool AllowDuplicates = false>
struct Remapper
{
/**
@@ -138,14 +144,18 @@ namespace AZ
* \param context - The serialize context for enumerating the @classPtr elements
*/
template<typename T, typename MapType>
static void GenerateNewIdsAndFixRefs(T* object, MapType& newIdMap, AZ::SerializeContext* context = nullptr)
static void GenerateNewIdsAndFixRefs(
T* object, MapType& newIdMap, AZ::SerializeContext* context = nullptr)
{
if (!context)
{
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext);
if (!context)
{
AZ_Error("Serialization", false, "No serialize context provided! Failed to get component application default serialize context! ComponentApp is not started or input serialize context should not be null!");
AZ_Error(
"Serialization", false,
"No serialize context provided! Failed to get component application default serialize context! ComponentApp is "
"not started or input serialize context should not be null!");
return;
}
}
@@ -156,8 +166,16 @@ namespace AZ
{
if (idGenerator)
{
auto it = newIdMap.emplace(originalId, idGenerator());
return it.first->second;
if constexpr(AllowDuplicates)
{
auto it = newIdMap.insert_or_assign(originalId, idGenerator());
return it.first->second;
}
else
{
auto it = newIdMap.emplace(originalId, idGenerator());
return it.first->second;
}
}
return originalId;
}
@@ -30,8 +30,10 @@ namespace AZ
bool m_isModifiedContainer;
};
template<typename IdType>
unsigned int Remapper<IdType>::RemapIds(void* classPtr, const AZ::Uuid& classUuid, const typename Remapper<IdType>::IdMapper& mapper, AZ::SerializeContext* context, bool replaceId)
template<typename IdType, bool AllowDuplicates>
unsigned int Remapper<IdType, AllowDuplicates>::RemapIds(
void* classPtr, const AZ::Uuid& classUuid, const typename Remapper<IdType, AllowDuplicates>::IdMapper& mapper,
AZ::SerializeContext* context, bool replaceId)
{
if (!context)
{
@@ -152,16 +154,18 @@ namespace AZ
return replaced;
}
template<typename IdType>
unsigned int Remapper<IdType>::ReplaceIdsAndIdRefs(void* classPtr, const AZ::Uuid& classUuid, const IdMapper& mapper, AZ::SerializeContext* context /*= nullptr*/)
template<typename IdType, bool AllowDuplicates>
unsigned int Remapper<IdType, AllowDuplicates>::ReplaceIdsAndIdRefs(void* classPtr, const AZ::Uuid& classUuid, const IdMapper& mapper, AZ::SerializeContext* context /*= nullptr*/)
{
unsigned int replaced = RemapIds(classPtr, classUuid, mapper, context, true);
replaced += RemapIds(classPtr, classUuid, mapper, context, false);
return replaced;
}
template<typename IdType>
unsigned int Remapper<IdType>::RemapIdsAndIdRefs(void* classPtr, const AZ::Uuid& classUuid, const typename Remapper<IdType>::IdReplacer& mapper, AZ::SerializeContext* context)
template<typename IdType, bool AllowDuplicates>
unsigned int Remapper<IdType, AllowDuplicates>::RemapIdsAndIdRefs(
void* classPtr, const AZ::Uuid& classUuid, const typename Remapper<IdType, AllowDuplicates>::IdReplacer& mapper,
AZ::SerializeContext* context)
{
if (!context)
{
+3
View File
@@ -21,11 +21,14 @@ namespace AZStd
using std::asin;
using std::atan;
using std::atan2;
using std::ceil;
using std::cos;
using std::exp2;
using std::floor;
using std::fmod;
using std::round;
using std::sin;
using std::sqrt;
using std::tan;
using std::trunc;
} // namespace AZStd
@@ -14,6 +14,9 @@
#include <sys/syslimits.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <AzCore/std/typetraits/underlying_type.h>
namespace AZ
{
@@ -1681,13 +1681,11 @@ namespace AZ::IO
AZStd::vector<AZStd::string> files;
do
{
if (AZStd::wildcard_match(pWildcardIn, fileIterator.m_filename))
{
AZStd::string foundFilename{ fileIterator.m_filename };
AZStd::to_lower(foundFilename.begin(), foundFilename.end());
files.emplace_back(AZStd::move(foundFilename));
}
} while (fileIterator = FindNext(fileIterator));
AZStd::string foundFilename{ fileIterator.m_filename };
AZStd::to_lower(foundFilename.begin(), foundFilename.end());
files.emplace_back(AZStd::move(foundFilename));
}
while (fileIterator = FindNext(fileIterator));
// Open files in alphabet order.
AZStd::sort(files.begin(), files.end());
@@ -38,20 +38,20 @@ namespace AzFramework
void SpawnableEntitiesContainer::SpawnAllEntities()
{
AZ_Assert(m_threadData, "Calling SpawnAllEntities on a Spawnable container that's not set.");
SpawnableEntitiesInterface::Get()->SpawnAllEntities(m_threadData->m_spawnedEntitiesTicket, SpawnablePriority_Default);
SpawnableEntitiesInterface::Get()->SpawnAllEntities(m_threadData->m_spawnedEntitiesTicket);
}
void SpawnableEntitiesContainer::SpawnEntities(AZStd::vector<size_t> entityIndices)
{
AZ_Assert(m_threadData, "Calling SpawnEntities on a Spawnable container that's not set.");
SpawnableEntitiesInterface::Get()->SpawnEntities(
m_threadData->m_spawnedEntitiesTicket, SpawnablePriority_Default, AZStd::move(entityIndices));
m_threadData->m_spawnedEntitiesTicket, AZStd::move(entityIndices));
}
void SpawnableEntitiesContainer::DespawnAllEntities()
{
AZ_Assert(m_threadData, "Calling DespawnEntities on a Spawnable container that's not set.");
SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_threadData->m_spawnedEntitiesTicket, SpawnablePriority_Default);
SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_threadData->m_spawnedEntitiesTicket);
}
void SpawnableEntitiesContainer::Reset(AZ::Data::Asset<Spawnable> spawnable)
@@ -69,7 +69,6 @@ namespace AzFramework
SpawnableEntitiesInterface::Get()->Barrier(
m_threadData->m_spawnedEntitiesTicket,
SpawnablePriority_Default,
[threadData = m_threadData](EntitySpawnTicket::Id) mutable
{
threadData.reset();
@@ -88,7 +87,6 @@ namespace AzFramework
AZ_Assert(m_threadData, "Calling DespawnEntities on a Spawnable container that's not set.");
SpawnableEntitiesInterface::Get()->Barrier(
m_threadData->m_spawnedEntitiesTicket,
SpawnablePriority_Default,
[generation = m_threadData->m_generation, callback = AZStd::move(callback)](EntitySpawnTicket::Id)
{
callback(generation);
@@ -115,7 +113,6 @@ namespace AzFramework
AZ_Assert(m_threadData, "SpawnableEntitiesContainer is monitoring a spawnable, but doesn't have the associated data.");
AZ_TracePrintf("Spawnables", "Reloading spawnable '%s'.\n", replacementAsset.GetHint().c_str());
SpawnableEntitiesInterface::Get()->ReloadSpawnable(
m_threadData->m_spawnedEntitiesTicket, SpawnablePriority_Default, AZStd::move(replacementAsset));
SpawnableEntitiesInterface::Get()->ReloadSpawnable(m_threadData->m_spawnedEntitiesTicket, AZStd::move(replacementAsset));
}
} // namespace AzFramework
@@ -21,6 +21,7 @@
namespace AZ
{
class Entity;
class SerializeContext;
}
namespace AzFramework
@@ -171,6 +172,77 @@ namespace AzFramework
using ClaimEntitiesCallback = AZStd::function<void(EntitySpawnTicket::Id, SpawnableEntityContainerView)>;
using BarrierCallback = AZStd::function<void(EntitySpawnTicket::Id)>;
struct SpawnAllEntitiesOptionalArgs final
{
//! Callback that's called after instances of entities have been created, but before they're spawned into the world. This
//! gives the opportunity to modify the entities if needed such as injecting additional components or modifying components.
EntityPreInsertionCallback m_preInsertionCallback;
//! Callback that's called when spawning entities has completed. This can be triggered from a different thread than the one that
//! made the function call to spawn. The returned list of entities contains all the newly created entities.
EntitySpawnCallback m_completionCallback;
//! The Serialize Context used to clone entities with. If this is not provided the global Serialize Contetx will be used.
AZ::SerializeContext* m_serializeContext { nullptr };
//! The priority at which this call will be executed.
SpawnablePriority m_priority { SpawnablePriority_Default };
};
struct SpawnEntitiesOptionalArgs final
{
//! Callback that's called after instances of entities have been created, but before they're spawned into the world. This
//! gives the opportunity to modify the entities if needed such as injecting additional components or modifying components.
EntityPreInsertionCallback m_preInsertionCallback;
//! Callback that's called when spawning entities has completed. This can be triggered from a different thread than the one that
//! made the function call to spawn. The returned list of entities contains all the newly created entities.
EntitySpawnCallback m_completionCallback;
//! The Serialize Context used to clone entities with. If this is not provided the global Serialize Contetx will be used.
AZ::SerializeContext* m_serializeContext{ nullptr };
//! The priority at which this call will be executed.
SpawnablePriority m_priority{ SpawnablePriority_Default };
//! Entity references are resolved by referring to the last entity spawned from a template entity in the spawnable. If this
//! is set to false entities from previous spawn calls are not taken into account. If set to true entity references may be
//! resolved to a previously spawned entity. A lookup table has to be constructed when true, which may negatively impact
//! performance, especially if a large number of entities are present on a ticket.
bool m_referencePreviouslySpawnedEntities{ false };
};
struct DespawnAllEntitiesOptionalArgs final
{
//! Callback that's called when despawning entities has completed. This can be triggered from a different thread than the one that
//! made the function call to despawn. The returned list of entities contains all the newly created entities.
EntityDespawnCallback m_completionCallback;
//! The priority at which this call will be executed.
SpawnablePriority m_priority { SpawnablePriority_Default };
};
struct ReloadSpawnableOptionalArgs final
{
//! Callback that's called when respawning entities has completed. This can be triggered from a different thread than the one that
//! made the function call to respawn. The returned list of entities contains all the newly created entities.
ReloadSpawnableCallback m_completionCallback;
//! The Serialize Context used to clone entities with. If this is not provided the global Serialize Context will be used.
AZ::SerializeContext* m_serializeContext { nullptr };
//! The priority at which this call will be executed.
SpawnablePriority m_priority { SpawnablePriority_Default };
};
struct ListEntitiesOptionalArgs final
{
//! The priority at which this call will be executed.
SpawnablePriority m_priority{ SpawnablePriority_Default };
};
struct ClaimEntitiesOptionalArgs final
{
//! The priority at which this call will be executed.
SpawnablePriority m_priority{ SpawnablePriority_Default };
};
struct BarrierOptionalArgs final
{
//! The priority at which this call will be executed.
SpawnablePriority m_priority{ SpawnablePriority_Default };
};
//! Interface definition to (de)spawn entities from a spawnable into the game world.
//!
//! While the callbacks of the individual calls are being processed they will block processing any other request. Callbacks can be
@@ -196,47 +268,34 @@ namespace AzFramework
//! Spawn instances of all entities in the spawnable.
//! @param ticket Stores the results of the call. Use this ticket to spawn additional entities or to despawn them.
//! @param priority The priority at which this call will be executed.
//! @param completionCallback Optional callback that's called when spawning entities has completed. This can be called from
//! a different thread than the one that made the function call. The returned list of entities contains all the newly
//! created entities.
virtual void SpawnAllEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, EntityPreInsertionCallback preInsertionCallback = {},
EntitySpawnCallback completionCallback = {}) = 0;
//! @param optionalArgs Optional additional arguments, see SpawnAllEntitiesOptionalArgs.
virtual void SpawnAllEntities(EntitySpawnTicket& ticket, SpawnAllEntitiesOptionalArgs optionalArgs = {}) = 0;
//! Spawn instances of some entities in the spawnable.
//! @param ticket Stores the results of the call. Use this ticket to spawn additional entities or to despawn them.
//! @param priority The priority at which this call will be executed.
//! @param entityIndices The indices into the template entities stored in the spawnable that will be used to spawn entities from.
//! @param completionCallback Optional callback that's called when spawning entities has completed. This can be called from
//! a different thread than the one that made this function call. The returned list of entities contains all the newly
//! created entities.
//! @param optionalArgs Optional additional arguments, see SpawnEntitiesOptionalArgs.
virtual void SpawnEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, AZStd::vector<size_t> entityIndices,
EntityPreInsertionCallback preInsertionCallback = {}, EntitySpawnCallback completionCallback = {}) = 0;
EntitySpawnTicket& ticket, AZStd::vector<size_t> entityIndices, SpawnEntitiesOptionalArgs optionalArgs = {}) = 0;
//! Removes all entities in the provided list from the environment.
//! @param ticket The ticket previously used to spawn entities with.
//! @param priority The priority at which this call will be executed.
//! @param completionCallback Optional callback that's called when despawning entities has completed. This can be called from
//! a different thread than the one that made this function call.
virtual void DespawnAllEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, EntityDespawnCallback completionCallback = {}) = 0;
//! @param optionalArgs Optional additional arguments, see DespawnAllEntitiesOptionalArgs.
virtual void DespawnAllEntities(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs = {}) = 0;
//! Removes all entities in the provided list from the environment and reconstructs the entities from the provided spawnable.
//! @param ticket Holds the information on the entities to reload.
//! @param priority The priority at which this call will be executed.
//! @param spawnable The spawnable that will replace the existing spawnable. Both need to have the same asset id.
//! @param completionCallback Optional callback that's called when the entities have been reloaded. This can be called from
//! a different thread than the one that made this function call. The returned list of entities contains all the replacement
//! entities.
//! @param optionalArgs Optional additional arguments, see ReloadSpawnableOptionalArgs.
virtual void ReloadSpawnable(
EntitySpawnTicket& ticket, SpawnablePriority priority, AZ::Data::Asset<Spawnable> spawnable,
ReloadSpawnableCallback completionCallback = {}) = 0;
EntitySpawnTicket& ticket, AZ::Data::Asset<Spawnable> spawnable, ReloadSpawnableOptionalArgs optionalArgs = {}) = 0;
//! List all entities that are spawned using this ticket.
//! @param ticket Only the entities associated with this ticket will be listed.
//! @param priority The priority at which this call will be executed.
//! @param listCallback Required callback that will be called to list the entities on.
virtual void ListEntities(EntitySpawnTicket& ticket, SpawnablePriority priority, ListEntitiesCallback listCallback) = 0;
//! @param optionalArgs Optional additional arguments, see ListEntitiesOptionalArgs.
virtual void ListEntities(
EntitySpawnTicket& ticket, ListEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs = {}) = 0;
//! List all entities that are spawned using this ticket with their spawnable index.
//! Spawnables contain a flat list of entities, which are used as templates to spawn entities from. For every spawned entity
//! the index of the entity in the spawnable that was used as a template is stored. This version of ListEntities will return
@@ -244,23 +303,24 @@ namespace AzFramework
//! the same index may appear multiple times as there are no restriction on how many instance of a specific entity can be
//! created.
//! @param ticket Only the entities associated with this ticket will be listed.
//! @param priority The priority at which this call will be executed.
//! @param listCallback Required callback that will be called to list the entities and indices on.
//! @param optionalArgs Optional additional arguments, see ListEntitiesOptionalArgs.
virtual void ListIndicesAndEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, ListIndicesEntitiesCallback listCallback) = 0;
EntitySpawnTicket& ticket, ListIndicesEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs = {}) = 0;
//! Claim all entities that are spawned using this ticket. Ownership of the entities is transferred from the ticket to the
//! caller through the callback. After this call the ticket will have no entities associated with it. The caller of
//! this function will need to manage the entities after this call.
//! @param ticket Only the entities associated with this ticket will be released.
//! @param priority The priority at which this call will be executed.
//! @param listCallback Required callback that will be called to transfer the entities through.
virtual void ClaimEntities(EntitySpawnTicket& ticket, SpawnablePriority priority, ClaimEntitiesCallback listCallback) = 0;
//! @param optionalArgs Optional additional arguments, see ClaimEntitiesOptionalArgs.
virtual void ClaimEntities(
EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback, ClaimEntitiesOptionalArgs optionalArgs = {}) = 0;
//! Blocks until all operations made on the provided ticket before the barrier call have completed.
//! @param ticket The ticket to monitor.
//! @param priority The priority at which this call will be executed.
//! @param completionCallback Required callback that will be called as soon as the barrier has been reached.
virtual void Barrier(EntitySpawnTicket& ticket, SpawnablePriority priority, BarrierCallback completionCallback) = 0;
//! @param optionalArgs Optional additional arguments, see BarrierOptionalArgs.
virtual void Barrier(EntitySpawnTicket& ticket, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) = 0;
//! Register a handler for OnSpawned events.
virtual void AddOnSpawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler) = 0;
@@ -38,6 +38,10 @@ namespace AzFramework
SpawnableEntitiesManager::SpawnableEntitiesManager()
{
AZ::ComponentApplicationBus::BroadcastResult(m_defaultSerializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
AZ_Assert(
m_defaultSerializeContext, "Failed to retrieve serialization context during construction of the Spawnable Entities Manager.");
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
AZ::u64 value = aznumeric_caster(m_highPriorityThreshold);
@@ -46,58 +50,61 @@ namespace AzFramework
}
}
void SpawnableEntitiesManager::SpawnAllEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, EntityPreInsertionCallback preInsertionCallback,
EntitySpawnCallback completionCallback)
void SpawnableEntitiesManager::SpawnAllEntities(EntitySpawnTicket& ticket, SpawnAllEntitiesOptionalArgs optionalArgs)
{
AZ_Assert(ticket.IsValid(), "Ticket provided to SpawnAllEntities hasn't been initialized.");
SpawnAllEntitiesCommand queueEntry;
queueEntry.m_ticketId = ticket.GetId();
queueEntry.m_completionCallback = AZStd::move(completionCallback);
queueEntry.m_preInsertionCallback = AZStd::move(preInsertionCallback);
QueueRequest(ticket, priority, AZStd::move(queueEntry));
queueEntry.m_serializeContext =
optionalArgs.m_serializeContext == nullptr ? m_defaultSerializeContext : optionalArgs.m_serializeContext;
queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback);
queueEntry.m_preInsertionCallback = AZStd::move(optionalArgs.m_preInsertionCallback);
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
}
void SpawnableEntitiesManager::SpawnEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, AZStd::vector<size_t> entityIndices,
EntityPreInsertionCallback preInsertionCallback, EntitySpawnCallback completionCallback)
EntitySpawnTicket& ticket, AZStd::vector<size_t> entityIndices, SpawnEntitiesOptionalArgs optionalArgs)
{
AZ_Assert(ticket.IsValid(), "Ticket provided to SpawnEntities hasn't been initialized.");
SpawnEntitiesCommand queueEntry;
queueEntry.m_ticketId = ticket.GetId();
queueEntry.m_entityIndices = AZStd::move(entityIndices);
queueEntry.m_completionCallback = AZStd::move(completionCallback);
queueEntry.m_preInsertionCallback = AZStd::move(preInsertionCallback);
QueueRequest(ticket, priority, AZStd::move(queueEntry));
queueEntry.m_serializeContext =
optionalArgs.m_serializeContext == nullptr ? m_defaultSerializeContext : optionalArgs.m_serializeContext;
queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback);
queueEntry.m_preInsertionCallback = AZStd::move(optionalArgs.m_preInsertionCallback);
queueEntry.m_referencePreviouslySpawnedEntities = optionalArgs.m_referencePreviouslySpawnedEntities;
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
}
void SpawnableEntitiesManager::DespawnAllEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, EntityDespawnCallback completionCallback)
void SpawnableEntitiesManager::DespawnAllEntities(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs)
{
AZ_Assert(ticket.IsValid(), "Ticket provided to DespawnAllEntities hasn't been initialized.");
DespawnAllEntitiesCommand queueEntry;
queueEntry.m_ticketId = ticket.GetId();
queueEntry.m_completionCallback = AZStd::move(completionCallback);
QueueRequest(ticket, priority, AZStd::move(queueEntry));
queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback);
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
}
void SpawnableEntitiesManager::ReloadSpawnable(
EntitySpawnTicket& ticket, SpawnablePriority priority, AZ::Data::Asset<Spawnable> spawnable,
ReloadSpawnableCallback completionCallback)
EntitySpawnTicket& ticket, AZ::Data::Asset<Spawnable> spawnable, ReloadSpawnableOptionalArgs optionalArgs)
{
AZ_Assert(ticket.IsValid(), "Ticket provided to ReloadSpawnable hasn't been initialized.");
ReloadSpawnableCommand queueEntry;
queueEntry.m_ticketId = ticket.GetId();
queueEntry.m_spawnable = AZStd::move(spawnable);
queueEntry.m_completionCallback = AZStd::move(completionCallback);
QueueRequest(ticket, priority, AZStd::move(queueEntry));
queueEntry.m_serializeContext =
optionalArgs.m_serializeContext == nullptr ? m_defaultSerializeContext : optionalArgs.m_serializeContext;
queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback);
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
}
void SpawnableEntitiesManager::ListEntities(EntitySpawnTicket& ticket, SpawnablePriority priority, ListEntitiesCallback listCallback)
void SpawnableEntitiesManager::ListEntities(
EntitySpawnTicket& ticket, ListEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs)
{
AZ_Assert(listCallback, "ListEntities called on spawnable entities without a valid callback to use.");
AZ_Assert(ticket.IsValid(), "Ticket provided to ListEntities hasn't been initialized.");
@@ -105,11 +112,11 @@ namespace AzFramework
ListEntitiesCommand queueEntry;
queueEntry.m_ticketId = ticket.GetId();
queueEntry.m_listCallback = AZStd::move(listCallback);
QueueRequest(ticket, priority, AZStd::move(queueEntry));
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
}
void SpawnableEntitiesManager::ListIndicesAndEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, ListIndicesEntitiesCallback listCallback)
EntitySpawnTicket& ticket, ListIndicesEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs)
{
AZ_Assert(listCallback, "ListEntities called on spawnable entities without a valid callback to use.");
AZ_Assert(ticket.IsValid(), "Ticket provided to ListEntities hasn't been initialized.");
@@ -117,10 +124,11 @@ namespace AzFramework
ListIndicesEntitiesCommand queueEntry;
queueEntry.m_ticketId = ticket.GetId();
queueEntry.m_listCallback = AZStd::move(listCallback);
QueueRequest(ticket, priority, AZStd::move(queueEntry));
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
}
void SpawnableEntitiesManager::ClaimEntities(EntitySpawnTicket& ticket, SpawnablePriority priority, ClaimEntitiesCallback listCallback)
void SpawnableEntitiesManager::ClaimEntities(
EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback, ClaimEntitiesOptionalArgs optionalArgs)
{
AZ_Assert(listCallback, "ClaimEntities called on spawnable entities without a valid callback to use.");
AZ_Assert(ticket.IsValid(), "Ticket provided to ClaimEntities hasn't been initialized.");
@@ -128,10 +136,10 @@ namespace AzFramework
ClaimEntitiesCommand queueEntry;
queueEntry.m_ticketId = ticket.GetId();
queueEntry.m_listCallback = AZStd::move(listCallback);
QueueRequest(ticket, priority, AZStd::move(queueEntry));
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
}
void SpawnableEntitiesManager::Barrier(EntitySpawnTicket& ticket, SpawnablePriority priority, BarrierCallback completionCallback)
void SpawnableEntitiesManager::Barrier(EntitySpawnTicket& ticket, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs)
{
AZ_Assert(completionCallback, "Barrier on spawnable entities called without a valid callback to use.");
AZ_Assert(ticket.IsValid(), "Ticket provided to Barrier hasn't been initialized.");
@@ -139,7 +147,7 @@ namespace AzFramework
BarrierCommand queueEntry;
queueEntry.m_ticketId = ticket.GetId();
queueEntry.m_completionCallback = AZStd::move(completionCallback);
QueueRequest(ticket, priority, AZStd::move(queueEntry));
QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry));
}
void SpawnableEntitiesManager::AddOnSpawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler)
@@ -174,58 +182,57 @@ namespace AzFramework
auto SpawnableEntitiesManager::ProcessQueue(Queue& queue) -> CommandQueueStatus
{
AZStd::queue<Requests> pendingRequestQueue;
// Process delayed requests first.
// Only process the requests that are currently in this queue, not the ones that could be re-added if they still can't complete.
size_t delayedSize = queue.m_delayed.size();
for (size_t i = 0; i < delayedSize; ++i)
{
AZStd::scoped_lock queueLock(queue.m_pendingRequestMutex);
queue.m_pendingRequest.swap(pendingRequestQueue);
Requests& request = queue.m_delayed.front();
bool result = AZStd::visit(
[this](auto&& args) -> bool
{
return ProcessRequest(args);
},
request);
if (!result)
{
queue.m_delayed.emplace_back(AZStd::move(request));
}
queue.m_delayed.pop_front();
}
if (!pendingRequestQueue.empty() || !queue.m_delayed.empty())
// Process newly added requests.
while (true)
{
AZ::SerializeContext* serializeContext = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
AZ_Assert(serializeContext, "Failed to retrieve serialization context.");
// Only process the requests that are currently in this queue, not the ones that could be re-added if they still can't complete.
size_t delayedSize = queue.m_delayed.size();
for (size_t i = 0; i < delayedSize; ++i)
AZStd::queue<Requests> pendingRequestQueue;
{
Requests& request = queue.m_delayed.front();
bool result = AZStd::visit([this, serializeContext](auto&& args) -> bool
{
return ProcessRequest(args, *serializeContext);
}, request);
if (!result)
{
queue.m_delayed.emplace_back(AZStd::move(request));
}
queue.m_delayed.pop_front();
AZStd::scoped_lock queueLock(queue.m_pendingRequestMutex);
queue.m_pendingRequest.swap(pendingRequestQueue);
}
do
if (!pendingRequestQueue.empty())
{
while (!pendingRequestQueue.empty())
{
Requests& request = pendingRequestQueue.front();
bool result = AZStd::visit([this, serializeContext](auto&& args) -> bool
bool result = AZStd::visit(
[this](auto&& args) -> bool
{
return ProcessRequest(args, *serializeContext);
}, request);
return ProcessRequest(args);
},
request);
if (!result)
{
queue.m_delayed.emplace_back(AZStd::move(request));
}
pendingRequestQueue.pop();
}
// Spawning entities can result in more entities being queued to spawn. Repeat spawning until the queue is
// empty to avoid a chain of entity spawning getting dragged out over multiple frames.
{
AZStd::scoped_lock queueLock(queue.m_pendingRequestMutex);
queue.m_pendingRequest.swap(pendingRequestQueue);
}
} while (!pendingRequestQueue.empty());
}
}
else
{
break;
}
};
return queue.m_delayed.empty() ? CommandQueueStatus::NoCommandsLeft : CommandQueueStatus::HasCommandsLeft;
}
@@ -250,24 +257,14 @@ namespace AzFramework
}
}
AZ::Entity* SpawnableEntitiesManager::SpawnSingleEntity(const AZ::Entity& entityTemplate, AZ::SerializeContext& serializeContext)
{
AZ::Entity* clone = serializeContext.CloneObject(&entityTemplate);
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
clone->SetId(AZ::Entity::MakeId());
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, clone);
return clone;
}
AZ::Entity* SpawnableEntitiesManager::CloneSingleEntity(const AZ::Entity& entityTemplate,
EntityIdMap& templateToCloneEntityIdMap, AZ::SerializeContext& serializeContext)
EntityIdMap& templateToCloneMap, AZ::SerializeContext& serializeContext)
{
return AZ::IdUtils::Remapper<AZ::EntityId>::CloneObjectAndGenerateNewIdsAndFixRefs(
&entityTemplate, templateToCloneEntityIdMap, &serializeContext);
return AZ::IdUtils::Remapper<AZ::EntityId, true>::CloneObjectAndGenerateNewIdsAndFixRefs(
&entityTemplate, templateToCloneMap, &serializeContext);
}
bool SpawnableEntitiesManager::ProcessRequest(SpawnAllEntitiesCommand& request, AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(SpawnAllEntitiesCommand& request)
{
Ticket& ticket = *request.m_ticket;
if (ticket.m_spawnable.IsReady() && request.m_requestId == ticket.m_currentRequestId)
@@ -291,13 +288,9 @@ namespace AzFramework
spawnedEntityIndices.reserve(spawnedEntityIndices.size() + entitiesToSpawnSize);
templateToCloneEntityIdMap.reserve(entitiesToSpawnSize);
// Mark all indices as spawned
for (size_t i = 0; i < entitiesToSpawnSize; ++i)
{
const AZ::Entity& entityTemplate = *entitiesToSpawn[i];
AZ::Entity* clone = CloneSingleEntity(entityTemplate, templateToCloneEntityIdMap, serializeContext);
AZ::Entity* clone = CloneSingleEntity(*entitiesToSpawn[i], templateToCloneEntityIdMap, *request.m_serializeContext);
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
spawnedEntities.emplace_back(clone);
@@ -305,16 +298,8 @@ namespace AzFramework
}
// loadAll is true if every entity has been spawned only once
if (spawnedEntities.size() == entitiesToSpawnSize)
{
ticket.m_loadAll = true;
}
else
{
// Case where there were already spawns from a previous request
ticket.m_loadAll = false;
}
ticket.m_loadAll = (spawnedEntities.size() == entitiesToSpawnSize);
// Let other systems know about newly spawned entities for any pre-processing before adding to the scene/game context.
if (request.m_preInsertionCallback)
{
@@ -323,11 +308,10 @@ namespace AzFramework
}
// Add to the game context, now the entities are active
AZStd::for_each(ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount, ticket.m_spawnedEntities.end(),
[](AZ::Entity* entity)
for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it)
{
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, entity);
});
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
}
// Let other systems know about newly spawned entities for any post-processing after adding to the scene/game context.
if (request.m_completionCallback)
@@ -347,21 +331,41 @@ namespace AzFramework
}
}
bool SpawnableEntitiesManager::ProcessRequest(SpawnEntitiesCommand& request, AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(SpawnEntitiesCommand& request)
{
Ticket& ticket = *request.m_ticket;
if (ticket.m_spawnable.IsReady() && request.m_requestId == ticket.m_currentRequestId)
{
AZStd::vector<AZ::Entity*>& spawnedEntities = ticket.m_spawnedEntities;
AZStd::vector<size_t>& spawnedEntityIndices = ticket.m_spawnedEntityIndices;
AZ_Assert(
spawnedEntities.size() == spawnedEntityIndices.size(),
"The indices for the spawned entities has gone out of sync with the entities.");
// Keep track how many entities there were in the array initially
// Keep track of how many entities there were in the array initially
size_t spawnedEntitiesInitialCount = spawnedEntities.size();
// These are 'template' entities we'll be cloning from
const Spawnable::EntityList& entitiesToSpawn = ticket.m_spawnable->GetEntities();
size_t entitiesToSpawnSize = request.m_entityIndices.size();
// Reconstruct the template to entity mapping.
EntityIdMap templateToCloneEntityIdMap;
if (!request.m_referencePreviouslySpawnedEntities)
{
templateToCloneEntityIdMap.reserve(entitiesToSpawnSize);
}
else
{
templateToCloneEntityIdMap.reserve(spawnedEntitiesInitialCount + entitiesToSpawnSize);
SpawnableConstIndexEntityContainerView indexEntityView(
spawnedEntities.begin(), spawnedEntityIndices.begin(), spawnedEntities.size());
for (auto& entry : indexEntityView)
{
templateToCloneEntityIdMap.insert_or_assign(entitiesToSpawn[entry.GetIndex()]->GetId(), entry.GetEntity()->GetId());
}
}
spawnedEntities.reserve(spawnedEntities.size() + entitiesToSpawnSize);
spawnedEntityIndices.reserve(spawnedEntityIndices.size() + entitiesToSpawnSize);
@@ -369,15 +373,11 @@ namespace AzFramework
{
if (index < entitiesToSpawn.size())
{
const AZ::Entity& entityTemplate = *entitiesToSpawn[index];
AZ::Entity* clone = serializeContext.CloneObject(&entityTemplate);
AZ::Entity* clone = CloneSingleEntity(*entitiesToSpawn[index], templateToCloneEntityIdMap, *request.m_serializeContext);
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
clone->SetId(AZ::Entity::MakeId());
spawnedEntities.push_back(clone);
spawnedEntityIndices.push_back(index);
}
}
ticket.m_loadAll = false;
@@ -390,11 +390,10 @@ namespace AzFramework
}
// Add to the game context, now the entities are active
AZStd::for_each(ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount, ticket.m_spawnedEntities.end(),
[](AZ::Entity* entity)
for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it)
{
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, entity);
});
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
}
if (request.m_completionCallback)
{
@@ -413,8 +412,7 @@ namespace AzFramework
}
}
bool SpawnableEntitiesManager::ProcessRequest(DespawnAllEntitiesCommand& request,
[[maybe_unused]] AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(DespawnAllEntitiesCommand& request)
{
Ticket& ticket = *request.m_ticket;
if (request.m_requestId == ticket.m_currentRequestId)
@@ -447,7 +445,7 @@ namespace AzFramework
}
}
bool SpawnableEntitiesManager::ProcessRequest(ReloadSpawnableCommand& request, AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(ReloadSpawnableCommand& request)
{
Ticket& ticket = *request.m_ticket;
AZ_Assert(ticket.m_spawnable.GetId() == request.m_spawnable.GetId(),
@@ -470,39 +468,43 @@ namespace AzFramework
// Rebuild the list of entities.
ticket.m_spawnedEntities.clear();
const Spawnable::EntityList& entities = request.m_spawnable->GetEntities();
// Map keeps track of ids from template (spawnable) to clone (instance)
// Allowing patch ups of fields referring to entityIds outside of a given entity
EntityIdMap templateToCloneEntityIdMap;
if (ticket.m_loadAll)
{
// The new spawnable may have a different number of entities and since the intent of the user was
// to load every, simply start over.
// to spawn every entity, simply start over.
ticket.m_spawnedEntityIndices.clear();
size_t entitiesToSpawnSize = entities.size();
// Map keeps track of ids from template (spawnable) to clone (instance)
// Allowing patch ups of fields referring to entityIds outside of a given entity
EntityIdMap templateToCloneEntityIdMap;
templateToCloneEntityIdMap.reserve(entitiesToSpawnSize);
// Mark all indices as spawned
for (size_t i = 0; i < entitiesToSpawnSize; ++i)
{
const AZ::Entity& entityTemplate = *entities[i];
AZ::Entity* clone = CloneSingleEntity(entityTemplate, templateToCloneEntityIdMap, serializeContext);
AZ::Entity* clone = CloneSingleEntity(*entities[i], templateToCloneEntityIdMap, *request.m_serializeContext);
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
ticket.m_spawnedEntities.emplace_back(clone);
ticket.m_spawnedEntities.push_back(clone);
ticket.m_spawnedEntityIndices.push_back(i);
}
}
else
{
size_t entitiesSize = entities.size();
templateToCloneEntityIdMap.reserve(entitiesSize);
for (size_t index : ticket.m_spawnedEntityIndices)
{
ticket.m_spawnedEntities.push_back(
index < entitiesSize ? SpawnSingleEntity(*entities[index], serializeContext) : nullptr);
// It's possible for the new spawnable to have a different number of entities, so guard against this.
// It's also possible that the entities have moved within the spawnable to a new index. This can't be
// detected and will result in the incorrect entities being spawned.
if (index < entitiesSize)
{
AZ::Entity* clone = CloneSingleEntity(*entities[index], templateToCloneEntityIdMap, *request.m_serializeContext);
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
ticket.m_spawnedEntities.push_back(clone);
}
}
}
ticket.m_spawnable = AZStd::move(request.m_spawnable);
@@ -525,7 +527,7 @@ namespace AzFramework
}
}
bool SpawnableEntitiesManager::ProcessRequest(ListEntitiesCommand& request, [[maybe_unused]] AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(ListEntitiesCommand& request)
{
Ticket& ticket = *request.m_ticket;
if (request.m_requestId == ticket.m_currentRequestId)
@@ -541,7 +543,7 @@ namespace AzFramework
}
}
bool SpawnableEntitiesManager::ProcessRequest(ListIndicesEntitiesCommand& request, [[maybe_unused]] AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(ListIndicesEntitiesCommand& request)
{
Ticket& ticket = *request.m_ticket;
if (request.m_requestId == ticket.m_currentRequestId)
@@ -560,7 +562,7 @@ namespace AzFramework
}
}
bool SpawnableEntitiesManager::ProcessRequest(ClaimEntitiesCommand& request, [[maybe_unused]] AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(ClaimEntitiesCommand& request)
{
Ticket& ticket = *request.m_ticket;
if (request.m_requestId == ticket.m_currentRequestId)
@@ -580,7 +582,7 @@ namespace AzFramework
}
}
bool SpawnableEntitiesManager::ProcessRequest(BarrierCommand& request, [[maybe_unused]] AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(BarrierCommand& request)
{
Ticket& ticket = *request.m_ticket;
if (request.m_requestId == ticket.m_currentRequestId)
@@ -599,7 +601,7 @@ namespace AzFramework
}
}
bool SpawnableEntitiesManager::ProcessRequest(DestroyTicketCommand& request, [[maybe_unused]] AZ::SerializeContext& serializeContext)
bool SpawnableEntitiesManager::ProcessRequest(DestroyTicketCommand& request)
{
if (request.m_requestId == request.m_ticket->m_currentRequestId)
{
@@ -37,7 +37,7 @@ namespace AzFramework
AZ_CLASS_ALLOCATOR(SpawnableEntitiesManager, AZ::SystemAllocator, 0);
using EntityIdMap = AZStd::unordered_map<AZ::EntityId, AZ::EntityId>;
enum class CommandQueueStatus : bool
{
HasCommandsLeft,
@@ -57,26 +57,21 @@ namespace AzFramework
// The following functions are thread safe
//
void SpawnAllEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, EntityPreInsertionCallback preInsertionCallback = {},
EntitySpawnCallback completionCallback = {}) override;
void SpawnAllEntities(EntitySpawnTicket& ticket, SpawnAllEntitiesOptionalArgs optionalArgs = {}) override;
void SpawnEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, AZStd::vector<size_t> entityIndices,
EntityPreInsertionCallback preInsertionCallback = {},
EntitySpawnCallback completionCallback = {}) override;
void DespawnAllEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, EntityDespawnCallback completionCallback = {}) override;
EntitySpawnTicket& ticket, AZStd::vector<size_t> entityIndices, SpawnEntitiesOptionalArgs optionalArgs = {}) override;
void DespawnAllEntities(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs = {}) override;
void ReloadSpawnable(
EntitySpawnTicket& ticket, SpawnablePriority priority, AZ::Data::Asset<Spawnable> spawnable,
ReloadSpawnableCallback completionCallback = {}) override;
EntitySpawnTicket& ticket, AZ::Data::Asset<Spawnable> spawnable, ReloadSpawnableOptionalArgs optionalArgs = {}) override;
void ListEntities(EntitySpawnTicket& ticket, SpawnablePriority priority, ListEntitiesCallback listCallback) override;
void ListEntities(
EntitySpawnTicket& ticket, ListEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs = {}) override;
void ListIndicesAndEntities(
EntitySpawnTicket& ticket, SpawnablePriority priority, ListIndicesEntitiesCallback listCallback) override;
void ClaimEntities(EntitySpawnTicket& ticket, SpawnablePriority priority, ClaimEntitiesCallback listCallback) override;
EntitySpawnTicket& ticket, ListIndicesEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs = {}) override;
void ClaimEntities(
EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback, ClaimEntitiesOptionalArgs optionalArgs = {}) override;
void Barrier(EntitySpawnTicket& spawnInfo, SpawnablePriority priority, BarrierCallback completionCallback) override;
void Barrier(EntitySpawnTicket& spawnInfo, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) override;
void AddOnSpawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler) override;
void AddOnDespawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler) override;
@@ -105,6 +100,7 @@ namespace AzFramework
{
EntitySpawnCallback m_completionCallback;
EntityPreInsertionCallback m_preInsertionCallback;
AZ::SerializeContext* m_serializeContext;
Ticket* m_ticket;
EntitySpawnTicket::Id m_ticketId;
uint32_t m_requestId;
@@ -114,9 +110,11 @@ namespace AzFramework
AZStd::vector<size_t> m_entityIndices;
EntitySpawnCallback m_completionCallback;
EntityPreInsertionCallback m_preInsertionCallback;
AZ::SerializeContext* m_serializeContext;
Ticket* m_ticket;
EntitySpawnTicket::Id m_ticketId;
uint32_t m_requestId;
bool m_referencePreviouslySpawnedEntities;
};
struct DespawnAllEntitiesCommand
{
@@ -129,6 +127,7 @@ namespace AzFramework
{
AZ::Data::Asset<Spawnable> m_spawnable;
ReloadSpawnableCallback m_completionCallback;
AZ::SerializeContext* m_serializeContext;
Ticket* m_ticket;
EntitySpawnTicket::Id m_ticketId;
uint32_t m_requestId;
@@ -185,21 +184,18 @@ namespace AzFramework
CommandQueueStatus ProcessQueue(Queue& queue);
AZ::Entity* SpawnSingleEntity(const AZ::Entity& entityTemplate,
AZ::SerializeContext& serializeContext);
AZ::Entity* CloneSingleEntity(const AZ::Entity& entityTemplate,
EntityIdMap& templateToCloneEntityIdMap, AZ::SerializeContext& serializeContext);
bool ProcessRequest(SpawnAllEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(SpawnEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(DespawnAllEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(ReloadSpawnableCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(ListEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(ListIndicesEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(ClaimEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(BarrierCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(DestroyTicketCommand& request, AZ::SerializeContext& serializeContext);
AZ::Entity* CloneSingleEntity(
const AZ::Entity& entityTemplate, EntityIdMap& templateToCloneMap, AZ::SerializeContext& serializeContext);
bool ProcessRequest(SpawnAllEntitiesCommand& request);
bool ProcessRequest(SpawnEntitiesCommand& request);
bool ProcessRequest(DespawnAllEntitiesCommand& request);
bool ProcessRequest(ReloadSpawnableCommand& request);
bool ProcessRequest(ListEntitiesCommand& request);
bool ProcessRequest(ListIndicesEntitiesCommand& request);
bool ProcessRequest(ClaimEntitiesCommand& request);
bool ProcessRequest(BarrierCommand& request);
bool ProcessRequest(DestroyTicketCommand& request);
Queue m_highPriorityQueue;
Queue m_regularPriorityQueue;
@@ -207,6 +203,7 @@ namespace AzFramework
AZ::Event<AZ::Data::Asset<Spawnable>> m_onSpawnedEvent;
AZ::Event<AZ::Data::Asset<Spawnable>> m_onDespawnedEvent;
AZ::SerializeContext* m_defaultSerializeContext { nullptr };
//! The threshold used to determine if a request goes in the regular (if bigger than the value) or high priority queue (if smaller
//! or equal to this value). The starting value of 64 is chosen as it's between default values SpawnablePriority_High and
//! SpawnablePriority_Default which gives users a bit of room to fine tune the priorities as this value can be configured
@@ -22,7 +22,11 @@
namespace AzFramework
{
AZ_CVAR(
float, ed_cameraSystemDefaultPlaneHeight, 34.0f, nullptr, AZ::ConsoleFunctorFlags::Null,
float,
ed_cameraSystemDefaultPlaneHeight,
34.0f,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The default height of the ground plane to do intersection tests against when orbiting");
AZ_CVAR(float, ed_cameraSystemBoostMultiplier, 3.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemTranslateSpeed, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
@@ -41,7 +45,11 @@ namespace AzFramework
AZ_CVAR(
AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(
AZ::CVarFixedString, ed_cameraSystemTranslateBackwardKey, "keyboard_key_alphanumeric_S", nullptr, AZ::ConsoleFunctorFlags::Null,
AZ::CVarFixedString,
ed_cameraSystemTranslateBackwardKey,
"keyboard_key_alphanumeric_S",
nullptr,
AZ::ConsoleFunctorFlags::Null,
"");
AZ_CVAR(
AZ::CVarFixedString, ed_cameraSystemTranslateLeftKey, "keyboard_key_alphanumeric_A", nullptr, AZ::ConsoleFunctorFlags::Null, "");
@@ -326,7 +334,9 @@ namespace AzFramework
}
Camera RotateCameraInput::StepCamera(
const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
const Camera& targetCamera,
const ScreenVector& cursorDelta,
[[maybe_unused]] const float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
@@ -374,7 +384,9 @@ namespace AzFramework
}
Camera PanCameraInput::StepCamera(
const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
const Camera& targetCamera,
const ScreenVector& cursorDelta,
[[maybe_unused]] const float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
@@ -473,7 +485,9 @@ namespace AzFramework
}
Camera TranslateCameraInput::StepCamera(
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
const Camera& targetCamera,
[[maybe_unused]] const ScreenVector& cursorDelta,
[[maybe_unused]] const float scrollDelta,
const float deltaTime)
{
Camera nextCamera = targetCamera;
@@ -630,7 +644,9 @@ namespace AzFramework
}
Camera OrbitDollyScrollCameraInput::StepCamera(
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta,
const Camera& targetCamera,
[[maybe_unused]] const ScreenVector& cursorDelta,
const float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
@@ -666,7 +682,9 @@ namespace AzFramework
}
Camera OrbitDollyCursorMoveCameraInput::StepCamera(
const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
const Camera& targetCamera,
const ScreenVector& cursorDelta,
[[maybe_unused]] const float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
@@ -686,7 +704,9 @@ namespace AzFramework
}
Camera ScrollTranslationCameraInput::StepCamera(
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta,
const Camera& targetCamera,
[[maybe_unused]] const ScreenVector& cursorDelta,
const float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
@@ -128,12 +128,12 @@ namespace AzFramework
worldPosition, CameraView(cameraState), CameraProjection(cameraState), cameraState.m_viewportSize);
}
AZ::Vector3 ScreenToWorld(
const ScreenPoint& screenPosition, const AZ::Matrix4x4& inverseCameraView,
const AZ::Matrix4x4& inverseCameraProjection, const AZ::Vector2& viewportSize)
AZ::Vector3 ScreenNDCToWorld(
const AZ::Vector2& normalizedScreenPosition, const AZ::Matrix4x4& inverseCameraView,
const AZ::Matrix4x4& inverseCameraProjection)
{
// convert screen space coordinates from <0, 1> to <-1,1> range
const auto ndcPosition = NDCFromScreenPoint(screenPosition, viewportSize) * 2.0f - AZ::Vector2::CreateOne();
const auto ndcPosition = normalizedScreenPosition * 2.0f - AZ::Vector2::CreateOne();
// transform ndc space position to clip space
const auto clipSpacePosition = inverseCameraProjection * Vector2ToVector4(ndcPosition, -1.0f, 1.0f);
@@ -145,6 +145,15 @@ namespace AzFramework
return worldPosition;
}
AZ::Vector3 ScreenToWorld(
const ScreenPoint& screenPosition, const AZ::Matrix4x4& inverseCameraView,
const AZ::Matrix4x4& inverseCameraProjection, const AZ::Vector2& viewportSize)
{
const auto normalizedScreenPosition = NDCFromScreenPoint(screenPosition, viewportSize);
return ScreenNDCToWorld(normalizedScreenPosition, inverseCameraView, inverseCameraProjection);
}
AZ::Vector3 ScreenToWorld(const ScreenPoint& screenPosition, const CameraState& cameraState)
{
return ScreenToWorld(
@@ -42,7 +42,7 @@ namespace AzFramework
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection,
const AZ::Vector2& viewportSize);
//! Unprojects a position in screen space to world space.
//! Unprojects a position in screen space pixel coordinates to world space.
//! Note: The position returned will be on the near clip plane of the camera in world space.
AZ::Vector3 ScreenToWorld(const ScreenPoint& screenPosition, const CameraState& cameraState);
@@ -52,6 +52,12 @@ namespace AzFramework
const ScreenPoint& screenPosition, const AZ::Matrix4x4& inverseCameraView,
const AZ::Matrix4x4& inverseCameraProjection, const AZ::Vector2& viewportSize);
//! Unprojects a position in screen space normalized device coordinates to world space.
//! Note: The position returned will be on the near clip plane of the camera in world space.
AZ::Vector3 ScreenNDCToWorld(
const AZ::Vector2& ndcPosition, const AZ::Matrix4x4& inverseCameraView,
const AZ::Matrix4x4& inverseCameraProjection);
//! Returns the camera projection for the current camera state.
AZ::Matrix4x4 CameraProjection(const CameraState& cameraState);
@@ -97,7 +97,7 @@ namespace AzManipulatorTestFramework
if (m_logging)
{
AZStd::string message = AZStd::string::format(format, args...);
std::cout << "[ActionDispatcher] " << message.c_str() << "\n";
AZ_Printf("[ActionDispatcher] %s", message.c_str());
}
}
@@ -21,12 +21,14 @@ namespace AzManipulatorTestFramework
{
//! Create a linear manipulator with a unit sphere bound.
AZStd::shared_ptr<AzToolsFramework::LinearManipulator> CreateLinearManipulator(
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId, const AZ::Vector3& position = AZ::Vector3::CreateZero(),
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId,
const AZ::Vector3& position = AZ::Vector3::CreateZero(),
float radius = 1.0f);
//! Create a planar manipulator with a unit sphere bound.
AZStd::shared_ptr<AzToolsFramework::PlanarManipulator> CreatePlanarManipulator(
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId, const AZ::Vector3& position = AZ::Vector3::CreateZero(),
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId,
const AZ::Vector3& position = AZ::Vector3::CreateZero(),
float radius = 1.0f);
//! Create a mouse pick from the specified ray and screen point.
@@ -39,7 +41,8 @@ namespace AzManipulatorTestFramework
//! Create a mouse interaction from the specified pick, buttons, interaction id and keyboard modifiers.
AzToolsFramework::ViewportInteraction::MouseInteraction CreateMouseInteraction(
const AzToolsFramework::ViewportInteraction::MousePick& mousePick, AzToolsFramework::ViewportInteraction::MouseButtons buttons,
const AzToolsFramework::ViewportInteraction::MousePick& mousePick,
AzToolsFramework::ViewportInteraction::MouseButtons buttons,
AzToolsFramework::ViewportInteraction::InteractionId interactionId,
AzToolsFramework::ViewportInteraction::KeyboardModifiers modifiers);
@@ -12,14 +12,13 @@
#pragma once
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzManipulatorTestFramework/ActionDispatcher.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
namespace AzManipulatorTestFramework
{
//! Dispatches actions immediately to the manipulators.
class ImmediateModeActionDispatcher
: public ActionDispatcher<ImmediateModeActionDispatcher>
class ImmediateModeActionDispatcher : public ActionDispatcher<ImmediateModeActionDispatcher>
{
using KeyboardModifier = AzToolsFramework::ViewportInteraction::KeyboardModifier;
using KeyboardModifiers = AzToolsFramework::ViewportInteraction::KeyboardModifiers;
@@ -62,7 +61,7 @@ namespace AzManipulatorTestFramework
void MouseLButtonUpImpl() override;
void MousePositionImpl(const AzFramework::ScreenPoint& position) override;
void KeyboardModifierDownImpl(const KeyboardModifier& keyModifier) override;
void KeyboardModifierUpImpl(const KeyboardModifier& keyModifier) override;
void KeyboardModifierUpImpl(const KeyboardModifier& keyModifier) override;
void ExpectManipulatorBeingInteractedImpl() override;
void ExpectManipulatorNotBeingInteractedImpl() override;
void SetEntityWorldTransformImpl(AZ::EntityId entityId, const AZ::Transform& transform) override;
@@ -97,8 +96,7 @@ namespace AzManipulatorTestFramework
return this;
}
inline ImmediateModeActionDispatcher* ImmediateModeActionDispatcher::GetKeyboardModifiers(
KeyboardModifiers& keyboardModifiers)
inline ImmediateModeActionDispatcher* ImmediateModeActionDispatcher::GetKeyboardModifiers(KeyboardModifiers& keyboardModifiers)
{
keyboardModifiers = GetKeyboardModifiers();
return this;
@@ -30,8 +30,10 @@ namespace AzManipulatorTestFramework
// create a default sphere view for a manipulator for simple intersection
template<typename Manipulator>
void SetupManipulatorView(
AZStd::shared_ptr<Manipulator> manipulator, const AzToolsFramework::ManipulatorManagerId manipulatorManagerId,
const AZ::Vector3& position, const float radius)
AZStd::shared_ptr<Manipulator> manipulator,
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId,
const AZ::Vector3& position,
const float radius)
{
// unit sphere view
auto sphereView = AzToolsFramework::CreateManipulatorViewSphere(
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
#include <AzManipulatorTestFramework/ViewportInteraction.h>
@@ -19,10 +19,10 @@ namespace AzManipulatorTestFramework
using MouseInteraction = AzToolsFramework::ViewportInteraction::MouseInteraction;
using MouseInteractionEvent = AzToolsFramework::ViewportInteraction::MouseInteractionEvent;
class CustomManipulatorManager
: public AzToolsFramework::ManipulatorManager
class CustomManipulatorManager : public AzToolsFramework::ManipulatorManager
{
using ManagerBase = AzToolsFramework::ManipulatorManager;
public:
using ManagerBase::ManagerBase;
@@ -31,18 +31,17 @@ namespace AzManipulatorTestFramework
};
//! Implementation of the manipulator interface using direct access to the manipulator manager.
class DirectCallManipulatorManager
: public ManipulatorManagerInterface
class DirectCallManipulatorManager : public ManipulatorManagerInterface
{
public:
DirectCallManipulatorManager(
ViewportInteractionInterface* viewportInteraction,
AZStd::shared_ptr<CustomManipulatorManager> manipulatorManager);
ViewportInteractionInterface* viewportInteraction, AZStd::shared_ptr<CustomManipulatorManager> manipulatorManager);
// ManipulatorManagerInterface ...
void ConsumeMouseInteractionEvent(const MouseInteractionEvent& event);
AzToolsFramework::ManipulatorManagerId GetId() const override;
bool ManipulatorBeingInteracted() const override;
private:
// Trigger the updating of manipulator bounds.
void DrawManipulators(const MouseInteraction& mouseInteraction);
@@ -61,8 +60,7 @@ namespace AzManipulatorTestFramework
}
DirectCallManipulatorManager::DirectCallManipulatorManager(
ViewportInteractionInterface* viewportInteraction,
AZStd::shared_ptr<CustomManipulatorManager> manipulatorManager)
ViewportInteractionInterface* viewportInteraction, AZStd::shared_ptr<CustomManipulatorManager> manipulatorManager)
: m_viewportInteraction(viewportInteraction)
, m_manipulatorManager(AZStd::move(manipulatorManager))
{
@@ -126,11 +124,9 @@ namespace AzManipulatorTestFramework
DirectCallManipulatorViewportInteraction::DirectCallManipulatorViewportInteraction()
: m_customManager(
AZStd::make_unique<CustomManipulatorManager>(
AzToolsFramework::ManipulatorManagerId(AZ::Crc32("TestManipulatorManagerId"))))
AZStd::make_unique<CustomManipulatorManager>(AzToolsFramework::ManipulatorManagerId(AZ::Crc32("TestManipulatorManagerId"))))
, m_viewportInteraction(AZStd::make_unique<ViewportInteraction>())
, m_manipulatorManager(
AZStd::make_unique<DirectCallManipulatorManager>(m_viewportInteraction.get(), m_customManager))
, m_manipulatorManager(AZStd::make_unique<DirectCallManipulatorManager>(m_viewportInteraction.get(), m_customManager))
{
}
@@ -10,8 +10,8 @@
*
*/
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
@@ -33,8 +33,7 @@ namespace AzManipulatorTestFramework
using KeyboardModifier = AzToolsFramework::ViewportInteraction::KeyboardModifier;
using MouseInteractionEvent = AzToolsFramework::ViewportInteraction::MouseInteractionEvent;
ImmediateModeActionDispatcher::ImmediateModeActionDispatcher(
ManipulatorViewportInteraction& viewportManipulatorInteraction)
ImmediateModeActionDispatcher::ImmediateModeActionDispatcher(ManipulatorViewportInteraction& viewportManipulatorInteraction)
: m_viewportManipulatorInteraction(viewportManipulatorInteraction)
{
}
@@ -126,8 +125,7 @@ namespace AzManipulatorTestFramework
void ImmediateModeActionDispatcher::EnterComponentModeImpl(const AZ::Uuid& uuid)
{
using AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus;
ComponentModeSystemRequestBus::Broadcast(
&ComponentModeSystemRequestBus::Events::AddSelectedComponentModesOfType, uuid);
ComponentModeSystemRequestBus::Broadcast(&ComponentModeSystemRequestBus::Events::AddSelectedComponentModesOfType, uuid);
}
const AzToolsFramework::ViewportInteraction::MouseInteractionEvent* ImmediateModeActionDispatcher::GetMouseInteractionEvent() const
@@ -144,8 +142,7 @@ namespace AzManipulatorTestFramework
AzToolsFramework::ViewportInteraction::MouseInteractionEvent* ImmediateModeActionDispatcher::GetMouseInteractionEvent()
{
return const_cast<MouseInteractionEvent*>(
static_cast<const ImmediateModeActionDispatcher*>(this)->GetMouseInteractionEvent());
return const_cast<MouseInteractionEvent*>(static_cast<const ImmediateModeActionDispatcher*>(this)->GetMouseInteractionEvent());
}
ImmediateModeActionDispatcher* ImmediateModeActionDispatcher::ExpectTrue(bool result)
@@ -162,8 +159,7 @@ namespace AzManipulatorTestFramework
return this;
}
ImmediateModeActionDispatcher* ImmediateModeActionDispatcher::GetEntityWorldTransform(
AZ::EntityId entityId, AZ::Transform& transform)
ImmediateModeActionDispatcher* ImmediateModeActionDispatcher::GetEntityWorldTransform(AZ::EntityId entityId, AZ::Transform& transform)
{
Log("Getting entity world transform");
transform = AzToolsFramework::GetWorldTransform(entityId);
@@ -11,17 +11,18 @@
*/
#include "AzManipulatorTestFrameworkTestFixtures.h"
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
namespace UnitTest
{
class AzManipulatorTestFrameworkBusCallTestFixture
: public LinearManipulatorTestFixture
class AzManipulatorTestFrameworkBusCallTestFixture : public LinearManipulatorTestFixture
{
protected:
AzManipulatorTestFrameworkBusCallTestFixture()
: LinearManipulatorTestFixture(AzToolsFramework::g_mainManipulatorManagerId) {}
: LinearManipulatorTestFixture(AzToolsFramework::g_mainManipulatorManagerId)
{
}
bool IsManipulatorInteractingBusCall() const
{
@@ -37,8 +38,8 @@ namespace UnitTest
TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportLeftMouseClick)
{
// given a left mouse down ray in world space
auto event = AzManipulatorTestFramework::CreateMouseInteractionEvent(
m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
auto event =
AzManipulatorTestFramework::CreateMouseInteractionEvent(m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
// consume the mouse down and up events
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);
@@ -56,8 +57,8 @@ namespace UnitTest
TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportMouseMoveHover)
{
// given a left mouse down ray in world space
const auto event = AzManipulatorTestFramework::CreateMouseInteractionEvent(
m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Move);
const auto event =
AzManipulatorTestFramework::CreateMouseInteractionEvent(m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Move);
// consume the mouse move event
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);
@@ -75,8 +76,8 @@ namespace UnitTest
TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportMouseMoveActive)
{
// given a left mouse down ray in world space
auto event = AzManipulatorTestFramework::CreateMouseInteractionEvent(
m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
auto event =
AzManipulatorTestFramework::CreateMouseInteractionEvent(m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
// consume the mouse down event
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);
@@ -110,14 +111,14 @@ namespace UnitTest
const AZ::Vector3 initialManipulatorPosition = m_linearManipulator->GetLocalPosition();
m_linearManipulator->InstallMouseMoveCallback(
[&movementAlongAxis, this](const AzToolsFramework::LinearManipulator::Action& action)
{
movementAlongAxis = action.LocalPositionOffset();
m_linearManipulator->SetLocalPosition(action.LocalPosition());
});
{
movementAlongAxis = action.LocalPositionOffset();
m_linearManipulator->SetLocalPosition(action.LocalPosition());
});
// given a left mouse down ray in world space
auto event = AzManipulatorTestFramework::CreateMouseInteractionEvent(
m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
auto event =
AzManipulatorTestFramework::CreateMouseInteractionEvent(m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
// consume the mouse down event
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);
@@ -134,7 +135,7 @@ namespace UnitTest
// consume the mouse up event
event.m_mouseEvent = AzToolsFramework::ViewportInteraction::MouseEvent::Up;
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);
// expect the left mouse down/up sanity flags to be set
EXPECT_TRUE(m_receivedLeftMouseDown);
EXPECT_TRUE(m_receivedLeftMouseUp);
@@ -14,10 +14,10 @@
namespace UnitTest
{
class CustomManipulatorManager
: public AzToolsFramework::ManipulatorManager
class CustomManipulatorManager : public AzToolsFramework::ManipulatorManager
{
using ManagerBase = AzToolsFramework::ManipulatorManager;
public:
using ManagerBase::ManagerBase;
@@ -27,17 +27,17 @@ namespace UnitTest
}
};
class AzManipulatorTestFrameworkCustomManagerTestFixture
: public LinearManipulatorTestFixture
class AzManipulatorTestFrameworkCustomManagerTestFixture : public LinearManipulatorTestFixture
{
protected:
AzManipulatorTestFrameworkCustomManagerTestFixture()
: LinearManipulatorTestFixture(AzToolsFramework::ManipulatorManagerId(AZ::Crc32("TestManipulatorManagerId"))) {}
: LinearManipulatorTestFixture(AzToolsFramework::ManipulatorManagerId(AZ::Crc32("TestManipulatorManagerId")))
{
}
void SetUpEditorFixtureImpl() override
{
m_manipulatorManager =
AZStd::make_shared<CustomManipulatorManager>(m_manipulatorManagerId);
m_manipulatorManager = AZStd::make_shared<CustomManipulatorManager>(m_manipulatorManagerId);
LinearManipulatorTestFixture::SetUpEditorFixtureImpl();
}
@@ -115,9 +115,9 @@ namespace UnitTest
m_linearManipulator->InstallMouseMoveCallback(
[&movementAlongAxis](const AzToolsFramework::LinearManipulator::Action& action)
{
movementAlongAxis = action.m_current.m_localPositionOffset;
});
{
movementAlongAxis = action.m_current.m_localPositionOffset;
});
// consume the mouse down event
m_manipulatorManager->ConsumeViewportMousePress(m_interaction);
@@ -141,4 +141,3 @@ namespace UnitTest
EXPECT_EQ(movementAlongAxis, expectedPositionAfterMovementAlongAxis);
}
} // namespace UnitTest
@@ -12,6 +12,7 @@
#include "AzManipulatorTestFrameworkTestFixtures.h"
#include <AZTestShared/Math/MathTestHelpers.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
@@ -22,7 +23,6 @@
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
#include <AzToolsFramework/Manipulators/PlanarManipulator.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AZTestShared/Math/MathTestHelpers.h>
namespace UnitTest
{
@@ -94,7 +94,8 @@ namespace UnitTest
template<typename Manipulator>
void ValidateManipulatorSnappingBehavior(
AZStd::shared_ptr<Manipulator> manipulator, AzManipulatorTestFramework::ImmediateModeActionDispatcher* actionDispatcher,
AZStd::shared_ptr<Manipulator> manipulator,
AzManipulatorTestFramework::ImmediateModeActionDispatcher* actionDispatcher,
const AzFramework::CameraState& cameraState)
{
manipulator->SetLocalOrientation(AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(180.0f, 0.0f, 135.0f)));
@@ -15,8 +15,7 @@
namespace UnitTest
{
class AValidViewportInteraction
: public ToolsApplicationFixture
class AValidViewportInteraction : public ToolsApplicationFixture
{
public:
AValidViewportInteraction()
@@ -27,8 +26,7 @@ namespace UnitTest
protected:
void SetUpEditorFixtureImpl() override
{
m_cameraState =
AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AZ::Vector2(800.0f, 600.0f));
m_cameraState = AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AZ::Vector2(800.0f, 600.0f));
}
public:
@@ -11,49 +11,48 @@
*/
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
namespace UnitTest
{
class AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture
: public ToolsApplicationFixture
class AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture : public ToolsApplicationFixture
{
protected:
struct State
{
State(AZStd::unique_ptr<AzManipulatorTestFramework::ManipulatorViewportInteraction> viewportManipulatorInteraction)
: m_viewportManipulatorInteraction(viewportManipulatorInteraction.release())
, m_actionDispatcher(AZStd::make_unique<AzManipulatorTestFramework::ImmediateModeActionDispatcher>(*m_viewportManipulatorInteraction))
, m_linearManipulator(
AzManipulatorTestFramework::CreateLinearManipulator(
m_viewportManipulatorInteraction->GetManipulatorManager().GetId(),
/*position=*/AZ::Vector3(0.0f, 50.0f, 0.0f),
/*radius=*/m_boundsRadius))
, m_actionDispatcher(
AZStd::make_unique<AzManipulatorTestFramework::ImmediateModeActionDispatcher>(*m_viewportManipulatorInteraction))
, m_linearManipulator(AzManipulatorTestFramework::CreateLinearManipulator(
m_viewportManipulatorInteraction->GetManipulatorManager().GetId(),
/*position=*/AZ::Vector3(0.0f, 50.0f, 0.0f),
/*radius=*/m_boundsRadius))
{
// default sanity check call backs
m_linearManipulator->InstallLeftMouseDownCallback(
[this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action)
{
m_receivedLeftMouseDown = true;
});
{
m_receivedLeftMouseDown = true;
});
m_linearManipulator->InstallMouseMoveCallback(
[this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action)
{
m_receivedMouseMove = true;
});
{
m_receivedMouseMove = true;
});
m_linearManipulator->InstallLeftMouseUpCallback(
[this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action)
{
m_receivedLeftMouseUp = true;
});
{
m_receivedLeftMouseUp = true;
});
}
~State() = default;
@@ -79,13 +78,12 @@ namespace UnitTest
protected:
void SetUpEditorFixtureImpl() override
{
m_directState = AZStd::make_unique<State>(
AZStd::make_unique<AzManipulatorTestFramework::DirectCallManipulatorViewportInteraction>());
m_busState = AZStd::make_unique<State>(
AZStd::make_unique<AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction>());
m_directState =
AZStd::make_unique<State>(AZStd::make_unique<AzManipulatorTestFramework::DirectCallManipulatorViewportInteraction>());
m_busState =
AZStd::make_unique<State>(AZStd::make_unique<AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction>());
m_cameraState =
AzFramework::CreateIdentityDefaultCamera(
AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
}
void TearDownEditorFixtureImpl() override
@@ -105,8 +103,7 @@ namespace UnitTest
{
// given a left mouse down ray in world space
// consume the mouse down and up events
state.m_actionDispatcher
->CameraState(m_cameraState)
state.m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(AzManipulatorTestFramework::GetCameraStateViewportCenter(m_cameraState))
->MouseLButtonDown()
->Trace("Expecting left mouse button down")
@@ -126,31 +123,27 @@ namespace UnitTest
->ExpectTrue(state.m_receivedLeftMouseUp)
->ExpectTrue(state.m_receivedMouseMove)
->ExpectFalse(state.m_linearManipulator->PerformingAction())
->ExpectManipulatorNotBeingInteracted()
;
->ExpectManipulatorNotBeingInteracted();
}
void AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture::ConsumeViewportMouseMoveHover(State& state)
{
// given a left mouse down ray in world space
// consume the mouse move event
state.m_actionDispatcher
->CameraState(m_cameraState)
state.m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(AzManipulatorTestFramework::GetCameraStateViewportCenter(m_cameraState))
->ExpectFalse(state.m_linearManipulator->PerformingAction())
->ExpectManipulatorNotBeingInteracted()
->ExpectFalse(state.m_receivedLeftMouseDown)
->ExpectFalse(state.m_receivedMouseMove)
->ExpectFalse(state.m_receivedLeftMouseUp)
;
->ExpectFalse(state.m_receivedLeftMouseUp);
}
void AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture::ConsumeViewportMouseMoveActive(State& state)
{
// given a left mouse down ray in world space
// consume the mouse move event
state.m_actionDispatcher
->CameraState(m_cameraState)
state.m_actionDispatcher->CameraState(m_cameraState)
->MouseLButtonDown()
->MousePosition(AzManipulatorTestFramework::GetCameraStateViewportCenter(m_cameraState))
->ExpectTrue(state.m_linearManipulator->PerformingAction())
@@ -158,8 +151,7 @@ namespace UnitTest
->MouseLButtonUp()
->ExpectTrue(state.m_receivedLeftMouseDown)
->ExpectTrue(state.m_receivedMouseMove)
->ExpectTrue(state.m_receivedLeftMouseUp)
;
->ExpectTrue(state.m_receivedLeftMouseUp);
}
void AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture::MoveManipulatorAlongAxis(State& state)
@@ -176,8 +168,7 @@ namespace UnitTest
// adjusted final world position taking into account the manipulator position relative to the camera
const auto finalPositionWorldAdjusted = finalPositionWorld - (vectorToInitialPositionWorld * scaledRadiusBound);
// calculate the position in screen space of the initial position of the manipulator
const auto initialPositionScreen =
AzFramework::WorldToScreen(initialPositionWorld, m_cameraState);
const auto initialPositionScreen = AzFramework::WorldToScreen(initialPositionWorld, m_cameraState);
// calculate the position in screen space of the final position of the manipulator
const auto finalPositionScreen = AzFramework::WorldToScreen(finalPositionWorldAdjusted, m_cameraState);
@@ -185,12 +176,11 @@ namespace UnitTest
state.m_linearManipulator->InstallMouseMoveCallback(
[&movementAlongAxis](const AzToolsFramework::LinearManipulator::Action& action)
{
movementAlongAxis = action.LocalPosition();
});
{
movementAlongAxis = action.LocalPosition();
});
state.m_actionDispatcher
->CameraState(m_cameraState)
state.m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(initialPositionScreen)
->MouseLButtonDown()
->ExpectTrue(state.m_linearManipulator->PerformingAction())
@@ -199,8 +189,7 @@ namespace UnitTest
->MouseLButtonUp()
->ExpectTrue(state.m_receivedLeftMouseDown)
->ExpectTrue(state.m_receivedLeftMouseUp)
->ExpectTrue(movementAlongAxis.IsClose(finalPositionWorld, 0.01f))
;
->ExpectTrue(movementAlongAxis.IsClose(finalPositionWorld, 0.01f));
}
TEST_F(AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture, ConsumeViewportLeftMouseClick)
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon / Locked Status</title>
<g id="Icon-/-Locked-Status" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-9">
<g id="Icons-/-Icon-Grid" transform="translate(17.000000, 15.000000)" fill="#FFFFFF">
<path d="M3,0 C4.03553391,-1.90224492e-16 4.875,0.839466094 4.875,1.875 L4.875,3.6 L6,3.6 L6,8 L0,8 L0,3.6 L1.125,3.6 L1.125,1.875 C1.125,0.839466094 1.96446609,1.90224492e-16 3,0 Z M3.375,5.2 L2.625,5.2 L2.625,6.4 L3.375,6.4 L3.375,5.2 Z M3,0.8 C2.37867966,0.8 1.875,1.30367966 1.875,1.925 L1.875,1.925 L1.875,3.6 L4.125,3.6 L4.125,1.925 C4.125,1.30367966 3.62132034,0.8 3,0.8 Z" id="Combined-Shape"></path>
</g>
<rect id="Rectangle" fill="#F9F9F9" opacity="0" x="0" y="0" width="24" height="24"></rect>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1017 B

@@ -356,7 +356,8 @@
<file>img/UI20/toolbar/Load.svg</file>
<file>img/UI20/toolbar/Local.svg</file>
<file>img/UI20/toolbar/Locked.svg</file>
<file>img/UI20/toolbar/LUA.svg</file>
<file>img/UI20/toolbar/Locked_Status.svg</file>
<file>img/UI20/toolbar/LUA.svg</file>
<file>img/UI20/toolbar/Material.svg</file>
<file>img/UI20/toolbar/Measure.svg</file>
<file>img/UI20/toolbar/Move.svg</file>
@@ -1,28 +1,32 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "AngularManipulator.h"
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzToolsFramework/Manipulators/ManipulatorView.h>
#include <AzToolsFramework/Manipulators/ManipulatorSnapping.h>
#include <AzToolsFramework/Manipulators/ManipulatorView.h>
namespace AzToolsFramework
{
static const float s_circularRotateThresholdDegrees = 80.0f;
static const float CircularRotateThresholdDegrees = 80.0f;
AngularManipulator::ActionInternal AngularManipulator::CalculateManipulationDataStart(
const Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Transform& localTransform,
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, const float rayDistance)
const Fixed& fixed,
const AZ::Transform& worldFromLocal,
const AZ::Transform& localTransform,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const float rayDistance)
{
const AZ::Transform worldFromLocalWithTransform = worldFromLocal * localTransform;
const AZ::Vector3 worldAxis = TransformDirectionNoScaling(worldFromLocalWithTransform, fixed.m_axis);
@@ -35,7 +39,7 @@ namespace AzToolsFramework
// if angular manipulator axis is at right angles to us, use initial ray direction
// as plane normal and use hit position on manipulator as plane point
const float pickAngle = AZ::RadToDeg(AZ::Acos(AZ::Abs(rayDirection.Dot(worldAxis))));
if (pickAngle > s_circularRotateThresholdDegrees)
if (pickAngle > CircularRotateThresholdDegrees)
{
actionInternal.m_start.m_planeNormal = -rayDirection;
actionInternal.m_start.m_planePoint = rayOrigin + rayDirection * rayDistance;
@@ -43,8 +47,8 @@ namespace AzToolsFramework
// store initial world hit position
Internal::CalculateRayPlaneIntersectingPoint(
rayOrigin, rayDirection, actionInternal.m_start.m_planePoint,
actionInternal.m_start.m_planeNormal, actionInternal.m_current.m_worldHitPosition);
rayOrigin, rayDirection, actionInternal.m_start.m_planePoint, actionInternal.m_start.m_planeNormal,
actionInternal.m_current.m_worldHitPosition);
// store entity transform (to go from local to world space)
// and store our own starting local transform
@@ -56,31 +60,33 @@ namespace AzToolsFramework
}
AngularManipulator::Action AngularManipulator::CalculateManipulationDataAction(
const Fixed& fixed, ActionInternal& actionInternal, const AZ::Transform& worldFromLocal,
const AZ::Transform& localTransform, const bool snapping, const float angleStepDegrees,
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection,
const Fixed& fixed,
ActionInternal& actionInternal,
const AZ::Transform& worldFromLocal,
const AZ::Transform& localTransform,
const bool snapping,
const float angleStepDegrees,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const ViewportInteraction::KeyboardModifiers keyboardModifiers)
{
const AZ::Transform worldFromLocalWithTransform = worldFromLocal * localTransform;
const AZ::Vector3 worldAxis = TransformDirectionNoScaling(worldFromLocalWithTransform, fixed.m_axis);
AZ::Vector3 worldHitPosition = AZ::Vector3::CreateZero();
Internal::CalculateRayPlaneIntersectingPoint(rayOrigin, rayDirection,
actionInternal.m_start.m_planePoint, actionInternal.m_start.m_planeNormal,
worldHitPosition);
Internal::CalculateRayPlaneIntersectingPoint(
rayOrigin, rayDirection, actionInternal.m_start.m_planePoint, actionInternal.m_start.m_planeNormal, worldHitPosition);
// get vector from center of rotation for current and previous frame
const AZ::Vector3 center = worldFromLocalWithTransform.GetTranslation();
const AZ::Vector3 currentWorldHitVector = (worldHitPosition - center).GetNormalizedSafe();
const AZ::Vector3 previousWorldHitVector =
(actionInternal.m_current.m_worldHitPosition - center).GetNormalizedSafe();
const AZ::Vector3 previousWorldHitVector = (actionInternal.m_current.m_worldHitPosition - center).GetNormalizedSafe();
// calculate which direction we rotated
const AZ::Vector3 worldAxisRight = worldAxis.Cross(previousWorldHitVector);
const float rotateSign = Sign(currentWorldHitVector.Dot(worldAxisRight));
// how far did we rotate this frame
const float rotationAngleRad = AZ::Acos(AZ::GetMin<float>(
1.0f, currentWorldHitVector.Dot(previousWorldHitVector)));
const float rotationAngleRad = AZ::Acos(AZ::GetMin<float>(1.0f, currentWorldHitVector.Dot(previousWorldHitVector)));
actionInternal.m_current.m_worldHitPosition = worldHitPosition;
// if we're snapping, only increment current radians when we know
@@ -148,16 +154,13 @@ namespace AzToolsFramework
// calculate initial state when mouse press first happens
m_actionInternal = CalculateManipulationDataStart(
m_fixed, TransformNormalizedScale(GetSpace()), TransformNormalizedScale(GetLocalTransform()),
interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection,
rayIntersectionDistance);
interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection, rayIntersectionDistance);
if (m_onLeftMouseDownCallback)
{
m_onLeftMouseDownCallback(CalculateManipulationDataAction(
m_fixed, m_actionInternal, m_actionInternal.m_start.m_worldFromLocal,
m_actionInternal.m_start.m_localTransform, snapping, angleStep,
interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection,
interaction.m_keyboardModifiers));
m_fixed, m_actionInternal, m_actionInternal.m_start.m_worldFromLocal, m_actionInternal.m_start.m_localTransform, snapping,
angleStep, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection, interaction.m_keyboardModifiers));
}
}
@@ -167,12 +170,9 @@ namespace AzToolsFramework
{
// calculate delta rotation
m_onMouseMoveCallback(CalculateManipulationDataAction(
m_fixed, m_actionInternal, m_actionInternal.m_start.m_worldFromLocal,
m_actionInternal.m_start.m_localTransform,
AngleSnapping(interaction.m_interactionId.m_viewportId),
AngleStep(interaction.m_interactionId.m_viewportId),
interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection,
interaction.m_keyboardModifiers));
m_fixed, m_actionInternal, m_actionInternal.m_start.m_worldFromLocal, m_actionInternal.m_start.m_localTransform,
AngleSnapping(interaction.m_interactionId.m_viewportId), AngleStep(interaction.m_interactionId.m_viewportId),
interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection, interaction.m_keyboardModifiers));
}
}
@@ -181,12 +181,9 @@ namespace AzToolsFramework
if (m_onLeftMouseUpCallback)
{
m_onLeftMouseUpCallback(CalculateManipulationDataAction(
m_fixed, m_actionInternal, m_actionInternal.m_start.m_worldFromLocal,
m_actionInternal.m_start.m_localTransform,
AngleSnapping(interaction.m_interactionId.m_viewportId),
AngleStep(interaction.m_interactionId.m_viewportId),
interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection,
interaction.m_keyboardModifiers));
m_fixed, m_actionInternal, m_actionInternal.m_start.m_worldFromLocal, m_actionInternal.m_start.m_localTransform,
AngleSnapping(interaction.m_interactionId.m_viewportId), AngleStep(interaction.m_interactionId.m_viewportId),
interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection, interaction.m_keyboardModifiers));
}
}
@@ -197,12 +194,9 @@ namespace AzToolsFramework
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
m_manipulatorView->Draw(
GetManipulatorManagerId(), managerState,
GetManipulatorId(), {
ApplySpace(GetLocalTransform()), GetNonUniformScale(),
AZ::Vector3::CreateZero(), MouseOver()
},
debugDisplay, cameraState, mouseInteraction);
GetManipulatorManagerId(), managerState, GetManipulatorId(),
{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay, cameraState,
mouseInteraction);
}
void AngularManipulator::SetAxis(const AZ::Vector3& axis)
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -22,14 +22,14 @@ namespace AzToolsFramework
{
class ManipulatorView;
/// AngularManipulator serves as a visual tool for users to change a component's property based on rotation
/// around an axis. The rotation angle increases if the rotation goes counter clock-wise when looking
/// in the opposite direction the rotation axis points to.
//! AngularManipulator serves as a visual tool for users to change a component's property based on rotation
//! around an axis. The rotation angle increases if the rotation goes counter clock-wise when looking
//! in the opposite direction the rotation axis points to.
class AngularManipulator
: public BaseManipulator
, public ManipulatorSpaceWithLocalTransform
{
/// Private constructor.
//! Private constructor.
explicit AngularManipulator(const AZ::Transform& worldFromLocal);
public:
@@ -42,33 +42,36 @@ namespace AzToolsFramework
~AngularManipulator() = default;
/// A Manipulator must only be created and managed through a shared_ptr.
//! A Manipulator must only be created and managed through a shared_ptr.
static AZStd::shared_ptr<AngularManipulator> MakeShared(const AZ::Transform& worldFromLocal);
/// The state of the manipulator at the start of an interaction.
//! The state of the manipulator at the start of an interaction.
struct Start
{
AZ::Quaternion m_space; ///< Starting orientation space of manipulator.
AZ::Quaternion m_rotation; ///< Starting local rotation of the manipulator.
AZ::Quaternion m_space; //!< Starting orientation space of manipulator.
AZ::Quaternion m_rotation; //!< Starting local rotation of the manipulator.
};
/// The state of the manipulator during an interaction.
//! The state of the manipulator during an interaction.
struct Current
{
AZ::Quaternion m_delta; ///< Amount of rotation to apply to manipulator during action.
AZ::Quaternion m_delta; //!< Amount of rotation to apply to manipulator during action.
};
/// Mouse action data used by MouseActionCallback (wraps Start and Current manipulator state).
//! Mouse action data used by MouseActionCallback (wraps Start and Current manipulator state).
struct Action
{
Start m_start;
Current m_current;
ViewportInteraction::KeyboardModifiers m_modifiers;
AZ::Quaternion LocalOrientation() const { return m_start.m_rotation * m_current.m_delta; }
AZ::Quaternion LocalOrientation() const
{
return m_start.m_rotation * m_current.m_delta;
}
};
/// This is the function signature of callbacks that will be invoked whenever a manipulator
/// is clicked on or dragged.
//! This is the function signature of callbacks that will be invoked whenever a manipulator
//! is clicked on or dragged.
using MouseActionCallback = AZStd::function<void(const Action&)>;
void InstallLeftMouseDownCallback(const MouseActionCallback& onMouseDownCallback);
@@ -82,46 +85,49 @@ namespace AzToolsFramework
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
void SetAxis(const AZ::Vector3& axis);
const AZ::Vector3& GetAxis() const { return m_fixed.m_axis; }
const AZ::Vector3& GetAxis() const
{
return m_fixed.m_axis;
}
void SetView(AZStd::unique_ptr<ManipulatorView>&& view);
ManipulatorView* GetView() const { return m_manipulatorView.get(); }
ManipulatorView* GetView() const
{
return m_manipulatorView.get();
}
private:
void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void SetBoundsDirtyImpl() override;
void InvalidateImpl() override;
/// Unchanging data set once for the angular manipulator.
//! Unchanging data set once for the angular manipulator.
struct Fixed
{
AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX(); ///< Axis for this angular manipulator to rotate around.
AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX(); //!< Axis for this angular manipulator to rotate around.
};
/// Initial data recorded when a press first happens with an angular manipulator.
//! Initial data recorded when a press first happens with an angular manipulator.
struct StartInternal
{
AZ::Transform m_worldFromLocal; ///< Initial transform when pressed.
AZ::Transform m_localTransform; ///< Additional transform (offset) to apply to manipulator.
AZ::Vector3 m_planePoint; ///< Position on plane to use for ray intersection.
AZ::Vector3 m_planeNormal; ///< Normal of plane to use for ray intersection.
AZ::Transform m_worldFromLocal; //!< Initial transform when pressed.
AZ::Transform m_localTransform; //!< Additional transform (offset) to apply to manipulator.
AZ::Vector3 m_planePoint; //!< Position on plane to use for ray intersection.
AZ::Vector3 m_planeNormal; //!< Normal of plane to use for ray intersection.
};
/// Current data recorded each frame during an interaction with an angular manipulator.
//! Current data recorded each frame during an interaction with an angular manipulator.
struct CurrentInternal
{
float m_preSnapRadians = 0.0f; ///< Amount of rotation before a snap (snap increment accumulator).
float m_radians = 0.0f; ///< Amount of rotation about the axis for this action.
AZ::Vector3 m_worldHitPosition; ///< Initial world space hit position.
float m_preSnapRadians = 0.0f; //!< Amount of rotation before a snap (snap increment accumulator).
float m_radians = 0.0f; //!< Amount of rotation about the axis for this action.
AZ::Vector3 m_worldHitPosition; //!< Initial world space hit position.
};
/// Wrap start and current internal data during an interaction with an angular manipulator.
//! Wrap start and current internal data during an interaction with an angular manipulator.
struct ActionInternal
{
StartInternal m_start;
@@ -135,16 +141,25 @@ namespace AzToolsFramework
MouseActionCallback m_onLeftMouseUpCallback = nullptr;
MouseActionCallback m_onMouseMoveCallback = nullptr;
AZStd::unique_ptr<ManipulatorView> m_manipulatorView; ///< Look of manipulator.
AZStd::unique_ptr<ManipulatorView> m_manipulatorView; //!< Look of manipulator.
static ActionInternal CalculateManipulationDataStart(
const Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Transform& localTransform,
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float rayDistance);
const Fixed& fixed,
const AZ::Transform& worldFromLocal,
const AZ::Transform& localTransform,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
float rayDistance);
static Action CalculateManipulationDataAction(
const Fixed& fixed, ActionInternal& actionInternal, const AZ::Transform& worldFromLocal,
const AZ::Transform& localTransform, bool snapping, float angleStepDegrees,
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection,
const Fixed& fixed,
ActionInternal& actionInternal,
const AZ::Transform& worldFromLocal,
const AZ::Transform& localTransform,
bool snapping,
float angleStepDegrees,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
ViewportInteraction::KeyboardModifiers keyboardModifiers);
};
} // namespace AzToolsFramework
@@ -1,33 +1,30 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "BaseManipulator.h"
#include <AzCore/Math/IntersectSegment.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
namespace AzToolsFramework
{
AZ_CVAR(
bool, cl_manipulatorDrawDebug, false, nullptr, AZ::ConsoleFunctorFlags::Null,
"Enable debug drawing for Manipulators");
AZ_CVAR(bool, cl_manipulatorDrawDebug, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Enable debug drawing for Manipulators");
const AZ::Color BaseManipulator::s_defaultMouseOverColor = AZ::Color(1.0f, 1.0f, 0.0f, 1.0f); // yellow
AZ_CLASS_ALLOCATOR_IMPL(BaseManipulator, AZ::SystemAllocator, 0)
static bool EntityIdAndEntityComponentIdComparison(
const AZ::EntityId entityId, const AZ::EntityComponentIdPair& entityComponentId)
static bool EntityIdAndEntityComponentIdComparison(const AZ::EntityId entityId, const AZ::EntityComponentIdPair& entityComponentId)
{
return entityId == entityComponentId.GetEntityId();
}
@@ -38,8 +35,7 @@ namespace AzToolsFramework
EndUndoBatch();
}
bool BaseManipulator::OnLeftMouseDown(
const ViewportInteraction::MouseInteraction& interaction, const float rayIntersectionDistance)
bool BaseManipulator::OnLeftMouseDown(const ViewportInteraction::MouseInteraction& interaction, const float rayIntersectionDistance)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -57,8 +53,7 @@ namespace AzToolsFramework
(*this.*m_onLeftMouseDownImpl)(interaction, rayIntersectionDistance);
ToolsApplicationNotificationBus::Broadcast(
&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values);
ToolsApplicationNotificationBus::Broadcast(&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values);
return true;
}
@@ -66,8 +61,7 @@ namespace AzToolsFramework
return false;
}
bool BaseManipulator::OnRightMouseDown(
const ViewportInteraction::MouseInteraction& interaction, const float rayIntersectionDistance)
bool BaseManipulator::OnRightMouseDown(const ViewportInteraction::MouseInteraction& interaction, const float rayIntersectionDistance)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -85,8 +79,7 @@ namespace AzToolsFramework
(*this.*m_onRightMouseDownImpl)(interaction, rayIntersectionDistance);
ToolsApplicationNotificationBus::Broadcast(
&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values);
ToolsApplicationNotificationBus::Broadcast(&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values);
return true;
}
@@ -118,8 +111,7 @@ namespace AzToolsFramework
EndUndoBatch();
}
bool BaseManipulator::OnMouseOver(
const ManipulatorId manipulatorId, const ViewportInteraction::MouseInteraction& interaction)
bool BaseManipulator::OnMouseOver(const ManipulatorId manipulatorId, const ViewportInteraction::MouseInteraction& interaction)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -132,8 +124,7 @@ namespace AzToolsFramework
{
OnMouseWheelImpl(interaction);
ToolsApplicationNotificationBus::Broadcast(
&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values);
ToolsApplicationNotificationBus::Broadcast(&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values);
}
void BaseManipulator::OnMouseMove(const ViewportInteraction::MouseInteraction& interaction)
@@ -142,16 +133,13 @@ namespace AzToolsFramework
if (!m_performingAction)
{
AZ_Warning(
"Manipulators", false,
"MouseMove action received, but this manipulator is not performing an action");
AZ_Warning("Manipulators", false, "MouseMove action received, but this manipulator is not performing an action");
return;
}
// ensure property grid (entity inspector) values are refreshed
ToolsApplicationNotificationBus::Broadcast(
&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values);
ToolsApplicationNotificationBus::Broadcast(&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values);
OnMouseMoveImpl(interaction);
}
@@ -170,16 +158,14 @@ namespace AzToolsFramework
Unregister();
}
ManipulatorManagerRequestBus::Event(managerId,
&ManipulatorManagerRequestBus::Events::RegisterManipulator, shared_from_this());
ManipulatorManagerRequestBus::Event(managerId, &ManipulatorManagerRequestBus::Events::RegisterManipulator, shared_from_this());
}
void BaseManipulator::Unregister()
{
// if the manipulator has already been unregistered, the m_manipulatorManagerId
// should be invalid which makes the call below a no-op.
ManipulatorManagerRequestBus::Event(m_manipulatorManagerId,
&ManipulatorManagerRequestBus::Events::UnregisterManipulator, this);
ManipulatorManagerRequestBus::Event(m_manipulatorManagerId, &ManipulatorManagerRequestBus::Events::UnregisterManipulator, this);
}
void BaseManipulator::Invalidate()
@@ -197,8 +183,7 @@ namespace AzToolsFramework
if (m_performingAction)
{
AZ_Warning(
"Manipulators", false,
"MouseDown action received, but the manipulator (id: %d) is still performing an action",
"Manipulators", false, "MouseDown action received, but the manipulator (id: %d) is still performing an action",
GetManipulatorId());
return;
@@ -214,8 +199,7 @@ namespace AzToolsFramework
if (!m_performingAction)
{
AZ_Warning(
"Manipulators", false,
"MouseUp action received, but this manipulator (id: %d) didn't receive MouseDown action before",
"Manipulators", false, "MouseUp action received, but this manipulator (id: %d) didn't receive MouseDown action before",
GetManipulatorId());
return;
}
@@ -263,13 +247,13 @@ namespace AzToolsFramework
if (entityComponentIdPair.GetComponentId() != AZ::InvalidComponentId)
{
PropertyEditorEntityChangeNotificationBus::Event(
entityComponentIdPair.GetEntityId(),
&PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged,
entityComponentIdPair.GetEntityId(), &PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged,
entityComponentIdPair.GetComponentId());
}
else
{
AZ_Warning("Manipulators", false,
AZ_Warning(
"Manipulators", false,
"This Manipulator was only registered with an EntityId and not an EntityComponentIdPair. "
"Please use AddEntityComponentIdPair() instead of AddEntityId() when registering what this "
"Manipulator is changing.");
@@ -280,8 +264,7 @@ namespace AzToolsFramework
for (const AZ::Component* component : entity->GetComponents())
{
PropertyEditorEntityChangeNotificationBus::Event(
entity->GetId(), &PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged,
component->GetId());
entity->GetId(), &PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged, component->GetId());
}
}
}
@@ -298,9 +281,7 @@ namespace AzToolsFramework
{
// look for a match (keep looking in case we have several entity ids with different component ids)
const auto entityComponentPairId =
m_entityComponentIdPairs.find_as(
entityId, AZStd::hash<AZ::EntityId>(),
&EntityIdAndEntityComponentIdComparison);
m_entityComponentIdPairs.find_as(entityId, AZStd::hash<AZ::EntityId>(), &EntityIdAndEntityComponentIdComparison);
// update the afterErased variable so we can return an iterator
// to the correct position in the container.
@@ -334,9 +315,8 @@ namespace AzToolsFramework
bool BaseManipulator::HasEntityId(const AZ::EntityId entityId) const
{
return m_entityComponentIdPairs.find_as(
entityId, AZStd::hash<AZ::EntityId>(),
&EntityIdAndEntityComponentIdComparison) != m_entityComponentIdPairs.end();
return m_entityComponentIdPairs.find_as(entityId, AZStd::hash<AZ::EntityId>(), &EntityIdAndEntityComponentIdComparison) !=
m_entityComponentIdPairs.end();
}
bool BaseManipulator::HasEntityComponentIdPair(const AZ::EntityComponentIdPair& entityComponentIdPair) const
@@ -346,7 +326,8 @@ namespace AzToolsFramework
void Manipulators::Register(const ManipulatorManagerId manipulatorManagerId)
{
ProcessManipulators([manipulatorManagerId](BaseManipulator* manipulator)
ProcessManipulators(
[manipulatorManagerId](BaseManipulator* manipulator)
{
manipulator->Register(manipulatorManagerId);
});
@@ -354,7 +335,8 @@ namespace AzToolsFramework
void Manipulators::Unregister()
{
ProcessManipulators([](BaseManipulator* manipulator)
ProcessManipulators(
[](BaseManipulator* manipulator)
{
if (manipulator->Registered())
{
@@ -365,7 +347,8 @@ namespace AzToolsFramework
void Manipulators::SetBoundsDirty()
{
ProcessManipulators([](BaseManipulator* manipulator)
ProcessManipulators(
[](BaseManipulator* manipulator)
{
manipulator->SetBoundsDirty();
});
@@ -373,7 +356,8 @@ namespace AzToolsFramework
void Manipulators::AddEntityComponentIdPair(const AZ::EntityComponentIdPair& entityComponentIdPair)
{
ProcessManipulators([&entityComponentIdPair](BaseManipulator* manipulator)
ProcessManipulators(
[&entityComponentIdPair](BaseManipulator* manipulator)
{
manipulator->AddEntityComponentIdPair(entityComponentIdPair);
});
@@ -381,7 +365,8 @@ namespace AzToolsFramework
void Manipulators::RemoveEntityComponentIdPair(const AZ::EntityComponentIdPair& entityComponentIdPair)
{
ProcessManipulators([&entityComponentIdPair](BaseManipulator* manipulator)
ProcessManipulators(
[&entityComponentIdPair](BaseManipulator* manipulator)
{
manipulator->RemoveEntityComponentIdPair(entityComponentIdPair);
});
@@ -389,7 +374,8 @@ namespace AzToolsFramework
void Manipulators::RemoveEntityId(const AZ::EntityId entityId)
{
ProcessManipulators([entityId](BaseManipulator* manipulator)
ProcessManipulators(
[entityId](BaseManipulator* manipulator)
{
manipulator->RemoveEntityId(entityId);
});
@@ -398,7 +384,8 @@ namespace AzToolsFramework
bool Manipulators::PerformingAction()
{
bool performingAction = false;
ProcessManipulators([&performingAction](BaseManipulator* manipulator)
ProcessManipulators(
[&performingAction](BaseManipulator* manipulator)
{
if (manipulator->PerformingAction())
{
@@ -412,7 +399,8 @@ namespace AzToolsFramework
bool Manipulators::Registered()
{
bool registered = false;
ProcessManipulators([&registered](BaseManipulator* manipulator)
ProcessManipulators(
[&registered](BaseManipulator* manipulator)
{
if (manipulator->Registered())
{
@@ -470,8 +458,12 @@ namespace AzToolsFramework
namespace Internal
{
bool CalculateRayPlaneIntersectingPoint(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection,
const AZ::Vector3& pointOnPlane, const AZ::Vector3& planeNormal, AZ::Vector3& resultIntersectingPoint)
bool CalculateRayPlaneIntersectingPoint(
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const AZ::Vector3& pointOnPlane,
const AZ::Vector3& planeNormal,
AZ::Vector3& resultIntersectingPoint)
{
float t = 0.0f;
if (AZ::Intersect::IntersectRayPlane(rayOrigin, rayDirection, pointOnPlane, planeNormal, t) > 0)
@@ -484,11 +476,12 @@ namespace AzToolsFramework
}
AZ::Vector3 TryConstrainHitPositionToView(
const AZ::Vector3& currentLocalHitPosition, const AZ::Vector3& startLocalHitPosition,
const AZ::Transform& localFromWorld, const AzFramework::CameraState& cameraState)
const AZ::Vector3& currentLocalHitPosition,
const AZ::Vector3& startLocalHitPosition,
const AZ::Transform& localFromWorld,
const AzFramework::CameraState& cameraState)
{
if (currentLocalHitPosition.GetDistance(localFromWorld.TransformPoint(cameraState.m_position))
> cameraState.m_farClip)
if (currentLocalHitPosition.GetDistance(localFromWorld.TransformPoint(cameraState.m_position)) > cameraState.m_farClip)
{
return startLocalHitPosition;
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -22,13 +22,13 @@
#include <AzCore/std/containers/set.h>
#include <AzCore/std/smart_ptr/enable_shared_from_this.h>
#include <AzToolsFramework/Manipulators/ManipulatorBus.h>
#include "ManipulatorSpace.h"
#include <AzToolsFramework/Manipulators/ManipulatorSpace.h>
namespace AzFramework
{
struct CameraState;
class DebugDisplayRequests;
}
} // namespace AzFramework
namespace AzToolsFramework
{
@@ -46,9 +46,8 @@ namespace AzToolsFramework
struct ManipulatorManagerState;
/// The base class for manipulators, providing interfaces for users of manipulators to talk to.
class BaseManipulator
: public AZStd::enable_shared_from_this<BaseManipulator>
//! The base class for manipulators, providing interfaces for users of manipulators to talk to.
class BaseManipulator : public AZStd::enable_shared_from_this<BaseManipulator>
{
public:
AZ_CLASS_ALLOCATOR_DECL
@@ -61,139 +60,181 @@ namespace AzToolsFramework
using EntityComponentIds = AZStd::unordered_set<AZ::EntityComponentIdPair>;
/// Callback for the event when the mouse pointer is over this manipulator and the left mouse button is pressed.
/// @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera through the mouse pointer.
/// @param rayIntersectionDistance The parameter value in the ray's explicit equation that represents the intersecting point on the target manipulator in world space.
/// @return Return true if OnLeftMouseDownImpl was attached and will be used.
//! Callback for the event when the mouse pointer is over this manipulator and the left mouse button is pressed.
//! @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera
//! through the mouse pointer.
//! @param rayIntersectionDistance The parameter value in the ray's explicit equation that represents the intersecting point on the
//! target manipulator in world space.
//! @return Return true if OnLeftMouseDownImpl was attached and will be used.
bool OnLeftMouseDown(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance);
/// Callback for the event when this manipulator is active and the left mouse button is released.
/// @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera through the mouse pointer.
//! Callback for the event when this manipulator is active and the left mouse button is released.
//! @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera
//! through the mouse pointer.
void OnLeftMouseUp(const ViewportInteraction::MouseInteraction& interaction);
/// Callback for the event when the mouse pointer is over this manipulator and the right mouse button is pressed .
/// @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera through the mouse pointer.
/// @param rayIntersectionDistance The parameter value in the ray's explicit equation that represents the intersecting point on the target manipulator in world space.
/// @return Return true if OnRightMouseDownImpl was attached and will be used.
//! Callback for the event when the mouse pointer is over this manipulator and the right mouse button is pressed .
//! @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera
//! through the mouse pointer.
//! @param rayIntersectionDistance The parameter value in the ray's explicit equation that represents the intersecting point on the
//! target manipulator in world space.
//! @return Return true if OnRightMouseDownImpl was attached and will be used.
bool OnRightMouseDown(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance);
/// Callback for the event when this manipulator is active and the right mouse button is released.
/// @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera through the mouse pointer.
//! Callback for the event when this manipulator is active and the right mouse button is released.
//! @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera
//! through the mouse pointer.
void OnRightMouseUp(const ViewportInteraction::MouseInteraction& interaction);
/// Callback for the event when this manipulator is active and the mouse is moved.
/// @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera through the mouse pointer.
//! Callback for the event when this manipulator is active and the mouse is moved.
//! @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera
//! through the mouse pointer.
void OnMouseMove(const ViewportInteraction::MouseInteraction& interaction);
/// Callback for the event when this manipulator is active and the mouse wheel is scrolled.
/// @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera through the mouse pointer.
//! Callback for the event when this manipulator is active and the mouse wheel is scrolled.
//! @param interaction It contains various mouse states when the event happens, as well as a ray shooting from the viewing camera
//! through the mouse pointer.
void OnMouseWheel(const ViewportInteraction::MouseInteraction& interaction);
/// This function changes the state indicating whether the manipulator is under the mouse pointer.
/// It is called in the event of OnMouseMove and OnMouseWheel only when there is no manipulator currently performing actions.
//! This function changes the state indicating whether the manipulator is under the mouse pointer.
//! It is called in the event of OnMouseMove and OnMouseWheel only when there is no manipulator currently performing actions.
bool OnMouseOver(ManipulatorId manipulatorId, const ViewportInteraction::MouseInteraction& interaction);
/// Register itself to a manipulator manager so that it can receive various mouse events and perform manipulations.
/// @param managerId The id identifying a unique manipulator manager.
//! Register itself to a manipulator manager so that it can receive various mouse events and perform manipulations.
//! @param managerId The id identifying a unique manipulator manager.
void Register(ManipulatorManagerId managerId);
/// Unregister itself from the manipulator manager it was registered with.
//! Unregister itself from the manipulator manager it was registered with.
void Unregister();
/// Bounds will need to be recalculated next time we render.
//! Bounds will need to be recalculated next time we render.
void SetBoundsDirty();
/// Is this manipulator currently registered with a manipulator manager.
//! Is this manipulator currently registered with a manipulator manager.
bool Registered() const
{
return m_manipulatorId != InvalidManipulatorId &&
m_manipulatorManagerId != InvalidManipulatorManagerId;
return m_manipulatorId != InvalidManipulatorId && m_manipulatorManagerId != InvalidManipulatorManagerId;
}
/// Is the manipulator in the middle of an action (between mouse down and mouse up).
bool PerformingAction() const { return m_performingAction; }
//! Is the manipulator in the middle of an action (between mouse down and mouse up).
bool PerformingAction() const
{
return m_performingAction;
}
/// Is the mouse currently over the manipulator (intersecting manipulator bound).
bool MouseOver() const { return m_mouseOver; }
//! Is the mouse currently over the manipulator (intersecting manipulator bound).
bool MouseOver() const
{
return m_mouseOver;
}
/// The unique id of this manipulator.
ManipulatorId GetManipulatorId() const { return m_manipulatorId; }
//! The unique id of this manipulator.
ManipulatorId GetManipulatorId() const
{
return m_manipulatorId;
}
/// The unique id of the manager this manipulator was registered with.
ManipulatorManagerId GetManipulatorManagerId() const { return m_manipulatorManagerId; }
//! The unique id of the manager this manipulator was registered with.
ManipulatorManagerId GetManipulatorManagerId() const
{
return m_manipulatorManagerId;
}
/// Returns all EntityComponentIdPairs associated with this manipulator.
//! Returns all EntityComponentIdPairs associated with this manipulator.
const EntityComponentIds& EntityComponentIdPairs() const
{
return m_entityComponentIdPairs;
}
/// Add an entity and component the manipulator is responsible for.
//! Add an entity and component the manipulator is responsible for.
void AddEntityComponentIdPair(const AZ::EntityComponentIdPair& entityComponentIdPair);
/// Remove an entity from being affected by this manipulator.
/// @note All components on this entity registered with the manipulator will be removed.
//! Remove an entity from being affected by this manipulator.
//! @note All components on this entity registered with the manipulator will be removed.
EntityComponentIds::iterator RemoveEntityId(AZ::EntityId entityId);
/// Remove a specific component (via a EntityComponentIdPair) being affected by this manipulator.
//! Remove a specific component (via a EntityComponentIdPair) being affected by this manipulator.
EntityComponentIds::iterator RemoveEntityComponentIdPair(const AZ::EntityComponentIdPair& entityComponentIdPair);
/// Is this entity currently being tracked by this manipulator.
//! Is this entity currently being tracked by this manipulator.
bool HasEntityId(AZ::EntityId entityId) const;
/// Is this entity component pair currently being tracked by this manipulator.
//! Is this entity component pair currently being tracked by this manipulator.
bool HasEntityComponentIdPair(const AZ::EntityComponentIdPair& entityComponentIdPair) const;
/// Forward a mouse over event in a case where we need the manipulator to immediately refresh.
/// @note Only call this when a mouse over event has just happened.
//! Forward a mouse over event in a case where we need the manipulator to immediately refresh.
//! @note Only call this when a mouse over event has just happened.
void ForwardMouseOverEvent(const ViewportInteraction::MouseInteraction& interaction);
static const AZ::Color s_defaultMouseOverColor;
protected:
/// Protected constructor.
//! Protected constructor.
BaseManipulator() = default;
/// Called when unregistering - users of manipulators should not call it directly.
//! Called when unregistering - users of manipulators should not call it directly.
void Invalidate();
/// The implementation to override in a derived class for Invalidate.
virtual void InvalidateImpl() {}
//! The implementation to override in a derived class for Invalidate.
virtual void InvalidateImpl()
{
}
/// The implementation to override in a derived class for OnLeftMouseDown.
/// Note: When implementing this function you must also call AttachLeftMouseDownImpl to ensure
/// m_onLeftMouseDownImpl is set to OnLeftMouseDownImpl, otherwise it will not be called
virtual void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& /*interaction*/, float /*rayIntersectionDistance*/) {}
void AttachLeftMouseDownImpl() { m_onLeftMouseDownImpl = &BaseManipulator::OnLeftMouseDownImpl; }
//! The implementation to override in a derived class for OnLeftMouseDown.
//! Note: When implementing this function you must also call AttachLeftMouseDownImpl to ensure
//! m_onLeftMouseDownImpl is set to OnLeftMouseDownImpl, otherwise it will not be called
virtual void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& /*interaction*/, float /*rayIntersectionDistance*/)
{
}
/// The implementation to override in a derived class for OnRightMouseDown.
/// Note: When implementing this function you must also call AttachRightMouseDownImpl to ensure
/// m_onRightMouseDownImpl is set to OnRightMouseDownImpl, otherwise it will not be called
virtual void OnRightMouseDownImpl(
const ViewportInteraction::MouseInteraction& /*interaction*/, float /*rayIntersectionDistance*/) {}
void AttachRightMouseDownImpl() { m_onRightMouseDownImpl = &BaseManipulator::OnRightMouseDownImpl; }
void AttachLeftMouseDownImpl()
{
m_onLeftMouseDownImpl = &BaseManipulator::OnLeftMouseDownImpl;
}
/// The implementation to override in a derived class for OnLeftMouseUp.
virtual void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& /*interaction*/) {}
//! The implementation to override in a derived class for OnRightMouseDown.
//! Note: When implementing this function you must also call AttachRightMouseDownImpl to ensure
//! m_onRightMouseDownImpl is set to OnRightMouseDownImpl, otherwise it will not be called
virtual void OnRightMouseDownImpl(const ViewportInteraction::MouseInteraction& /*interaction*/, float /*rayIntersectionDistance*/)
{
}
/// The implementation to override in a derived class for OnRightMouseUp.
virtual void OnRightMouseUpImpl(const ViewportInteraction::MouseInteraction& /*interaction*/) {}
void AttachRightMouseDownImpl()
{
m_onRightMouseDownImpl = &BaseManipulator::OnRightMouseDownImpl;
}
/// The implementation to override in a derived class for OnMouseMove.
virtual void OnMouseMoveImpl(const ViewportInteraction::MouseInteraction& /*interaction*/) {}
//! The implementation to override in a derived class for OnLeftMouseUp.
virtual void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& /*interaction*/)
{
}
/// The implementation to override in a derived class for OnMouseOver.
virtual void OnMouseOverImpl(
ManipulatorId /*manipulatorId*/, const ViewportInteraction::MouseInteraction& /*interaction*/) {}
//! The implementation to override in a derived class for OnRightMouseUp.
virtual void OnRightMouseUpImpl(const ViewportInteraction::MouseInteraction& /*interaction*/)
{
}
/// The implementation to override in a derived class for OnMouseWheel.
virtual void OnMouseWheelImpl(const ViewportInteraction::MouseInteraction& /*interaction*/) {}
//! The implementation to override in a derived class for OnMouseMove.
virtual void OnMouseMoveImpl(const ViewportInteraction::MouseInteraction& /*interaction*/)
{
}
/// The implementation to override in a derived class for SetBoundsDirty.
virtual void SetBoundsDirtyImpl() {}
//! The implementation to override in a derived class for OnMouseOver.
virtual void OnMouseOverImpl(ManipulatorId /*manipulatorId*/, const ViewportInteraction::MouseInteraction& /*interaction*/)
{
}
/// Rendering for the manipulator - it is recommended drawing be delegated to a ManipulatorView.
//! The implementation to override in a derived class for OnMouseWheel.
virtual void OnMouseWheelImpl(const ViewportInteraction::MouseInteraction& /*interaction*/)
{
}
//! The implementation to override in a derived class for SetBoundsDirty.
virtual void SetBoundsDirtyImpl()
{
}
//! Rendering for the manipulator - it is recommended drawing be delegated to a ManipulatorView.
virtual void Draw(
const ManipulatorManagerState& managerState,
AzFramework::DebugDisplayRequests& debugDisplay,
@@ -202,39 +243,39 @@ namespace AzToolsFramework
private:
friend class ManipulatorManager;
AZStd::unordered_set<AZ::EntityComponentIdPair> m_entityComponentIdPairs; ///< The entities this manipulator is associated with.
AZStd::unordered_set<AZ::EntityComponentIdPair> m_entityComponentIdPairs; //!< The entities this manipulator is associated with.
ManipulatorId m_manipulatorId = InvalidManipulatorId; ///< The unique id of this manipulator.
ManipulatorManagerId m_manipulatorManagerId = InvalidManipulatorManagerId; ///< The manager this manipulator was registered with.
UndoSystem::URSequencePoint* m_undoBatch = nullptr; ///< Undo active while mouse is pressed.
bool m_performingAction = false; ///< After mouse down and before mouse up.
bool m_mouseOver = false; ///< Is the mouse pointer over the manipulator bound.
ManipulatorId m_manipulatorId = InvalidManipulatorId; //!< The unique id of this manipulator.
ManipulatorManagerId m_manipulatorManagerId = InvalidManipulatorManagerId; //!< The manager this manipulator was registered with.
UndoSystem::URSequencePoint* m_undoBatch = nullptr; //!< Undo active while mouse is pressed.
bool m_performingAction = false; //!< After mouse down and before mouse up.
bool m_mouseOver = false; //!< Is the mouse pointer over the manipulator bound.
/// Member function pointers to OnLeftMouseDownImpl and OnRightMouseDownImpl.
/// Set in AttachLeft/RightMouseDownImpl.
//! Member function pointers to OnLeftMouseDownImpl and OnRightMouseDownImpl.
//! Set in AttachLeft/RightMouseDownImpl.
void (BaseManipulator::*m_onLeftMouseDownImpl)(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) = nullptr;
void (BaseManipulator::*m_onRightMouseDownImpl)(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) = nullptr;
/// Update the mouseOver state for this manipulator.
//! Update the mouseOver state for this manipulator.
void UpdateMouseOver(ManipulatorId manipulatorId);
/// Manage correctly ending the undo batch.
//! Manage correctly ending the undo batch.
void EndUndoBatch();
/// Record an action as having started.
//! Record an action as having started.
void BeginAction();
/// Record an action as having stopped.
//! Record an action as having stopped.
void EndAction();
/// Let other systems (UI) know that a component property has been modified by a manipulator.
//! Let other systems (UI) know that a component property has been modified by a manipulator.
void NotifyEntityComponentPropertyChanged();
};
/// Base class to be used when composing aggregate manipulator types - wraps some
/// common functionality all manipulators need.
//! Base class to be used when composing aggregate manipulator types - wraps some
//! common functionality all manipulators need.
class Manipulators
{
public:
@@ -249,8 +290,10 @@ namespace AzToolsFramework
bool PerformingAction();
bool Registered();
/// Refresh the Manipulator and/or View based on the current view position.
virtual void RefreshView(const AZ::Vector3& /*worldViewPosition*/) {}
//! Refresh the Manipulator and/or View based on the current view position.
virtual void RefreshView(const AZ::Vector3& /*worldViewPosition*/)
{
}
const AZ::Transform& GetLocalTransform() const;
const AZ::Transform& GetSpace() const;
@@ -262,39 +305,59 @@ namespace AzToolsFramework
void SetNonUniformScale(const AZ::Vector3& nonUniformScale);
protected:
/// Common processing for base manipulator type - Implement for all
/// individual manipulators used in an aggregate manipulator.
//! Common processing for base manipulator type - Implement for all
//! individual manipulators used in an aggregate manipulator.
virtual void ProcessManipulators(const AZStd::function<void(BaseManipulator*)>&) = 0;
///@{
/// Allows implementers to perform additional logic when updating the location of the manipulator group.
virtual void SetSpaceImpl([[maybe_unused]] const AZ::Transform& worldFromLocal) {}
virtual void SetLocalTransformImpl([[maybe_unused]] const AZ::Transform& localTransform) {}
virtual void SetLocalPositionImpl([[maybe_unused]] const AZ::Vector3& localPosition) {}
virtual void SetLocalOrientationImpl([[maybe_unused]] const AZ::Quaternion& localOrientation) {}
virtual void SetNonUniformScaleImpl([[maybe_unused]] const AZ::Vector3& nonUniformScale) {}
///@}
//!@{
//! Allows implementers to perform additional logic when updating the location of the manipulator group.
virtual void SetSpaceImpl([[maybe_unused]] const AZ::Transform& worldFromLocal)
{
}
ManipulatorSpaceWithLocalTransform m_manipulatorSpaceWithLocalTransform; ///< The space and local transform for the manipulators.
virtual void SetLocalTransformImpl([[maybe_unused]] const AZ::Transform& localTransform)
{
}
virtual void SetLocalPositionImpl([[maybe_unused]] const AZ::Vector3& localPosition)
{
}
virtual void SetLocalOrientationImpl([[maybe_unused]] const AZ::Quaternion& localOrientation)
{
}
virtual void SetNonUniformScaleImpl([[maybe_unused]] const AZ::Vector3& nonUniformScale)
{
}
//!@}
ManipulatorSpaceWithLocalTransform m_manipulatorSpaceWithLocalTransform; //!< The space and local transform for the manipulators.
};
namespace Internal
{
/// This helper function calculates the intersecting point between a ray and a plane.
/// @param rayOrigin The origin of the ray to test.
/// @param rayDirection The direction of the ray to test.
/// @param maxRayLength
/// @param pointOnPlane A point on the plane.
/// @param planeNormal The normal vector of the plane.
/// @param[out] resultIntersectingPoint This stores the result intersecting point. It will be left unchanged
/// if there is no intersection between the ray and the plane.
/// @return Was there an intersection
bool CalculateRayPlaneIntersectingPoint(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection,
const AZ::Vector3& pointOnPlane, const AZ::Vector3& planeNormal, AZ::Vector3& resultIntersectingPoint);
//! This helper function calculates the intersecting point between a ray and a plane.
//! @param rayOrigin The origin of the ray to test.
//! @param rayDirection The direction of the ray to test.
//! @param maxRayLength The maximum length of the ray to test.
//! @param pointOnPlane A point on the plane.
//! @param planeNormal The normal vector of the plane.
//! @param[out] resultIntersectingPoint This stores the result intersecting point. It will be left unchanged
//! if there is no intersection between the ray and the plane.
//! @return Was there an intersection
bool CalculateRayPlaneIntersectingPoint(
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const AZ::Vector3& pointOnPlane,
const AZ::Vector3& planeNormal,
AZ::Vector3& resultIntersectingPoint);
/// Returns startLocalHitPosition if currentLocalHitPosition is further away than the camera's far clip plane.
//! Returns startLocalHitPosition if currentLocalHitPosition is further away than the camera's far clip plane.
AZ::Vector3 TryConstrainHitPositionToView(
const AZ::Vector3& currentLocalHitPosition, const AZ::Vector3& startLocalHitPosition,
const AZ::Transform& localFromWorld, const AzFramework::CameraState& cameraState);
}
const AZ::Vector3& currentLocalHitPosition,
const AZ::Vector3& startLocalHitPosition,
const AZ::Transform& localFromWorld,
const AzFramework::CameraState& cameraState);
} // namespace Internal
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -21,31 +21,30 @@ namespace AZ
namespace AzToolsFramework
{
/// Interface for handling box manipulator requests.
/// Used by \ref BoxComponentMode.
class BoxManipulatorRequests
: public AZ::EntityComponentBus
//! Interface for handling box manipulator requests.
//! Used by \ref BoxComponentMode.
class BoxManipulatorRequests : public AZ::EntityComponentBus
{
public:
/// Get the X/Y/Z dimensions of the box shape/collider.
//! Get the X/Y/Z dimensions of the box shape/collider.
virtual AZ::Vector3 GetDimensions() = 0;
/// Set the X/Y/Z dimensions of the box shape/collider.
//! Set the X/Y/Z dimensions of the box shape/collider.
virtual void SetDimensions(const AZ::Vector3& dimensions) = 0;
/// Get the transform of the box shape/collider.
/// This is used by \ref BoxComponentMode instead of the \ref \AZ::TransformBus
/// because a collider may have an additional translation/orientation offset from
/// the Entity transform.
//! Get the transform of the box shape/collider.
//! This is used by \ref BoxComponentMode instead of the \ref \AZ::TransformBus
//! because a collider may have an additional translation/orientation offset from
//! the Entity transform.
virtual AZ::Transform GetCurrentTransform() = 0;
/// Get the scale currently applied to the box.
/// With the Box Shape, the largest x/y/z component is taken
/// so scale is always uniform, with colliders the scale may
/// be different per component.
//! Get the scale currently applied to the box.
//! With the Box Shape, the largest x/y/z component is taken
//! so scale is always uniform, with colliders the scale may
//! be different per component.
virtual AZ::Vector3 GetBoxScale() = 0;
protected:
~BoxManipulatorRequests() = default;
};
/// Type to inherit to implement BoxManipulatorRequests
//! Type to inherit to implement BoxManipulatorRequests
using BoxManipulatorRequestBus = AZ::EBus<BoxManipulatorRequests>;
} // namespace AzToolsFramework
@@ -1,22 +1,22 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/VertexContainer.h>
#include <AzCore/Math/VertexContainerInterface.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzToolsFramework/Manipulators/ManipulatorBus.h>
#include <AzToolsFramework/Manipulators/HoverSelection.h>
#include <AzToolsFramework/Manipulators/ManipulatorBus.h>
#include <AzToolsFramework/Manipulators/SelectionManipulator.h>
#include <AzToolsFramework/Manipulators/TranslationManipulators.h>
#include <AzToolsFramework/Viewport/ActionBus.h>
@@ -24,37 +24,74 @@
namespace AzToolsFramework
{
/// Concrete implementation of AZ::VariableVertices backed by an AZ::VertexContainer.
//! Concrete implementation of AZ::VariableVertices backed by an AZ::VertexContainer.
template<typename Vertex>
class VariableVerticesVertexContainer
: public AZ::VariableVertices<Vertex>
class VariableVerticesVertexContainer : public AZ::VariableVertices<Vertex>
{
public:
explicit VariableVerticesVertexContainer(AZ::VertexContainer<Vertex>& vertexContainer)
: m_vertexContainer(vertexContainer) {}
: m_vertexContainer(vertexContainer)
{
}
bool GetVertex(size_t index, Vertex& vertex) const override { return m_vertexContainer.GetVertex(index, vertex); }
bool UpdateVertex(size_t index, const Vertex& vertex) override { return m_vertexContainer.UpdateVertex(index, vertex); };
void AddVertex(const Vertex& vertex) override { m_vertexContainer.AddVertex(vertex); }
bool InsertVertex(size_t index, const Vertex& vertex) override { return m_vertexContainer.InsertVertex(index, vertex); }
bool RemoveVertex(size_t index) override { return m_vertexContainer.RemoveVertex(index); }
void SetVertices(const AZStd::vector<Vertex>& vertices) override { m_vertexContainer.SetVertices(vertices); };
void ClearVertices() override { m_vertexContainer.Clear(); }
size_t Size() const override { return m_vertexContainer.Size(); }
bool Empty() const override { return m_vertexContainer.Empty(); }
bool GetVertex(size_t index, Vertex& vertex) const override
{
return m_vertexContainer.GetVertex(index, vertex);
}
bool UpdateVertex(size_t index, const Vertex& vertex) override
{
return m_vertexContainer.UpdateVertex(index, vertex);
};
void AddVertex(const Vertex& vertex) override
{
m_vertexContainer.AddVertex(vertex);
}
bool InsertVertex(size_t index, const Vertex& vertex) override
{
return m_vertexContainer.InsertVertex(index, vertex);
}
bool RemoveVertex(size_t index) override
{
return m_vertexContainer.RemoveVertex(index);
}
void SetVertices(const AZStd::vector<Vertex>& vertices) override
{
m_vertexContainer.SetVertices(vertices);
};
void ClearVertices() override
{
m_vertexContainer.Clear();
}
size_t Size() const override
{
return m_vertexContainer.Size();
}
bool Empty() const override
{
return m_vertexContainer.Empty();
}
private:
AZ::VertexContainer<Vertex>& m_vertexContainer;
};
/// Concrete implementation of AZ::FixedVertices backed by an AZStd::array.
//! Concrete implementation of AZ::FixedVertices backed by an AZStd::array.
template<typename Vertex, size_t Count>
class FixedVerticesArray
: public AZ::FixedVertices<Vertex>
class FixedVerticesArray : public AZ::FixedVertices<Vertex>
{
public:
explicit FixedVerticesArray(AZStd::array<Vertex, Count>& array)
: m_array(array) {}
: m_array(array)
{
}
bool GetVertex(size_t index, Vertex& vertex) const override
{
@@ -72,22 +109,26 @@ namespace AzToolsFramework
if (index < m_array.size())
{
m_array[index] = vertex;
return true;;
return true;
;
}
return false;
}
size_t Size() const override { return m_array.size(); }
size_t Size() const override
{
return m_array.size();
}
private:
AZStd::array<Vertex, Count>& m_array;
};
/// EditorVertexSelection provides an interface for a collection of manipulators to expose
/// editing of vertices in a container/collection. EditorVertexSelection is templated on the
/// type of Vertex (Vector2/Vector3) stored in the container.
/// EditorVertexSelectionBase provides common behavior shared across Fixed and Variable selections.
//! EditorVertexSelection provides an interface for a collection of manipulators to expose
//! editing of vertices in a container/collection. EditorVertexSelection is templated on the
//! type of Vertex (Vector2/Vector3) stored in the container.
//! EditorVertexSelectionBase provides common behavior shared across Fixed and Variable selections.
template<typename Vertex>
class EditorVertexSelectionBase
: private AzFramework::EntityDebugDisplayEventBus::Handler
@@ -99,89 +140,110 @@ namespace AzToolsFramework
EditorVertexSelectionBase& operator=(EditorVertexSelectionBase&&) = default;
virtual ~EditorVertexSelectionBase() = default;
/// Setup and configure the EditorVertexSelection for operation.
//! Setup and configure the EditorVertexSelection for operation.
void Create(
const AZ::EntityComponentIdPair& entityComponentIdPair, ManipulatorManagerId managerId,
const AZ::EntityComponentIdPair& entityComponentIdPair,
ManipulatorManagerId managerId,
AZStd::unique_ptr<HoverSelection> hoverSelection,
TranslationManipulators::Dimensions dimensions,
TranslationManipulatorConfiguratorFn translationManipulatorConfigurator);
/// Create a translation manipulator for a given vertex.
//! Create a translation manipulator for a given vertex.
void CreateTranslationManipulator(
const AZ::EntityComponentIdPair& entityComponentIdPair,
ManipulatorManagerId managerId, const Vertex& vertex, size_t index);
const AZ::EntityComponentIdPair& entityComponentIdPair, ManipulatorManagerId managerId, const Vertex& vertex, size_t index);
/// Destroy all manipulators associated with the vertex selection.
//! Destroy all manipulators associated with the vertex selection.
void Destroy();
/// Set custom callback for when vertex positions are updated.
//! Set custom callback for when vertex positions are updated.
void SetVertexPositionsUpdatedCallback(const AZStd::function<void()>& callback);
/// Update manipulators based on local changes to vertex positions.
//! Update manipulators based on local changes to vertex positions.
void RefreshLocal();
/// Update the translation manipulator to be correctly positioned based
/// on the current selection (recenter it).
//! Update the translation manipulator to be correctly positioned based
//! on the current selection (recenter it).
void RefreshTranslationManipulator();
/// Update manipulators based on changes to the entity's transform and non-uniform scale.
//! Update manipulators based on changes to the entity's transform and non-uniform scale.
void RefreshSpace(const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne());
/// Set bounds dirty (need recalculating) for all owned manipulators (selection, translation, hover).
//! Set bounds dirty (need recalculating) for all owned manipulators (selection, translation, hover).
void SetBoundsDirty();
/// How should the EditorVertexSelection respond to mouse input.
virtual bool HandleMouse(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
//! How should the EditorVertexSelection respond to mouse input.
virtual bool HandleMouse(const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
/// Snap the selected vertices to the terrain.
/// Note: With a multi-selection the manipulator will be translated to the picked
/// terrain position with all verts moved relative to it.
void SnapVerticesToTerrain(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
//! Snap the selected vertices to the terrain.
//! Note: With a multi-selection the manipulator will be translated to the picked
//! terrain position with all vertices moved relative to it.
void SnapVerticesToTerrain(const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
/// The Actions provided by the EditorVertexSelection while it is active.
/// e.g. Vertex deletion, duplication etc.
//! The Actions provided by the EditorVertexSelection while it is active.
//! e.g. Vertex deletion, duplication etc.
AZStd::vector<ActionOverride> ActionOverrides() const;
/// Let the EditorVertexSelection know a batch movement is about to begin so it
/// can avoid certain unnecessary updates.
//! Let the EditorVertexSelection know a batch movement is about to begin so it
//! can avoid certain unnecessary updates.
void BeginBatchMovement();
/// Let the EditorVertexSelection know a batch movement has ended so it can return
/// to its normal state.
//! Let the EditorVertexSelection know a batch movement has ended so it can return
//! to its normal state.
void EndBatchMovement();
/// Set the position of the TranslationManipulators (if active).
//! Set the position of the TranslationManipulators (if active).
void SetSelectedPosition(const AZ::Vector3& localPosition);
AZ::EntityId GetEntityId() const { return m_entityComponentIdPair.GetEntityId(); }
AZ::EntityId GetEntityId() const
{
return m_entityComponentIdPair.GetEntityId();
}
protected:
/// Internal interface for EditorVertexSelection.
//! Internal interface for EditorVertexSelection.
virtual void SetupSelectionManipulator(
const AZStd::shared_ptr<SelectionManipulator>& selectionManipulator,
const AZ::EntityComponentIdPair& entityComponentIdPair,
ManipulatorManagerId managerId, size_t index) = 0;
ManipulatorManagerId managerId,
size_t index) = 0;
virtual void PrepareActions() = 0;
/// Default behavior when clicking on a selection manipulator (representing a vertex).
//! Default behavior when clicking on a selection manipulator (representing a vertex).
void SelectionManipulatorSelectCallback(
size_t index, const ViewportInteraction::MouseInteraction& interaction,
const AZ::EntityComponentIdPair& entityComponentIdPair, ManipulatorManagerId managerId);
size_t index,
const ViewportInteraction::MouseInteraction& interaction,
const AZ::EntityComponentIdPair& entityComponentIdPair,
ManipulatorManagerId managerId);
/// Destroy the translation manipulator and deselect all vertices.
//! Destroy the translation manipulator and deselect all vertices.
void ClearSelected();
AZ::ComponentId GetComponentId() const { return m_entityComponentIdPair.GetComponentId(); }
const AZ::EntityComponentIdPair& GetEntityComponentIdPair() const { return m_entityComponentIdPair; }
ManipulatorManagerId GetManipulatorManagerId() const { return m_manipulatorManagerId; }
AZ::ComponentId GetComponentId() const
{
return m_entityComponentIdPair.GetComponentId();
}
/// Is the translation vertex manipulator in 2D or 3D.
TranslationManipulators::Dimensions Dimensions() const { return m_dimensions; }
const AZ::EntityComponentIdPair& GetEntityComponentIdPair() const
{
return m_entityComponentIdPair;
}
/// How to configure the translation manipulator (view and axes).
TranslationManipulatorConfiguratorFn ConfiguratorFn() const { return m_manipulatorConfiguratorFn; }
ManipulatorManagerId GetManipulatorManagerId() const
{
return m_manipulatorManagerId;
}
/// The state we are in when editing vertices.
//! Is the translation vertex manipulator in 2D or 3D.
TranslationManipulators::Dimensions Dimensions() const
{
return m_dimensions;
}
//! How to configure the translation manipulator (view and axes).
TranslationManipulatorConfiguratorFn ConfiguratorFn() const
{
return m_manipulatorConfiguratorFn;
}
//! The state we are in when editing vertices.
enum class State
{
Selecting,
@@ -190,23 +252,22 @@ namespace AzToolsFramework
void SetState(State state);
AZStd::unique_ptr<HoverSelection> m_hoverSelection = nullptr; ///< Interface to hover selection, representing bounds that can be selected.
AZStd::shared_ptr<IndexedTranslationManipulator<Vertex>> m_translationManipulator = nullptr; ///< Manipulator when vertex is selected to translate it.
AZStd::vector<AZStd::shared_ptr<SelectionManipulator>> m_selectionManipulators; ///< Manipulators for each vertex when entity is selected.
AZStd::array<AZStd::vector<ActionOverride>, 2> m_actionOverrides; ///< Available actions corresponding to each mode.
AZStd::unique_ptr<HoverSelection> m_hoverSelection =
nullptr; //!< Interface to hover selection, representing bounds that can be selected.
AZStd::shared_ptr<IndexedTranslationManipulator<Vertex>> m_translationManipulator =
nullptr; //!< Manipulator when vertex is selected to translate it.
AZStd::vector<AZStd::shared_ptr<SelectionManipulator>>
m_selectionManipulators; //!< Manipulators for each vertex when entity is selected.
AZStd::array<AZStd::vector<ActionOverride>, 2> m_actionOverrides; //!< Available actions corresponding to each mode.
private:
// AzFramework::EntityDebugDisplayEventBus
void DisplayEntityViewport(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
// AzFramework::ViewportDebugDisplayEventBus
void DisplayViewport2d(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
void DisplayViewport2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
/// Set selected manipulator and vertices position from offset from starting position when pressed.
//! Set selected manipulator and vertices position from offset from starting position when pressed.
void UpdateManipulatorsAndVerticesFromOffset(
IndexedTranslationManipulator<Vertex>& translationManipulator,
const AZ::Vector3& localManipulatorStartPosition,
@@ -217,23 +278,24 @@ namespace AzToolsFramework
template<typename V, typename AZStd::enable_if<AZStd::is_same<V, AZ::Vector2>::value>::type* = nullptr>
void UpdateManipulatorSpace(const AzFramework::ViewportInfo& viewportInfo) const;
EditorBoxSelect m_editorBoxSelect; ///< Provide box select support for vertex selection.
AZ::EntityComponentIdPair m_entityComponentIdPair; ///< Id of the Entity and Component this editor vertex selection was created on.
ManipulatorManagerId m_manipulatorManagerId; ///< Id of the manager manipulators created from this type will be associated with.
TranslationManipulators::Dimensions m_dimensions = TranslationManipulators::Dimensions::Three; ///< The dimensions this vertex selection was created with.
TranslationManipulatorConfiguratorFn m_manipulatorConfiguratorFn = nullptr; ///< Function pointer set on Create to decide look and functionality of translation manipulator.
AZStd::function<void()> m_onVertexPositionsUpdated = nullptr; ///< Callback for when vertex positions are changed.
State m_state = State::Selecting; ///< Different states VertexSelection can be in.
bool m_worldSpace = false; ///< Are the manipulators being used in local or world space.
bool m_batchMovementInProgress = false; ///< If a batch movement operation is in progress we do not want to
///< refresh the VertexSelection during it for performance reasons.
EditorBoxSelect m_editorBoxSelect; //!< Provide box select support for vertex selection.
AZ::EntityComponentIdPair m_entityComponentIdPair; //!< Id of the Entity and Component this editor vertex selection was created on.
ManipulatorManagerId m_manipulatorManagerId; //!< Id of the manager manipulators created from this type will be associated with.
TranslationManipulators::Dimensions m_dimensions =
TranslationManipulators::Dimensions::Three; //!< The dimensions this vertex selection was created with.
TranslationManipulatorConfiguratorFn m_manipulatorConfiguratorFn =
nullptr; //!< Function pointer set on Create to decide look and functionality of translation manipulator.
AZStd::function<void()> m_onVertexPositionsUpdated = nullptr; //!< Callback for when vertex positions are changed.
State m_state = State::Selecting; //!< Different states VertexSelection can be in.
bool m_worldSpace = false; //!< Are the manipulators being used in local or world space.
bool m_batchMovementInProgress = false; //!< If a batch movement operation is in progress we do not want to
//!< refresh the VertexSelection during it for performance reasons.
};
/// EditorVertexSelectionFixed provides selection and editing for a fixed length number of
/// vertices. New vertices cannot be inserted/added or removed.
//! EditorVertexSelectionFixed provides selection and editing for a fixed length number of
//! vertices. New vertices cannot be inserted/added or removed.
template<typename Vertex>
class EditorVertexSelectionFixed
: public EditorVertexSelectionBase<Vertex>
class EditorVertexSelectionFixed : public EditorVertexSelectionBase<Vertex>
{
public:
AZ_CLASS_ALLOCATOR_DECL
@@ -247,15 +309,15 @@ namespace AzToolsFramework
void SetupSelectionManipulator(
const AZStd::shared_ptr<SelectionManipulator>& selectionManipulator,
const AZ::EntityComponentIdPair& entityComponentIdPair,
ManipulatorManagerId managerId, size_t index) override;
ManipulatorManagerId managerId,
size_t index) override;
void PrepareActions() override;
};
/// EditorVertexSelectionVariable provides selection and editing for a variable length number of
/// vertices. New vertices can be inserted/added or removed from the collection.
//! EditorVertexSelectionVariable provides selection and editing for a variable length number of
//! vertices. New vertices can be inserted/added or removed from the collection.
template<typename Vertex>
class EditorVertexSelectionVariable
: public EditorVertexSelectionBase<Vertex>
class EditorVertexSelectionVariable : public EditorVertexSelectionBase<Vertex>
{
public:
AZ_CLASS_ALLOCATOR_DECL
@@ -272,7 +334,8 @@ namespace AzToolsFramework
void SetupSelectionManipulator(
const AZStd::shared_ptr<SelectionManipulator>& selectionManipulator,
const AZ::EntityComponentIdPair& entityComponentIdPair,
ManipulatorManagerId managerId, size_t vertIndex) override;
ManipulatorManagerId managerId,
size_t vertIndex) override;
//! Presents a warning to the user that vertices will not be deleted.
//! @note Allow overriding by derived classes to make this a noop if required.
@@ -281,21 +344,18 @@ namespace AzToolsFramework
private:
void PrepareActions() override;
/// @return The center point of the selected vertices.
Vertex InsertSelectedInPlace(
AZStd::vector<typename IndexedTranslationManipulator<Vertex>::VertexLookup>& manipulators);
//! @return The center point of the selected vertices.
Vertex InsertSelectedInPlace(AZStd::vector<typename IndexedTranslationManipulator<Vertex>::VertexLookup>& manipulators);
};
/// Helper for inserting a vertex in a variable vertices container.
//! Helper for inserting a vertex in a variable vertices container.
template<typename Vertex>
void InsertVertexAfter(
const AZ::EntityComponentIdPair& entityComponentIdPair, size_t vertIndex, const Vertex& localPosition);
void InsertVertexAfter(const AZ::EntityComponentIdPair& entityComponentIdPair, size_t vertIndex, const Vertex& localPosition);
/// Helper for removing a vertex in a variable vertices container.
/// Remove a vertex from the container and ensure the associated manipulator is unset and
/// property display values are refreshed.
//! Helper for removing a vertex in a variable vertices container.
//! Remove a vertex from the container and ensure the associated manipulator is unset and
//! property display values are refreshed.
template<typename Vertex>
void SafeRemoveVertex(
const AZ::EntityComponentIdPair& entityComponentIdPair, size_t vertexIndex);
void SafeRemoveVertex(const AZ::EntityComponentIdPair& entityComponentIdPair, size_t vertexIndex);
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -16,10 +16,10 @@
namespace AzToolsFramework
{
/// HoverSelection provides an interface for manipulator/s offering selection when
/// the mouse is hovered over a particular bound. This interface is used to represent
/// a Spline manipulator bound, and a series of LineSegment manipulator bounds.
/// This generic interface allows EditorVertexSelection to use either Spline or LineSegment selection.
//! HoverSelection provides an interface for manipulator/s offering selection when
//! the mouse is hovered over a particular bound. This interface is used to represent
//! a Spline manipulator bound, and a series of LineSegment manipulator bounds.
//! This generic interface allows EditorVertexSelection to use either Spline or LineSegment selection.
class HoverSelection
{
public:
@@ -33,21 +33,37 @@ namespace AzToolsFramework
virtual void SetNonUniformScale(const AZ::Vector3& nonUniformScale) = 0;
};
/// NullHoverSelection is used when vertices cannot be inserted. This serves as a no-op
/// and is used to prevent the need for additional null checks in EditorVertexSelection.
class NullHoverSelection
: public HoverSelection
//! NullHoverSelection is used when vertices cannot be inserted. This serves as a no-op
//! and is used to prevent the need for additional null checks in EditorVertexSelection.
class NullHoverSelection : public HoverSelection
{
public:
NullHoverSelection() = default;
NullHoverSelection(const NullHoverSelection&) = delete;
NullHoverSelection& operator=(const NullHoverSelection&) = delete;
void Register(ManipulatorManagerId /*managerId*/) override {}
void Unregister() override {}
void SetBoundsDirty() override {}
void Refresh() override {}
void SetSpace(const AZ::Transform& /*worldFromLocal*/) override {}
void SetNonUniformScale([[maybe_unused]] const AZ::Vector3& nonUniformScale) override {}
void Register([[maybe_unused]] ManipulatorManagerId managerId) override
{
}
void Unregister() override
{
}
void SetBoundsDirty() override
{
}
void Refresh() override
{
}
void SetSpace([[maybe_unused]] const AZ::Transform& worldFromLocal) override
{
}
void SetNonUniformScale([[maybe_unused]] const AZ::Vector3& nonUniformScale) override
{
}
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "LineHoverSelection.h"
@@ -22,17 +22,15 @@
namespace AzToolsFramework
{
static const AZ::Color s_lineSelectManipulatorColor = AZ::Color(0.0f, 1.0f, 0.0f, 1.0f);
static const AZ::Color LineSelectManipulatorColor = AZ::Color(0.0f, 1.0f, 0.0f, 1.0f);
template<typename Vertex>
static void UpdateLineSegmentPosition(
const size_t vertIndex, const AZ::EntityId entityId, LineSegmentSelectionManipulator& lineSegment)
static void UpdateLineSegmentPosition(const size_t vertIndex, const AZ::EntityId entityId, LineSegmentSelectionManipulator& lineSegment)
{
Vertex start;
bool foundStart = false;
AZ::FixedVerticesRequestBus<Vertex>::EventResult(
foundStart, entityId, &AZ::FixedVerticesRequestBus<Vertex>::Handler::GetVertex,
vertIndex, start);
foundStart, entityId, &AZ::FixedVerticesRequestBus<Vertex>::Handler::GetVertex, vertIndex, start);
if (foundStart)
{
@@ -40,14 +38,12 @@ namespace AzToolsFramework
}
size_t size = 0;
AZ::FixedVerticesRequestBus<Vertex>::EventResult(
size, entityId, &AZ::FixedVerticesRequestBus<Vertex>::Handler::Size);
AZ::FixedVerticesRequestBus<Vertex>::EventResult(size, entityId, &AZ::FixedVerticesRequestBus<Vertex>::Handler::Size);
Vertex end;
bool foundEnd = false;
AZ::FixedVerticesRequestBus<Vertex>::EventResult(
foundEnd, entityId, &AZ::FixedVerticesRequestBus<Vertex>::Handler::GetVertex,
(vertIndex + 1) % size, end);
foundEnd, entityId, &AZ::FixedVerticesRequestBus<Vertex>::Handler::GetVertex, (vertIndex + 1) % size, end);
if (foundEnd)
{
@@ -56,8 +52,7 @@ namespace AzToolsFramework
// update the view
const float lineWidth = 0.05f;
lineSegment.SetView(
CreateManipulatorViewLineSelect(lineSegment, s_lineSelectManipulatorColor, lineWidth));
lineSegment.SetView(CreateManipulatorViewLineSelect(lineSegment, LineSelectManipulatorColor, lineWidth));
}
template<typename Vertex>
@@ -66,9 +61,8 @@ namespace AzToolsFramework
: m_entityId(entityComponentIdPair.GetEntityId())
{
// create a line segment manipulator from vertex positions and setup its callback
auto setupLineSegment = [this] (
const AZ::EntityComponentIdPair& entityComponentIdPair,
const ManipulatorManagerId managerId, const size_t vertIndex)
auto setupLineSegment =
[this](const AZ::EntityComponentIdPair& entityComponentIdPair, const ManipulatorManagerId managerId, const size_t vertIndex)
{
m_lineSegmentManipulators.push_back(LineSegmentSelectionManipulator::MakeShared());
AZStd::shared_ptr<LineSegmentSelectionManipulator>& lineSegmentManipulator = m_lineSegmentManipulators.back();
@@ -81,11 +75,9 @@ namespace AzToolsFramework
lineSegmentManipulator->InstallLeftMouseUpCallback(
[vertIndex, entityComponentIdPair](const LineSegmentSelectionManipulator::Action& action)
{
InsertVertexAfter<Vertex>(
entityComponentIdPair, vertIndex,
AZ::AdaptVertexIn<Vertex>(action.m_localLineHitPosition));
});
{
InsertVertexAfter<Vertex>(entityComponentIdPair, vertIndex, AZ::AdaptVertexIn<Vertex>(action.m_localLineHitPosition));
});
};
// create all line segment manipulators for the polygon prism (used for selection bounds)
@@ -150,8 +142,7 @@ namespace AzToolsFramework
void LineSegmentHoverSelection<Vertex>::Refresh()
{
size_t vertexCount = 0;
AZ::FixedVerticesRequestBus<Vertex>::EventResult(
vertexCount, m_entityId, &AZ::FixedVerticesRequestBus<Vertex>::Handler::Size);
AZ::FixedVerticesRequestBus<Vertex>::EventResult(vertexCount, m_entityId, &AZ::FixedVerticesRequestBus<Vertex>::Handler::Size);
// update the start/end positions of all the line segment manipulators to ensure
// they stay consistent with the polygon prism shape
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -25,17 +25,14 @@ namespace AzToolsFramework
{
class LineSegmentSelectionManipulator;
/// LineSegmentHoverSelection is a concrete implementation of HoverSelection wrapping a collection/container
/// of vertices and a list of LineSegmentManipulators. The underlying manipulators are used to control selection
/// by highlighting where on the line a new vertex will be inserted.
//! LineSegmentHoverSelection is a concrete implementation of HoverSelection wrapping a collection/container
//! of vertices and a list of LineSegmentManipulators. The underlying manipulators are used to control selection
//! by highlighting where on the line a new vertex will be inserted.
template<typename Vertex>
class LineSegmentHoverSelection
: public HoverSelection
class LineSegmentHoverSelection : public HoverSelection
{
public:
explicit LineSegmentHoverSelection(
const AZ::EntityComponentIdPair& entityComponentIdPair,
ManipulatorManagerId managerId);
explicit LineSegmentHoverSelection(const AZ::EntityComponentIdPair& entityComponentIdPair, ManipulatorManagerId managerId);
LineSegmentHoverSelection(const LineSegmentHoverSelection&) = delete;
LineSegmentHoverSelection& operator=(const LineSegmentHoverSelection&) = delete;
~LineSegmentHoverSelection();
@@ -49,6 +46,6 @@ namespace AzToolsFramework
private:
AZ::EntityId m_entityId;
AZStd::vector<AZStd::shared_ptr<LineSegmentSelectionManipulator>> m_lineSegmentManipulators; ///< Manipulators for each line.
AZStd::vector<AZStd::shared_ptr<LineSegmentSelectionManipulator>> m_lineSegmentManipulators; //!< Manipulators for each line.
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "LineSegmentSelectionManipulator.h"
@@ -20,15 +20,20 @@
namespace AzToolsFramework
{
LineSegmentSelectionManipulator::Action CalculateManipulationDataAction(
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection, const float rayLength, const AZ::Vector3& localStart, const AZ::Vector3& localEnd)
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const float rayLength,
const AZ::Vector3& localStart,
const AZ::Vector3& localEnd)
{
AZ::Vector3 worldClosestPositionRay, worldClosestPositionLineSegment;
float rayProportion, lineSegmentProportion;
AZ::Intersect::ClosestSegmentSegment(
rayOrigin, rayOrigin + rayDirection * rayLength,
worldFromLocal.TransformPoint(nonUniformScale * localStart), worldFromLocal.TransformPoint(nonUniformScale * localEnd),
rayProportion, lineSegmentProportion, worldClosestPositionRay, worldClosestPositionLineSegment);
rayOrigin, rayOrigin + rayDirection * rayLength, worldFromLocal.TransformPoint(nonUniformScale * localStart),
worldFromLocal.TransformPoint(nonUniformScale * localEnd), rayProportion, lineSegmentProportion, worldClosestPositionRay,
worldClosestPositionLineSegment);
AZ::Transform worldFromLocalNormalized = worldFromLocal;
const AZ::Vector3 scale = worldFromLocalNormalized.ExtractUniformScale() * nonUniformScale;
@@ -47,7 +52,9 @@ namespace AzToolsFramework
AttachLeftMouseDownImpl();
}
LineSegmentSelectionManipulator::~LineSegmentSelectionManipulator() {}
LineSegmentSelectionManipulator::~LineSegmentSelectionManipulator()
{
}
void LineSegmentSelectionManipulator::InstallLeftMouseDownCallback(const MouseActionCallback& onMouseDownCallback)
{
@@ -112,12 +119,9 @@ namespace AzToolsFramework
if (mouseInteraction.m_keyboardModifiers.Ctrl() && !mouseInteraction.m_keyboardModifiers.Shift())
{
m_manipulatorView->Draw(
GetManipulatorManagerId(), managerState,
GetManipulatorId(), {
TransformUniformScale(GetSpace()), GetNonUniformScale(),
m_localStart, MouseOver()
},
debugDisplay, cameraState, mouseInteraction);
GetManipulatorManagerId(), managerState, GetManipulatorId(),
{ TransformUniformScale(GetSpace()), GetNonUniformScale(), m_localStart, MouseOver() }, debugDisplay, cameraState,
mouseInteraction);
}
}
@@ -135,4 +139,4 @@ namespace AzToolsFramework
{
m_manipulatorView->Invalidate(GetManipulatorManagerId());
}
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -20,12 +20,12 @@ namespace AzToolsFramework
{
class ManipulatorView;
/// A manipulator to expose where on a line a user is moving their mouse.
//! A manipulator to expose where on a line a user is moving their mouse.
class LineSegmentSelectionManipulator
: public BaseManipulator
, public ManipulatorSpace
{
/// Private constructor.
//! Private constructor.
LineSegmentSelectionManipulator();
public:
@@ -37,10 +37,10 @@ namespace AzToolsFramework
~LineSegmentSelectionManipulator();
/// A Manipulator must only be created and managed through a shared_ptr.
//! A Manipulator must only be created and managed through a shared_ptr.
static AZStd::shared_ptr<LineSegmentSelectionManipulator> MakeShared();
/// Mouse action data used by MouseActionCallback.
//! Mouse action data used by MouseActionCallback.
struct Action
{
AZ::Vector3 m_localLineHitPosition;
@@ -57,18 +57,31 @@ namespace AzToolsFramework
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
void SetStart(const AZ::Vector3& startLocal) { m_localStart = startLocal; }
void SetEnd(const AZ::Vector3& endLocal) { m_localEnd = endLocal; }
const AZ::Vector3& GetStart() const { return m_localStart; }
const AZ::Vector3& GetEnd() const { return m_localEnd; }
void SetStart(const AZ::Vector3& startLocal)
{
m_localStart = startLocal;
}
void SetEnd(const AZ::Vector3& endLocal)
{
m_localEnd = endLocal;
}
const AZ::Vector3& GetStart() const
{
return m_localStart;
}
const AZ::Vector3& GetEnd() const
{
return m_localEnd;
}
void SetView(AZStd::unique_ptr<ManipulatorView>&& view);
private:
void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void InvalidateImpl() override;
void SetBoundsDirtyImpl() override;
@@ -79,12 +92,18 @@ namespace AzToolsFramework
MouseActionCallback m_onLeftMouseDownCallback = nullptr;
MouseActionCallback m_onLeftMouseUpCallback = nullptr;
ViewportInteraction::KeyboardModifiers m_keyboardModifiers; ///< What modifier keys are pressed when interacting with this manipulator.
ViewportInteraction::KeyboardModifiers
m_keyboardModifiers; //!< What modifier keys are pressed when interacting with this manipulator.
AZStd::unique_ptr<ManipulatorView> m_manipulatorView = nullptr; ///< Look of manipulator.
AZStd::unique_ptr<ManipulatorView> m_manipulatorView = nullptr; //!< Look of manipulator.
};
LineSegmentSelectionManipulator::Action CalculateManipulationDataAction(
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection, float rayLength, const AZ::Vector3& localStart, const AZ::Vector3& localEnd);
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
float rayLength,
const AZ::Vector3& localStart,
const AZ::Vector3& localEnd);
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "LinearManipulator.h"
@@ -22,13 +22,16 @@
namespace AzToolsFramework
{
LinearManipulator::Starter CalculateLinearManipulationDataStart(
const LinearManipulator::Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform, const ViewportInteraction::MouseInteraction& interaction, const float intersectionDistance,
const LinearManipulator::Fixed& fixed,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const ViewportInteraction::MouseInteraction& interaction,
const float intersectionDistance,
const AzFramework::CameraState& cameraState)
{
const ManipulatorInteraction manipulatorInteraction =
BuildManipulatorInteraction(
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
const ManipulatorInteraction manipulatorInteraction = BuildManipulatorInteraction(
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
const AZ::Vector3 axis = TransformDirectionNoScaling(localTransform, fixed.m_axis);
const AZ::Vector3 rayCrossAxis = manipulatorInteraction.m_localRayDirection.Cross(axis);
@@ -47,32 +50,35 @@ namespace AzToolsFramework
manipulatorInteraction.m_localRayOrigin + manipulatorInteraction.m_localRayDirection * intersectionDistance;
Internal::CalculateRayPlaneIntersectingPoint(
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection,
localIntersectionPoint, startTransition.m_localNormal, start.m_localHitPosition);
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection, localIntersectionPoint,
startTransition.m_localNormal, start.m_localHitPosition);
start.m_screenPosition = interaction.m_mousePick.m_screenCoordinates;
start.m_localPosition = localTransform.GetTranslation();
start.m_localScale = AZ::Vector3(localTransform.GetUniformScale());;
start.m_localScale = AZ::Vector3(localTransform.GetUniformScale());
;
start.m_localAxis = axis;
// sign to determine which side of the linear axis we pressed
// (useful to know when the visual axis flips to face the camera)
start.m_sign =
AZ::GetSign((start.m_localHitPosition - localTransform.GetTranslation()).Dot(axis));
start.m_sign = AZ::GetSign((start.m_localHitPosition - localTransform.GetTranslation()).Dot(axis));
startTransition.m_screenToWorldScale =
1.0f / CalculateScreenToWorldMultiplier((worldFromLocal * localTransform).GetTranslation(), cameraState);
return {startTransition, start};
return { startTransition, start };
}
LinearManipulator::Action CalculateLinearManipulationDataAction(
const LinearManipulator::Fixed& fixed, const LinearManipulator::Starter& starter,
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
const GridSnapParameters& gridSnapParams, const ViewportInteraction::MouseInteraction& interaction)
const LinearManipulator::Fixed& fixed,
const LinearManipulator::Starter& starter,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const GridSnapParameters& gridSnapParams,
const ViewportInteraction::MouseInteraction& interaction)
{
const ManipulatorInteraction manipulatorInteraction =
BuildManipulatorInteraction(
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
const ManipulatorInteraction manipulatorInteraction = BuildManipulatorInteraction(
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
const auto& [startTransition, start] = starter;
@@ -81,8 +87,8 @@ namespace AzToolsFramework
// if an invalid ray intersection is attempted
AZ::Vector3 localHitPosition = start.m_localHitPosition;
Internal::CalculateRayPlaneIntersectingPoint(
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection,
start.m_localHitPosition, startTransition.m_localNormal, localHitPosition);
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection, start.m_localHitPosition,
startTransition.m_localNormal, localHitPosition);
localHitPosition = Internal::TryConstrainHitPositionToView(
localHitPosition, start.m_localHitPosition, worldFromLocal.GetInverse(),
@@ -103,9 +109,8 @@ namespace AzToolsFramework
LinearManipulator::Action action;
action.m_fixed = fixed;
action.m_start = start;
action.m_current.m_localPositionOffset = snapping
? CalculateSnappedAmount(unsnappedOffset, axis, gridSize * scaleRecip)
: unsnappedOffset;
action.m_current.m_localPositionOffset =
snapping ? CalculateSnappedAmount(unsnappedOffset, axis, gridSize * scaleRecip) : unsnappedOffset;
action.m_current.m_screenPosition = interaction.m_mousePick.m_screenCoordinates;
action.m_viewportId = interaction.m_interactionId.m_viewportId;
@@ -191,7 +196,8 @@ namespace AzToolsFramework
// note: m_localTransform must not be made uniform as it may contain a local scale we want to snap
m_onLeftMouseUpCallback(CalculateLinearManipulationDataAction(
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(), gridSnapParams, interaction));
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(), gridSnapParams,
interaction));
}
}
@@ -202,16 +208,14 @@ namespace AzToolsFramework
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const AZ::Transform localTransform = m_useVisualsOverride
? AZ::Transform::CreateFromQuaternionAndTranslation(
m_visualOrientationOverride, GetLocalPosition())
? AZ::Transform::CreateFromQuaternionAndTranslation(m_visualOrientationOverride, GetLocalPosition())
: GetLocalTransform();
if (cl_manipulatorDrawDebug)
{
if (PerformingAction())
{
const GridSnapParameters gridSnapParams =
GridSnapSettings(mouseInteraction.m_interactionId.m_viewportId);
const GridSnapParameters gridSnapParams = GridSnapSettings(mouseInteraction.m_interactionId.m_viewportId);
const auto action = CalculateLinearManipulationDataAction(
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(), gridSnapParams,
@@ -219,9 +223,10 @@ namespace AzToolsFramework
// display the exact hit (ray intersection) of the mouse pick on the manipulator
DrawTransformAxes(
debugDisplay, TransformUniformScale(GetSpace()) *
AZ::Transform::CreateTranslation(
action.m_start.m_localHitPosition + GetNonUniformScale() * action.m_current.m_localPositionOffset));
debugDisplay,
TransformUniformScale(GetSpace()) *
AZ::Transform::CreateTranslation(
action.m_start.m_localHitPosition + GetNonUniformScale() * action.m_current.m_localPositionOffset));
}
AZ::Transform combined = GetLocalTransform();
@@ -229,8 +234,7 @@ namespace AzToolsFramework
combined = GetSpace() * combined;
DrawTransformAxes(debugDisplay, combined);
DrawAxis(
debugDisplay, combined.GetTranslation(), TransformDirectionNoScaling(combined, m_fixed.m_axis));
DrawAxis(debugDisplay, combined.GetTranslation(), TransformDirectionNoScaling(combined, m_fixed.m_axis));
}
for (auto& view : m_manipulatorViews)
@@ -238,12 +242,9 @@ namespace AzToolsFramework
auto nonUniformScale = GetNonUniformScale();
view->Draw(
GetManipulatorManagerId(), managerState,
GetManipulatorId(), {
ApplySpace(localTransform), GetNonUniformScale(),
AZ::Vector3::CreateZero(), MouseOver()
},
debugDisplay, cameraState, mouseInteraction);
GetManipulatorManagerId(), managerState, GetManipulatorId(),
{ ApplySpace(localTransform), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay, cameraState,
mouseInteraction);
}
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -22,13 +22,13 @@ namespace AzToolsFramework
{
struct GridSnapParameters;
/// LinearManipulator serves as a visual tool for users to modify values
/// in one dimension on an axis defined in 3D space.
//! LinearManipulator serves as a visual tool for users to modify values
//! in one dimension on an axis defined in 3D space.
class LinearManipulator
: public BaseManipulator
, public ManipulatorSpaceWithLocalTransform
{
/// Private constructor.
//! Private constructor.
explicit LinearManipulator(const AZ::Transform& worldFromLocal);
public:
@@ -41,68 +41,80 @@ namespace AzToolsFramework
~LinearManipulator() = default;
/// A Manipulator must only be created and managed through a shared_ptr.
/// @note worldFromLocal should not contain scale.
//! A Manipulator must only be created and managed through a shared_ptr.
//! @note worldFromLocal should not contain scale.
static AZStd::shared_ptr<LinearManipulator> MakeShared(const AZ::Transform& worldFromLocal);
/// Unchanging data set once for the linear manipulator.
//! Unchanging data set once for the linear manipulator.
struct Fixed
{
AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX(); ///< The axis the manipulator will move along.
AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX(); //!< The axis the manipulator will move along.
};
/// Data passed between the initial press and first movement of the linear manipulator.
//! Data passed between the initial press and first movement of the linear manipulator.
struct StartTransition
{
/// The normal in local space of the manipulator when the mouse down event happens.
//! The normal in local space of the manipulator when the mouse down event happens.
AZ::Vector3 m_localNormal;
/// Used to scale movement based on camera distance if we want screen space instead
/// of world space displacement.
//! Used to scale movement based on camera distance if we want screen space instead
//! of world space displacement.
float m_screenToWorldScale;
};
/// The state of the manipulator at the start of an interaction.
//! The state of the manipulator at the start of an interaction.
struct Start
{
AZ::Vector3 m_localPosition; ///< The current position of the manipulator in local space.
AZ::Vector3 m_localScale; ///< The current scale of the manipulator in local space.
AZ::Vector3 m_localHitPosition; ///< The intersection point in local space between the ray and the manipulator when the mouse down event happens.
AZ::Vector3 m_localAxis; ///< The axis in the local space of the manipulator itself.
float m_sign; ///< Used to determine which side of the axis we clicked on in case it's flipped to face the camera.
AzFramework::ScreenPoint m_screenPosition; ///< The initial position in screen space of the manipulator.
AZ::Vector3 m_localPosition; //!< The current position of the manipulator in local space.
AZ::Vector3 m_localScale; //!< The current scale of the manipulator in local space.
AZ::Vector3 m_localHitPosition; //!< The intersection point in local space between the ray and the manipulator when the mouse
//!< down event happens.
AZ::Vector3 m_localAxis; //!< The axis in the local space of the manipulator itself.
float m_sign; //!< Used to determine which side of the axis we clicked on in case it's flipped to face the camera.
AzFramework::ScreenPoint m_screenPosition; //!< The initial position in screen space of the manipulator.
};
/// The state of the manipulator during an interaction.
//! The state of the manipulator during an interaction.
struct Current
{
AZ::Vector3 m_localPositionOffset; ///< The current offset of the manipulator from its starting position in local space.
AZ::Vector3 m_localScaleOffset; ///< The current offset of the manipulator from its starting scale in local space.
AzFramework::ScreenPoint m_screenPosition; ///< The current position in screen space of the manipulator.
AZ::Vector3 m_localPositionOffset; //!< The current offset of the manipulator from its starting position in local space.
AZ::Vector3 m_localScaleOffset; //!< The current offset of the manipulator from its starting scale in local space.
AzFramework::ScreenPoint m_screenPosition; //!< The current position in screen space of the manipulator.
};
/// Mouse action data used by MouseActionCallback (wraps Fixed, Start and Current manipulator state).
//! Mouse action data used by MouseActionCallback (wraps Fixed, Start and Current manipulator state).
struct Action
{
Fixed m_fixed;
Start m_start;
Current m_current;
ViewportInteraction::KeyboardModifiers m_modifiers;
int m_viewportId; ///< The id of the viewport this manipulator is being used in.
AZ::Vector3 LocalScale() const { return m_start.m_localScale + m_current.m_localScaleOffset; }
AZ::Vector3 LocalScaleOffset() const { return m_current.m_localScaleOffset; }
AZ::Vector3 LocalPosition() const { return m_start.m_localPosition + m_current.m_localPositionOffset; }
AZ::Vector3 LocalPositionOffset() const { return m_current.m_localPositionOffset; }
int m_viewportId; //!< The id of the viewport this manipulator is being used in.
AZ::Vector3 LocalScale() const
{
return m_start.m_localScale + m_current.m_localScaleOffset;
}
AZ::Vector3 LocalScaleOffset() const
{
return m_current.m_localScaleOffset;
}
AZ::Vector3 LocalPosition() const
{
return m_start.m_localPosition + m_current.m_localPositionOffset;
}
AZ::Vector3 LocalPositionOffset() const
{
return m_current.m_localPositionOffset;
}
AZ::Vector2 ScreenOffset() const
{
return AzFramework::Vector2FromScreenVector(
m_current.m_screenPosition - m_start.m_screenPosition);
return AzFramework::Vector2FromScreenVector(m_current.m_screenPosition - m_start.m_screenPosition);
}
};
/// This is the function signature of callbacks that will be invoked whenever a manipulator
/// is clicked on or dragged.
//! This is the function signature of callbacks that will be invoked whenever a manipulator
//! is clicked on or dragged.
using MouseActionCallback = AZStd::function<void(const Action&)>;
/// Tuple of StartTransition (initial mouse down to mouse move) and Start state.
//! Tuple of StartTransition (initial mouse down to mouse move) and Start state.
using Starter = AZStd::tuple<StartTransition, Start>;
void InstallLeftMouseDownCallback(const MouseActionCallback& onMouseDownCallback);
@@ -116,7 +128,10 @@ namespace AzToolsFramework
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
void SetAxis(const AZ::Vector3& axis);
const AZ::Vector3& GetAxis() const { return m_fixed.m_axis; }
const AZ::Vector3& GetAxis() const
{
return m_fixed.m_axis;
}
template<typename Views>
void SetViews(Views&& views)
@@ -135,12 +150,9 @@ namespace AzToolsFramework
}
private:
void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void InvalidateImpl() override;
void SetBoundsDirtyImpl() override;
@@ -155,16 +167,24 @@ namespace AzToolsFramework
MouseActionCallback m_onLeftMouseUpCallback = nullptr;
MouseActionCallback m_onMouseMoveCallback = nullptr;
ManipulatorViews m_manipulatorViews; ///< Look of manipulator.
ManipulatorViews m_manipulatorViews; //!< Look of manipulator.
};
LinearManipulator::Starter CalculateLinearManipulationDataStart(
const LinearManipulator::Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform, const ViewportInteraction::MouseInteraction& interaction, float intersectionDistance,
const LinearManipulator::Fixed& fixed,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const ViewportInteraction::MouseInteraction& interaction,
float intersectionDistance,
const AzFramework::CameraState& cameraState);
LinearManipulator::Action CalculateLinearManipulationDataAction(
const LinearManipulator::Fixed& fixed, const LinearManipulator::Starter& starter,
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
const GridSnapParameters& gridSnapParams, const ViewportInteraction::MouseInteraction& interaction);
const LinearManipulator::Fixed& fixed,
const LinearManipulator::Starter& starter,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const GridSnapParameters& gridSnapParams,
const ViewportInteraction::MouseInteraction& interaction);
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -26,56 +26,55 @@ namespace AzToolsFramework
using ManipulatorManagerId = IdType<struct ManipulatorManagerType>;
static const ManipulatorManagerId InvalidManipulatorManagerId = ManipulatorManagerId(0);
/// EBus interface used to send requests to ManipulatorManager.
class ManipulatorManagerRequests
: public AZ::EBusTraits
//! EBus interface used to send requests to ManipulatorManager.
class ManipulatorManagerRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; /**< We can have multiple manipulator managers.
In the case where there are multiple viewports, each displaying
a different set of entities, a different manipulator manager is required
to provide a different collision space for each viewport so that mouse
hit detection can be handled properly. */
//! We can have multiple manipulator managers.
//! In the case where there are multiple viewports, each displaying
//! a different set of entities, a different manipulator manager is required
//! to provide a different collision space for each viewport so that mouse
//! hit detection can be handled properly.
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = ManipulatorManagerId;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
virtual ~ManipulatorManagerRequests() = default;
/// Register a manipulator with the Manipulator Manager.
/// @param manipulator The manipulator parameter is passed as a shared_ptr so
/// that the system responsible for managing manipulators can maintain ownership
/// of the manipulator even if is destroyed while in use.
//! Register a manipulator with the Manipulator Manager.
//! @param manipulator The manipulator parameter is passed as a shared_ptr so
//! that the system responsible for managing manipulators can maintain ownership
//! of the manipulator even if is destroyed while in use.
virtual void RegisterManipulator(AZStd::shared_ptr<BaseManipulator> manipulator) = 0;
/// Unregister a manipulator from the Manipulator Manager.
/// After unregistering the manipulator, it will be excluded from mouse hit detection
/// and will not receive any mouse action events. The Manipulator Manager will also
/// relinquish ownership of the manipulator.
//! Unregister a manipulator from the Manipulator Manager.
//! After unregistering the manipulator, it will be excluded from mouse hit detection
//! and will not receive any mouse action events. The Manipulator Manager will also
//! relinquish ownership of the manipulator.
virtual void UnregisterManipulator(BaseManipulator* manipulator) = 0;
/// Delete a manipulator bound.
//! Delete a manipulator bound.
virtual void DeleteManipulatorBound(Picking::RegisteredBoundId boundId) = 0;
/// Mark the bound of a manipulator dirty so it's excluded from mouse hit detection.
/// This should be called whenever a manipulator is moved.
//! Mark the bound of a manipulator dirty so it's excluded from mouse hit detection.
//! This should be called whenever a manipulator is moved.
virtual void SetBoundDirty(Picking::RegisteredBoundId boundId) = 0;
/// Returns true if the manipulator manager is currently interacting, otherwise false.
//! Returns true if the manipulator manager is currently interacting, otherwise false.
virtual bool Interacting() const = 0;
/// Update the bound for a manipulator.
/// If \ref boundId hasn't been registered before or it's invalid, a new bound is created and set using \ref boundShapeData
/// @param manipulatorId The id of the manipulator whose bound needs to update.
/// @param boundId The id of the bound that needs to update.
/// @param boundShapeData The pointer to the new bound shape data.
/// @return If \ref boundId has been registered return the same id, otherwise create a new bound and return its id.
//! Update the bound for a manipulator.
//! If \ref boundId hasn't been registered before or it's invalid, a new bound is created and set using \ref boundShapeData.
//! @param manipulatorId The id of the manipulator whose bound needs to update.
//! @param boundId The id of the bound that needs to update.
//! @param boundShapeData The pointer to the new bound shape data.
//! @return If \ref boundId has been registered return the same id, otherwise create a new bound and return its id.
virtual Picking::RegisteredBoundId UpdateBound(
ManipulatorId manipulatorId, Picking::RegisteredBoundId boundId,
const Picking::BoundRequestShapeBase& boundShapeData) = 0;
ManipulatorId manipulatorId, Picking::RegisteredBoundId boundId, const Picking::BoundRequestShapeBase& boundShapeData) = 0;
};
/// Type to inherit to implement ManipulatorManagerRequests.
//! Type to inherit to implement ManipulatorManagerRequests.
using ManipulatorManagerRequestBus = AZ::EBus<ManipulatorManagerRequests>;
}//namespace AzToolsFramework
} // namespace AzToolsFramework
@@ -1,17 +1,17 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "BaseManipulator.h"
#include "ManipulatorManager.h"
#include "BaseManipulator.h"
#include <AzCore/std/tuple.h>
#include <AzToolsFramework/Picking/BoundInterface.h>
@@ -51,7 +51,8 @@ namespace AzToolsFramework
if (manipulator->Registered())
{
AZ_Assert(manipulator->GetManipulatorManagerId() == m_manipulatorManagerId,
AZ_Assert(
manipulator->GetManipulatorManagerId() == m_manipulatorManagerId,
"This manipulator was registered with a different manipulator manager!");
return;
}
@@ -75,8 +76,7 @@ namespace AzToolsFramework
}
Picking::RegisteredBoundId ManipulatorManager::UpdateBound(
const ManipulatorId manipulatorId, const Picking::RegisteredBoundId boundId,
const Picking::BoundRequestShapeBase& boundShapeData)
const ManipulatorId manipulatorId, const Picking::RegisteredBoundId boundId, const Picking::BoundRequestShapeBase& boundShapeData)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -99,8 +99,7 @@ namespace AzToolsFramework
AZ_Assert(boundItr->second == manipulatorId, "Manipulator and its bounds are out of synchronization!");
}
const Picking::RegisteredBoundId newBoundId =
m_boundManager.UpdateOrRegisterBound(boundShapeData, boundId);
const Picking::RegisteredBoundId newBoundId = m_boundManager.UpdateOrRegisterBound(boundShapeData, boundId);
if (newBoundId != boundId)
{
@@ -142,13 +141,6 @@ namespace AzToolsFramework
}
}
void ManipulatorManager::CheckModifierKeysChanged(
[[maybe_unused]] const ViewportInteraction::KeyboardModifiers keyboardModifiers,
const ViewportInteraction::MousePick& mousePick)
{
RefreshMouseOverState(mousePick);
}
void ManipulatorManager::DrawManipulators(
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
@@ -181,7 +173,8 @@ namespace AzToolsFramework
if (found != m_boundIdToManipulatorIdMap.end())
{
const auto manipulatorFound = m_manipulatorIdToPtrMap.find(found->second);
AZ_Assert(manipulatorFound != m_manipulatorIdToPtrMap.end(),
AZ_Assert(
manipulatorFound != m_manipulatorIdToPtrMap.end(),
"Found a bound without a corresponding Manipulator, "
"it's likely a bound was not cleaned up correctly");
rayIntersectionDistance = hitItr.second;
@@ -194,10 +187,9 @@ namespace AzToolsFramework
bool ManipulatorManager::ConsumeViewportMousePress(const ViewportInteraction::MouseInteraction& interaction)
{
if (auto pickedManipulator = PickManipulator(interaction.m_mousePick);
pickedManipulator.has_value())
if (auto pickedManipulator = PickManipulator(interaction.m_mousePick); pickedManipulator.has_value())
{
auto[manipulator, intersectionDistance] = pickedManipulator.value();
auto [manipulator, intersectionDistance] = pickedManipulator.value();
if (interaction.m_mouseButtons.Left())
{
@@ -249,24 +241,19 @@ namespace AzToolsFramework
const ViewportInteraction::MousePick& mousePick)
{
float intersectionDistance = 0.0f;
const AZStd::shared_ptr<BaseManipulator> pickedManipulator = PerformRaycast(
mousePick.m_rayOrigin, mousePick.m_rayDirection, intersectionDistance);
const AZStd::shared_ptr<BaseManipulator> pickedManipulator =
PerformRaycast(mousePick.m_rayOrigin, mousePick.m_rayDirection, intersectionDistance);
return pickedManipulator.get() != nullptr
? AZStd::make_optional(AZStd::make_tuple(pickedManipulator, intersectionDistance))
: AZStd::nullopt;
return pickedManipulator.get() != nullptr ? AZStd::make_optional(AZStd::make_tuple(pickedManipulator, intersectionDistance))
: AZStd::nullopt;
}
ManipulatorManager::PickedManipulatorId ManipulatorManager::PickManipulatorId(
const ViewportInteraction::MousePick& mousePick)
ManipulatorManager::PickedManipulatorId ManipulatorManager::PickManipulatorId(const ViewportInteraction::MousePick& mousePick)
{
auto [manipulator, intersectionDistance] =
PickManipulator(mousePick).value_or(PickedManipulator(nullptr, 0.0f));
const ManipulatorId pickedManipulatorId = manipulator
? manipulator->GetManipulatorId()
: InvalidManipulatorId;
auto [manipulator, intersectionDistance] = PickManipulator(mousePick).value_or(PickedManipulator(nullptr, 0.0f));
const ManipulatorId pickedManipulatorId = manipulator ? manipulator->GetManipulatorId() : InvalidManipulatorId;
return PickedManipulatorId{pickedManipulatorId, intersectionDistance};
return PickedManipulatorId{ pickedManipulatorId, intersectionDistance };
}
ManipulatorManager::ConsumeMouseMoveResult ManipulatorManager::ConsumeViewportMouseMove(
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -23,7 +23,7 @@ namespace AzFramework
{
struct CameraState;
class DebugDisplayRequests;
}
} // namespace AzFramework
namespace AzToolsFramework
{
@@ -40,15 +40,15 @@ namespace AzToolsFramework
class BaseManipulator;
class LinearManipulator;
/// State of overall manipulator manager.
//! State of overall manipulator manager.
struct ManipulatorManagerState
{
bool m_interacting;
};
/// This class serves to manage all relevant mouse events and coordinate all registered manipulators to function properly.
/// ManipulatorManager does not manage the life cycle of specific manipulators. The users of manipulators are responsible
/// for creating and deleting them at right time, as well as registering and unregistering accordingly.
//! This class serves to manage all relevant mouse events and coordinate all registered manipulators to function properly.
//! ManipulatorManager does not manage the life cycle of specific manipulators. The users of manipulators are responsible
//! for creating and deleting them at right time, as well as registering and unregistering accordingly.
class ManipulatorManager
: private ManipulatorManagerRequestBus::Handler
, private EditorEntityInfoNotificationBus::Handler
@@ -59,7 +59,7 @@ namespace AzToolsFramework
explicit ManipulatorManager(ManipulatorManagerId managerId);
~ManipulatorManager();
/// The result of consuming a mouse move.
//! The result of consuming a mouse move.
enum class ConsumeMouseMoveResult
{
None,
@@ -80,57 +80,52 @@ namespace AzToolsFramework
void DeleteManipulatorBound(Picking::RegisteredBoundId boundId) override;
void SetBoundDirty(Picking::RegisteredBoundId boundId) override;
Picking::RegisteredBoundId UpdateBound(
ManipulatorId manipulatorId, Picking::RegisteredBoundId boundId,
const Picking::BoundRequestShapeBase& boundShapeData) override;
bool Interacting() const override { return m_activeManipulator != nullptr; }
ManipulatorId manipulatorId, Picking::RegisteredBoundId boundId, const Picking::BoundRequestShapeBase& boundShapeData) override;
bool Interacting() const override
{
return m_activeManipulator != nullptr;
}
void DrawManipulators(
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction);
// O3DE_DEPRECATED(LY-117150)
/// Check if the modifier key state has changed - if so we may need to refresh
/// certain manipulator bounds.
AZ_DEPRECATED(
void CheckModifierKeysChanged(
ViewportInteraction::KeyboardModifiers keyboardModifiers,
const ViewportInteraction::MousePick& mousePick),
"CheckModifierKeysChanged is deprecated and will be removed in a future release");
protected:
/// @param rayOrigin The origin of the ray to test intersection with.
/// @param rayDirection The direction of the ray to test intersection with.
/// @param[out] rayIntersectionDistance The result intersecting point equals "rayOrigin + rayIntersectionDistance * rayDirection".
/// @return A pointer to a manipulator that the ray intersects. Null pointer if no intersection is detected.
//! @param rayOrigin The origin of the ray to test intersection with.
//! @param rayDirection The direction of the ray to test intersection with.
//! @param[out] rayIntersectionDistance The result intersecting point equals "rayOrigin + rayIntersectionDistance * rayDirection".
//! @return A pointer to a manipulator that the ray intersects. Null pointer if no intersection is detected.
AZStd::shared_ptr<BaseManipulator> PerformRaycast(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance);
// EditorEntityInfoNotifications ...
void OnEntityInfoUpdatedVisibility(AZ::EntityId entityId, bool visible) override;
/// Alias for a Manipulator and intersection distance.
//! Alias for a Manipulator and intersection distance.
using PickedManipulator = AZStd::tuple<AZStd::shared_ptr<BaseManipulator>, float>;
/// Alias for a ManipulatorId and intersection distance.
//! Alias for a ManipulatorId and intersection distance.
using PickedManipulatorId = AZStd::tuple<ManipulatorId, float>;
/// Return the picked manipulator and intersection distance if a manipulator was intersected.
//! Return the picked manipulator and intersection distance if a manipulator was intersected.
AZStd::optional<PickedManipulator> PickManipulator(const ViewportInteraction::MousePick& mousePick);
/// Wrapper for PickManipulator to return the ManipulatorId directly.
//! Wrapper for PickManipulator to return the ManipulatorId directly.
PickedManipulatorId PickManipulatorId(const ViewportInteraction::MousePick& mousePick);
/// Called once per frame after all manipulators have been drawn (and their
/// bounds updated if required).
//! Called once per frame after all manipulators have been drawn (and their
//! bounds updated if required).
void RefreshMouseOverState(const ViewportInteraction::MousePick& mousePick);
ManipulatorManagerId m_manipulatorManagerId; ///< This manipulator manager's id.
ManipulatorId m_nextManipulatorIdToGenerate; ///< Id to use for the next manipulator that is registered with this manager.
ManipulatorManagerId m_manipulatorManagerId; //!< This manipulator manager's id.
ManipulatorId m_nextManipulatorIdToGenerate; //!< Id to use for the next manipulator that is registered with this manager.
AZStd::unordered_map<ManipulatorId, AZStd::shared_ptr<BaseManipulator>> m_manipulatorIdToPtrMap; ///< Mapping from a manipulatorId to the corresponding manipulator.
AZStd::unordered_map<Picking::RegisteredBoundId, ManipulatorId> m_boundIdToManipulatorIdMap; ///< Mapping from a boundId to the corresponding manipulatorId.
AZStd::unordered_map<ManipulatorId, AZStd::shared_ptr<BaseManipulator>>
m_manipulatorIdToPtrMap; //!< Mapping from a manipulatorId to the corresponding manipulator.
AZStd::unordered_map<Picking::RegisteredBoundId, ManipulatorId>
m_boundIdToManipulatorIdMap; //!< Mapping from a boundId to the corresponding manipulatorId.
AZStd::shared_ptr<BaseManipulator> m_activeManipulator; ///< The manipulator we are currently interacting with.
Picking::ManipulatorBoundManager m_boundManager; ///< All active manipulator bounds that could be interacted with.
AZStd::shared_ptr<BaseManipulator> m_activeManipulator; //!< The manipulator we are currently interacting with.
Picking::ManipulatorBoundManager m_boundManager; //!< All active manipulator bounds that could be interacted with.
};
// The main/default ManipulatorManagerId to be used for
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ManipulatorSnapping.h"
@@ -19,19 +19,27 @@
#include <AzToolsFramework/Viewport/ViewportMessages.h>
AZ_CVAR(
AZ::Color, cl_viewportGridMainColor, AZ::Color::CreateFromRgba(26, 26, 26, 127), nullptr,
AZ::ConsoleFunctorFlags::Null, "Main color for snapping grid");
AZ::Color,
cl_viewportGridMainColor,
AZ::Color::CreateFromRgba(26, 26, 26, 127),
nullptr,
AZ::ConsoleFunctorFlags::Null,
"Main color for snapping grid");
AZ_CVAR(
AZ::Color, cl_viewportGridFadeColor, AZ::Color::CreateFromRgba(127, 127, 127, 0), nullptr,
AZ::ConsoleFunctorFlags::Null, "Fade color for snapping grid");
AZ::Color,
cl_viewportGridFadeColor,
AZ::Color::CreateFromRgba(127, 127, 127, 0),
nullptr,
AZ::ConsoleFunctorFlags::Null,
"Fade color for snapping grid");
AZ_CVAR(int, cl_viewportGridSquareCount, 20, nullptr, AZ::ConsoleFunctorFlags::Null, "Number of grid squares for snapping grid");
AZ_CVAR(float, cl_viewportGridLineWidth, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Width of grid lines for snapping grid");
AZ_CVAR(
int, cl_viewportGridSquareCount, 20, nullptr, AZ::ConsoleFunctorFlags::Null,
"Number of grid squares for snapping grid");
AZ_CVAR(
float, cl_viewportGridLineWidth, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null,
"Width of grid lines for snapping grid");
AZ_CVAR(
float, cl_viewportFadeLineDistanceScale, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null,
float,
cl_viewportFadeLineDistanceScale,
1.0f,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The scale to be applied to the line that fades out (scales the current gridSize)");
namespace AzToolsFramework
@@ -43,16 +51,17 @@ namespace AzToolsFramework
}
ManipulatorInteraction BuildManipulatorInteraction(
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
const AZ::Vector3& worldRayOrigin, const AZ::Vector3& worldRayDirection)
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Vector3& worldRayOrigin,
const AZ::Vector3& worldRayDirection)
{
const AZ::Transform worldFromLocalUniform = AzToolsFramework::TransformUniformScale(worldFromLocal);
const AZ::Transform localFromWorldUniform = worldFromLocalUniform.GetInverse();
return {localFromWorldUniform.TransformPoint(worldRayOrigin),
TransformDirectionNoScaling(localFromWorldUniform, worldRayDirection),
NonUniformScaleReciprocal(nonUniformScale),
ScaleReciprocal(worldFromLocalUniform)};
return { localFromWorldUniform.TransformPoint(worldRayOrigin),
TransformDirectionNoScaling(localFromWorldUniform, worldRayDirection), NonUniformScaleReciprocal(nonUniformScale),
ScaleReciprocal(worldFromLocalUniform) };
}
struct SnapAdjustment
@@ -87,8 +96,7 @@ namespace AzToolsFramework
}
AZ::Vector3 CalculateSnappedTerrainPosition(
const AZ::Vector3& worldSurfacePosition, const AZ::Transform& worldFromLocal,
const int viewportId, const float gridSize)
const AZ::Vector3& worldSurfacePosition, const AZ::Transform& worldFromLocal, const int viewportId, const float gridSize)
{
const AZ::Transform localFromWorld = worldFromLocal.GetInverse();
const AZ::Vector3 localSurfacePosition = localFromWorld.TransformPoint(worldSurfacePosition);
@@ -101,8 +109,7 @@ namespace AzToolsFramework
// find terrain height at xy snapped location
float terrainHeight = 0.0f;
ViewportInteraction::MainEditorViewportInteractionRequestBus::EventResult(
terrainHeight, viewportId,
&ViewportInteraction::MainEditorViewportInteractionRequestBus::Events::TerrainHeight,
terrainHeight, viewportId, &ViewportInteraction::MainEditorViewportInteractionRequestBus::Events::TerrainHeight,
Vector3ToVector2(worldFromLocal.TransformPoint(localSnappedSurfacePosition)));
// set snapped z value to terrain height
@@ -116,8 +123,7 @@ namespace AzToolsFramework
{
bool snapping = false;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
snapping, viewportId,
&ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
snapping, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
return snapping;
}
@@ -126,8 +132,7 @@ namespace AzToolsFramework
{
float gridSize = 0.0f;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
gridSize, viewportId,
&ViewportInteraction::ViewportInteractionRequestBus::Events::GridSize);
gridSize, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSize);
return gridSize;
}
@@ -136,7 +141,8 @@ namespace AzToolsFramework
{
bool snapping = GridSnapping(viewportId);
const float gridSize = GridSize(viewportId);
if (AZ::IsClose(gridSize, 0.0f, 1e-2f)) // Same threshold value as min value for m_spinBox in SnapToWidget constructor in MainWindow.cpp
if (AZ::IsClose(
gridSize, 0.0f, 1e-2f)) // Same threshold value as min value for m_spinBox in SnapToWidget constructor in MainWindow.cpp
{
snapping = false;
}
@@ -148,8 +154,7 @@ namespace AzToolsFramework
{
bool snapping = false;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
snapping, viewportId,
&ViewportInteraction::ViewportInteractionRequestBus::Events::AngleSnappingEnabled);
snapping, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::AngleSnappingEnabled);
return snapping;
}
@@ -158,8 +163,7 @@ namespace AzToolsFramework
{
float angle = 0.0f;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
angle, viewportId,
&ViewportInteraction::ViewportInteractionRequestBus::Events::AngleStep);
angle, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::AngleStep);
return angle;
}
@@ -168,14 +172,12 @@ namespace AzToolsFramework
{
bool show = false;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
show, viewportId,
&ViewportInteraction::ViewportInteractionRequestBus::Events::ShowGrid);
show, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::ShowGrid);
return show;
}
void DrawSnappingGrid(
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Transform& worldFromLocal, const float squareSize)
void DrawSnappingGrid(AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Transform& worldFromLocal, const float squareSize)
{
debugDisplay.PushMatrix(worldFromLocal);
@@ -197,21 +199,17 @@ namespace AzToolsFramework
// draw the faded end parts of the grid lines
debugDisplay.DrawLine(
AZ::Vector3(lineOffset, -halfGridSize, 0.0f),
AZ::Vector3(lineOffset, -(halfGridSize + fadeLineLength), 0.0f),
AZ::Vector3(lineOffset, -halfGridSize, 0.0f), AZ::Vector3(lineOffset, -(halfGridSize + fadeLineLength), 0.0f),
gridMainColor, gridFadeColor);
debugDisplay.DrawLine(
AZ::Vector3(lineOffset, halfGridSize, 0.0f),
AZ::Vector3(lineOffset, (halfGridSize + fadeLineLength), 0.0f),
AZ::Vector3(lineOffset, halfGridSize, 0.0f), AZ::Vector3(lineOffset, (halfGridSize + fadeLineLength), 0.0f), gridMainColor,
gridFadeColor);
debugDisplay.DrawLine(
AZ::Vector3(-halfGridSize, lineOffset, 0.0f), AZ::Vector3(-(halfGridSize + fadeLineLength), lineOffset, 0.0f),
gridMainColor, gridFadeColor);
debugDisplay.DrawLine(
AZ::Vector3(-halfGridSize, lineOffset, 0.0f),
AZ::Vector3(-(halfGridSize + fadeLineLength), lineOffset, 0.0f),
gridMainColor, gridFadeColor);
debugDisplay.DrawLine(
AZ::Vector3(halfGridSize, lineOffset, 0.0f),
AZ::Vector3((halfGridSize + fadeLineLength), lineOffset, 0.0f),
gridMainColor, gridFadeColor);
AZ::Vector3(halfGridSize, lineOffset, 0.0f), AZ::Vector3((halfGridSize + fadeLineLength), lineOffset, 0.0f), gridMainColor,
gridFadeColor);
// build a vector of the main grid lines to draw (start and end positions)
lines.push_back(AZ::Vector3(lineOffset, -halfGridSize, 0.0f));
@@ -1,19 +1,19 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/Vector3.h>
namespace AzFramework
{
@@ -22,7 +22,7 @@ namespace AzFramework
namespace AzToolsFramework
{
/// Structure to encapsulate grid snapping properties.
//! Structure to encapsulate grid snapping properties.
struct GridSnapParameters
{
GridSnapParameters(bool gridSnap, float gridSize);
@@ -31,96 +31,92 @@ namespace AzToolsFramework
float m_gridSize;
};
/// Structure to hold transformed incoming viewport interaction from world space to manipulator space.
//! Structure to hold transformed incoming viewport interaction from world space to manipulator space.
struct ManipulatorInteraction
{
AZ::Vector3 m_localRayOrigin; ///< The ray origin (start) in the reference from of the manipulator.
AZ::Vector3 m_localRayDirection; ///< The ray direction in the reference from of the manipulator.
AZ::Vector3 m_nonUniformScaleReciprocal; ///< Handles inverting any non-uniform scale which was applied
///< separately from the transform.
float m_scaleReciprocal; ///< The scale reciprocal (1.0 / scale) of the transform used to move the
///< ray from world space to local space.
AZ::Vector3 m_localRayOrigin; //!< The ray origin (start) in the reference from of the manipulator.
AZ::Vector3 m_localRayDirection; //!< The ray direction in the reference from of the manipulator.
AZ::Vector3 m_nonUniformScaleReciprocal; //!< Handles inverting any non-uniform scale which was applied
//!< separately from the transform.
float m_scaleReciprocal; //!< The scale reciprocal (1.0 / scale) of the transform used to move the
//!< ray from world space to local space.
};
/// Build a ManipulatorInteraction structure from the incoming viewport interaction.
//! Build a ManipulatorInteraction structure from the incoming viewport interaction.
ManipulatorInteraction BuildManipulatorInteraction(
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
const AZ::Vector3& worldRayOrigin, const AZ::Vector3& worldRayDirection);
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Vector3& worldRayOrigin,
const AZ::Vector3& worldRayDirection);
/// Calculate the offset along an axis to adjust a position to stay snapped to a given grid size.
/// @note This is snap up or down to the nearest grid segment (e.g. 0.2 snaps to 0.0 -> delta 0.2,
/// 0.7 snaps to 1.0 -> delta 0.3).
AZ::Vector3 CalculateSnappedOffset(
const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, float size);
//! Calculate the offset along an axis to adjust a position to stay snapped to a given grid size.
//! @note This is snap up or down to the nearest grid segment (e.g. 0.2 snaps to 0.0 -> delta 0.2,
//! 0.7 snaps to 1.0 -> delta 0.3).
AZ::Vector3 CalculateSnappedOffset(const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, float size);
/// Return the amount to snap from the starting position given the current grid size.
/// @note A movement of more than half size (in either direction) will cause a snap by size.
//! Return the amount to snap from the starting position given the current grid size.
//! @note A movement of more than half size (in either direction) will cause a snap by size.
AZ::Vector3 CalculateSnappedAmount(const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, float size);
/// For a given point on the terrain, calculate the closest xy position snapped to the grid
/// (z position is aligned to terrain height, not snapped to z grid)
//! For a given point on the terrain, calculate the closest xy position snapped to the grid
//! (z position is aligned to terrain height, not snapped to z grid)
AZ::Vector3 CalculateSnappedTerrainPosition(
const AZ::Vector3& worldSurfacePosition, const AZ::Transform& worldFromLocal,
int viewportId, float gridSize);
const AZ::Vector3& worldSurfacePosition, const AZ::Transform& worldFromLocal, int viewportId, float gridSize);
/// Wrapper for grid snapping and grid size bus calls.
//! Wrapper for grid snapping and grid size bus calls.
GridSnapParameters GridSnapSettings(int viewportId);
/// Wrapper for angle snapping enabled bus call.
//! Wrapper for angle snapping enabled bus call.
bool AngleSnapping(int viewportId);
/// Wrapper for angle snapping increment bus call.
/// @return Angle in degrees
//! Wrapper for angle snapping increment bus call.
//! @return Angle in degrees.
float AngleStep(int viewportId);
/// Wrapper for grid rendering check call.
//! Wrapper for grid rendering check call.
bool ShowingGrid(int viewportId);
/// Render the grid used for snapping.
void DrawSnappingGrid(
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Transform& worldFromLocal, float squareSize);
//! Render the grid used for snapping.
void DrawSnappingGrid(AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Transform& worldFromLocal, float squareSize);
/// Round to x number of significant digits.
/// @param value Number to round.
/// @param exponent Precision to use when rounding.
//! Round to x number of significant digits.
//! @param value Number to round.
//! @param exponent Precision to use when rounding.
inline float Round(const float value, const float exponent)
{
const float precision = std::pow(10.0f, exponent);
return roundf(value * precision) / precision;
}
/// Round to 3 significant digits (3 digits common usage).
//! Round to 3 significant digits (3 digits common usage).
inline float Round3(const float value)
{
return Round(value, 3.0f);
}
/// Util to return sign of floating point number.
/// value > 0 return 1.0
/// value < 0 return -1.0
/// value == 0 return 0.0
//! Util to return sign of floating point number.
//! value > 0 return 1.0
//! value < 0 return -1.0
//! value == 0 return 0.0
inline float Sign(const float value)
{
return static_cast<float>((0.0f < value) - (value < 0.0f));
}
/// Find the max scale element and return the reciprocal of it.
/// Note: The reciprocal will be rounded to three significant digits to eliminate
/// noise in the value returned when dealing with values far from the origin.
//! Find the max scale element and return the reciprocal of it.
//! Note: The reciprocal will be rounded to three significant digits to eliminate
//! noise in the value returned when dealing with values far from the origin.
inline float ScaleReciprocal(const AZ::Transform& transform)
{
return Round3(1.0f / transform.GetUniformScale());
}
/// Find the reciprocal of the non-uniform scale.
/// Each element will be rounded to three significant digits to eliminate noise
/// when dealing with values far from the origin.
//! Find the reciprocal of the non-uniform scale.
//! Each element will be rounded to three significant digits to eliminate noise
//! when dealing with values far from the origin.
inline AZ::Vector3 NonUniformScaleReciprocal(const AZ::Vector3& nonUniformScale)
{
AZ::Vector3 scaleReciprocal = nonUniformScale.GetReciprocal();
return AZ::Vector3(
Round3(scaleReciprocal.GetX()),
Round3(scaleReciprocal.GetY()),
Round3(scaleReciprocal.GetZ()));
return AZ::Vector3(Round3(scaleReciprocal.GetX()), Round3(scaleReciprocal.GetY()), Round3(scaleReciprocal.GetZ()));
}
} // namespace AzToolsFramework
@@ -20,7 +20,7 @@ namespace AZ
namespace AzToolsFramework
{
/// Handles location for manipulators which have a global space but no local transformation.
//! Handles location for manipulators which have a global space but no local transformation.
class ManipulatorSpace
{
public:
@@ -32,17 +32,16 @@ namespace AzToolsFramework
const AZ::Vector3& GetNonUniformScale() const;
void SetNonUniformScale(const AZ::Vector3& nonUniformScale);
/// Calculates a transform combining the space and local transform, taking non-uniform scale into account.
//! Calculates a transform combining the space and local transform, taking non-uniform scale into account.
AZ::Transform ApplySpace(const AZ::Transform& localTransform) const;
private:
AZ::Transform m_space = AZ::Transform::CreateIdentity(); ///< Space the manipulator is in.
AZ::Vector3 m_nonUniformScale = AZ::Vector3::CreateOne(); ///< Handles non-uniform scale for the space the manipulator is in.
AZ::Transform m_space = AZ::Transform::CreateIdentity(); //!< Space the manipulator is in.
AZ::Vector3 m_nonUniformScale = AZ::Vector3::CreateOne(); //!< Handles non-uniform scale for the space the manipulator is in.
};
/// Handles location for manipulators which have a global space and a local position, but no local rotation.
class ManipulatorSpaceWithLocalPosition
: public ManipulatorSpace
//! Handles location for manipulators which have a global space and a local position, but no local rotation.
class ManipulatorSpaceWithLocalPosition : public ManipulatorSpace
{
public:
AZ_TYPE_INFO(ManipulatorSpaceWithLocalPosition, "{47BE15AF-60A8-436B-8F3F-7DDFB97220E6}")
@@ -52,12 +51,11 @@ namespace AzToolsFramework
void SetLocalPosition(const AZ::Vector3& localPosition);
private:
AZ::Vector3 m_localPosition = AZ::Vector3::CreateZero(); ///< Position in local space.
AZ::Vector3 m_localPosition = AZ::Vector3::CreateZero(); //!< Position in local space.
};
/// Handles location for manipulators which have a global space and a local transform (position and rotation).
class ManipulatorSpaceWithLocalTransform
: public ManipulatorSpace
//! Handles location for manipulators which have a global space and a local transform (position and rotation).
class ManipulatorSpaceWithLocalTransform : public ManipulatorSpace
{
public:
AZ_TYPE_INFO(ManipulatorSpaceWithLocalTransform, "{6D100797-1DD8-45B0-A21C-8893B770C0BC}")
@@ -72,6 +70,6 @@ namespace AzToolsFramework
void SetLocalOrientation(const AZ::Quaternion& localOrientation);
private:
AZ::Transform m_localTransform = AZ::Transform::CreateIdentity(); ///< Local transform.
AZ::Transform m_localTransform = AZ::Transform::CreateIdentity(); //!< Local transform.
};
} // namespace AzToolsFramework
@@ -1,26 +1,26 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ManipulatorView.h"
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Component/NonUniformScaleBus.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/VectorConversions.h>
#include <AzCore/std/containers/array.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/Manipulators/AngularManipulator.h>
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
#include <AzToolsFramework/Manipulators/LineSegmentSelectionManipulator.h>
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/Manipulators/PlanarManipulator.h>
#include <AzToolsFramework/Manipulators/SplineSelectionManipulator.h>
#include <AzToolsFramework/Maths/TransformUtils.h>
@@ -33,8 +33,7 @@ namespace AzToolsFramework
AZ::Transform WorldFromLocalWithUniformScale(const AZ::EntityId entityId)
{
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(
worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
return TransformUniformScale(worldFromLocal);
}
@@ -56,13 +55,16 @@ namespace AzToolsFramework
return AzToolsFramework::TransformDirectionNoScaling(m_worldFromLocal, direction);
}
/// Take into account the location of the camera and orientate the axis so it faces the camera.
/// if we did correct the camera (shouldCorrect is true) then we know the axis facing us it negative.
/// we can use this to change the rendering for a flipped axis if we wish.
// Take into account the location of the camera and orientate the axis so it faces the camera.
// if we did correct the camera (shouldCorrect is true) then we know the axis facing us it negative.
// we can use this to change the rendering for a flipped axis if we wish.
static void CameraCorrectAxis(
const AZ::Vector3& axis, AZ::Vector3& correctedAxis, const ManipulatorManagerState& managerState,
const AZ::Vector3& axis,
AZ::Vector3& correctedAxis,
const ManipulatorManagerState& managerState,
const ViewportInteraction::MouseInteraction& mouseInteraction,
const AZ::Transform& worldFromLocal, const AZ::Vector3& localPosition,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& localPosition,
const AzFramework::CameraState& cameraState,
bool* shouldCorrect = nullptr)
{
@@ -74,9 +76,7 @@ namespace AzToolsFramework
const bool correcting = ShouldFlipCameraAxis(worldFromLocal, localPosition, axis, cameraState);
// the corrected axis, if no flip was required, output == input
correctedAxis = correcting
? -axis
: axis;
correctedAxis = correcting ? -axis : axis;
// optional out ref to use if we care about the result
if (shouldCorrect)
@@ -86,10 +86,13 @@ namespace AzToolsFramework
}
}
/// Calculate quad bound in world space.
// calculate quad bound in world space.
static Picking::BoundShapeQuad CalculateQuadBound(
const AZ::Vector3& localPosition, const ManipulatorState& manipulatorState,
const AZ::Vector3& axis1, const AZ::Vector3& axis2, const float size)
const AZ::Vector3& localPosition,
const ManipulatorState& manipulatorState,
const AZ::Vector3& axis1,
const AZ::Vector3& axis2,
const float size)
{
const AZ::Vector3 worldPosition = manipulatorState.TransformPoint(localPosition);
const AZ::Vector3 endAxis1World = manipulatorState.TransformDirectionNoScaling(axis1) * size;
@@ -104,8 +107,10 @@ namespace AzToolsFramework
}
static Picking::BoundShapeQuad CalculateQuadBoundBillboard(
const AZ::Vector3& localPosition, const AZ::Transform& worldFromLocal,
const float size, const AzFramework::CameraState& cameraState)
const AZ::Vector3& localPosition,
const AZ::Transform& worldFromLocal,
const float size,
const AzFramework::CameraState& cameraState)
{
const AZ::Vector3 worldPosition = worldFromLocal.TransformPoint(localPosition);
@@ -117,10 +122,13 @@ namespace AzToolsFramework
return quadBound;
}
/// Calculate line bound in world space (axis and length).
// calculate line bound in world space (axis and length).
static Picking::BoundShapeLineSegment CalculateLineBound(
const AZ::Vector3& localPosition, const AZ::Transform& worldFromLocal,
const AZ::Vector3& axis, const float length, const float width)
const AZ::Vector3& localPosition,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& axis,
const float length,
const float width)
{
Picking::BoundShapeLineSegment lineBound;
lineBound.m_start = worldFromLocal.TransformPoint(localPosition);
@@ -129,7 +137,7 @@ namespace AzToolsFramework
return lineBound;
}
/// Calculate line bound in world space (start and end point).
// calculate line bound in world space (start and end point).
static Picking::BoundShapeLineSegment CalculateLineBound(
const AZ::Vector3& localStartPosition,
const AZ::Vector3& localEndPosition,
@@ -143,10 +151,14 @@ namespace AzToolsFramework
return lineBound;
}
/// Calculate cone bound in world space.
// calculate cone bound in world space.
static Picking::BoundShapeCone CalculateConeBound(
const AZ::Vector3& localPosition, const AZ::Transform& worldFromLocal,
const AZ::Vector3& axis, const AZ::Vector3& offset, const float length, const float radius)
const AZ::Vector3& localPosition,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& axis,
const AZ::Vector3& offset,
const float length,
const float radius)
{
Picking::BoundShapeCone coneBound;
coneBound.m_radius = radius;
@@ -156,10 +168,13 @@ namespace AzToolsFramework
return coneBound;
}
/// Calculate box bound in world space.
// calculate box bound in world space.
static Picking::BoundShapeBox CalculateBoxBound(
const AZ::Vector3& localPosition, const AZ::Transform& worldFromLocal,
const AZ::Quaternion& orientation, const AZ::Vector3& offset, const AZ::Vector3& halfExtents)
const AZ::Vector3& localPosition,
const AZ::Transform& worldFromLocal,
const AZ::Quaternion& orientation,
const AZ::Vector3& offset,
const AZ::Vector3& halfExtents)
{
Picking::BoundShapeBox boxBound;
boxBound.m_halfExtents = halfExtents;
@@ -168,10 +183,13 @@ namespace AzToolsFramework
return boxBound;
}
/// Calculate cylinder bound in world space.
// calculate cylinder bound in world space.
static Picking::BoundShapeCylinder CalculateCylinderBound(
const AZ::Vector3& localPosition, const AZ::Transform& worldFromLocal,
const AZ::Vector3& axis, const float length, const float radius)
const AZ::Vector3& localPosition,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& axis,
const float length,
const float radius)
{
Picking::BoundShapeCylinder boxBound;
boxBound.m_base = worldFromLocal.TransformPoint(localPosition);
@@ -181,10 +199,9 @@ namespace AzToolsFramework
return boxBound;
}
/// Calculate sphere bound in world space.
// calculate sphere bound in world space.
static Picking::BoundShapeSphere CalculateSphereBound(
const AZ::Vector3& localPosition, const ManipulatorState& manipulatorState,
const float radius)
const AZ::Vector3& localPosition, const ManipulatorState& manipulatorState, const float radius)
{
Picking::BoundShapeSphere sphereBound;
sphereBound.m_center = manipulatorState.TransformPoint(localPosition);
@@ -192,10 +209,13 @@ namespace AzToolsFramework
return sphereBound;
}
/// Calculate torus bound in world space.
// calculate torus bound in world space.
static Picking::BoundShapeTorus CalculateTorusBound(
const AZ::Vector3& localPosition, const AZ::Transform& worldFromLocal,
const AZ::Vector3& axis, const float radius, const float width)
const AZ::Vector3& localPosition,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& axis,
const float radius,
const float width)
{
Picking::BoundShapeTorus torusBound;
torusBound.m_center = worldFromLocal.TransformPoint(localPosition);
@@ -205,7 +225,7 @@ namespace AzToolsFramework
return torusBound;
}
/// Calculate spline bound in world space.
// calculate spline bound in world space.
static Picking::BoundShapeSpline CalculateSplineBound(
const AZStd::weak_ptr<const AZ::Spline>& spline, const AZ::Transform& worldFromLocal, const float width)
{
@@ -224,8 +244,7 @@ namespace AzToolsFramework
return lineWidth[mouseOver];
}
static AZ::Color ViewColor(
const bool mouseOver, const AZ::Color& defaultColor, const AZ::Color& mouseOverColor)
static AZ::Color ViewColor(const bool mouseOver, const AZ::Color& defaultColor, const AZ::Color& mouseOverColor)
{
const AZStd::array<AZ::Color, 2> viewColor = { { defaultColor, mouseOverColor } };
return viewColor[mouseOver].GetAsVector4();
@@ -250,19 +269,16 @@ namespace AzToolsFramework
void ManipulatorView::SetBoundDirty(const ManipulatorManagerId managerId)
{
ManipulatorManagerRequestBus::Event(
managerId, &ManipulatorManagerRequestBus::Events::SetBoundDirty, m_boundId);
ManipulatorManagerRequestBus::Event(managerId, &ManipulatorManagerRequestBus::Events::SetBoundDirty, m_boundId);
m_boundDirty = true;
}
void ManipulatorView::RefreshBound(
const ManipulatorManagerId managerId, const ManipulatorId manipulatorId,
const Picking::BoundRequestShapeBase& bound)
const ManipulatorManagerId managerId, const ManipulatorId manipulatorId, const Picking::BoundRequestShapeBase& bound)
{
ManipulatorManagerRequestBus::EventResult(
m_boundId, managerId, &ManipulatorManagerRequestBus::Events::UpdateBound,
manipulatorId, m_boundId, bound);
m_boundId, managerId, &ManipulatorManagerRequestBus::Events::UpdateBound, manipulatorId, m_boundId, bound);
// store the manager id if we know the bound has been registered
m_managerId = managerId;
@@ -271,8 +287,7 @@ namespace AzToolsFramework
}
void ManipulatorView::RefreshBoundInternal(
const ManipulatorManagerId managerId, const ManipulatorId manipulatorId,
const Picking::BoundRequestShapeBase& bound)
const ManipulatorManagerId managerId, const ManipulatorId manipulatorId, const Picking::BoundRequestShapeBase& bound)
{
// update the manipulator's bounds if necessary
// if m_screenSizeFixed is true, any camera movement can potentially change the size
@@ -287,8 +302,7 @@ namespace AzToolsFramework
{
if (m_boundId != Picking::InvalidBoundId)
{
ManipulatorManagerRequestBus::Event(
managerId, &ManipulatorManagerRequestBus::Events::DeleteManipulatorBound, m_boundId);
ManipulatorManagerRequestBus::Event(managerId, &ManipulatorManagerRequestBus::Events::DeleteManipulatorBound, m_boundId);
m_boundId = Picking::InvalidBoundId;
}
@@ -297,33 +311,34 @@ namespace AzToolsFramework
float ManipulatorView::ManipulatorViewScaleMultiplier(
const AZ::Vector3& worldPosition, const AzFramework::CameraState& cameraState) const
{
return ScreenSizeFixed()
? CalculateScreenToWorldMultiplier(worldPosition, cameraState)
: 1.0f;
return ScreenSizeFixed() ? CalculateScreenToWorldMultiplier(worldPosition, cameraState) : 1.0f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ManipulatorViewQuad::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const AZ::Vector3 axis1 = m_axis1;
const AZ::Vector3 axis2 = m_axis2;
CameraCorrectAxis(
axis1, m_cameraCorrectedAxis1, managerState, mouseInteraction,
manipulatorState.m_worldFromLocal, manipulatorState.m_localPosition, cameraState);
axis1, m_cameraCorrectedAxis1, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState);
CameraCorrectAxis(
axis2, m_cameraCorrectedAxis2, managerState, mouseInteraction,
manipulatorState.m_worldFromLocal, manipulatorState.m_localPosition, cameraState);
axis2, m_cameraCorrectedAxis2, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState);
const Picking::BoundShapeQuad quadBound =
CalculateQuadBound(
manipulatorState.m_localPosition, manipulatorState, m_cameraCorrectedAxis1, m_cameraCorrectedAxis2,
m_size * ManipulatorViewScaleMultiplier(
const Picking::BoundShapeQuad quadBound = CalculateQuadBound(
manipulatorState.m_localPosition, manipulatorState, m_cameraCorrectedAxis1, m_cameraCorrectedAxis2,
m_size *
ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState));
debugDisplay.SetLineWidth(defaultLineWidth(manipulatorState.m_mouseOver));
@@ -339,9 +354,7 @@ namespace AzToolsFramework
debugDisplay.SetColor(Vector3ToVector4(m_mouseOverColor.GetAsVector3(), 0.5f));
debugDisplay.CullOff();
debugDisplay.DrawQuad(
quadBound.m_corner1, quadBound.m_corner2,
quadBound.m_corner3, quadBound.m_corner4);
debugDisplay.DrawQuad(quadBound.m_corner1, quadBound.m_corner2, quadBound.m_corner3, quadBound.m_corner4);
debugDisplay.CullOn();
}
@@ -349,41 +362,46 @@ namespace AzToolsFramework
}
void ManipulatorViewQuadBillboard::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& /*mouseInteraction*/)
{
const Picking::BoundShapeQuad quadBound =
CalculateQuadBoundBillboard(manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal,
m_size * ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState), cameraState);
const Picking::BoundShapeQuad quadBound = CalculateQuadBoundBillboard(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal,
m_size *
ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState),
cameraState);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
debugDisplay.DrawQuad(
quadBound.m_corner1, quadBound.m_corner2,
quadBound.m_corner3, quadBound.m_corner4);
debugDisplay.DrawQuad(quadBound.m_corner1, quadBound.m_corner2, quadBound.m_corner3, quadBound.m_corner4);
RefreshBoundInternal(managerId, manipulatorId, quadBound);
}
void ManipulatorViewLine::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const float viewScale = ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const float viewScale =
ManipulatorViewScaleMultiplier(manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
CameraCorrectAxis(
m_axis, m_cameraCorrectedAxis, managerState, mouseInteraction,
manipulatorState.m_worldFromLocal, manipulatorState.m_localPosition, cameraState);
m_axis, m_cameraCorrectedAxis, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState);
const Picking::BoundShapeLineSegment lineBound =
CalculateLineBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal,
m_cameraCorrectedAxis, m_length * viewScale, m_width * viewScale);
const Picking::BoundShapeLineSegment lineBound = CalculateLineBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis, m_length * viewScale,
m_width * viewScale);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
debugDisplay.SetLineWidth(defaultLineWidth(manipulatorState.m_mouseOver));
@@ -393,13 +411,16 @@ namespace AzToolsFramework
}
void ManipulatorViewLineSelect::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const float viewScale = ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const float viewScale =
ManipulatorViewScaleMultiplier(manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const Picking::BoundShapeLineSegment lineBound =
CalculateLineBound(m_localStart, m_localEnd, manipulatorState, m_width * viewScale);
@@ -407,44 +428,42 @@ namespace AzToolsFramework
if (manipulatorState.m_mouseOver)
{
const LineSegmentSelectionManipulator::Action action = CalculateManipulationDataAction(
manipulatorState.m_worldFromLocal, manipulatorState.m_nonUniformScale,
mouseInteraction.m_mousePick.m_rayOrigin, mouseInteraction.m_mousePick.m_rayDirection,
cameraState.m_farClip, m_localStart, m_localEnd);
manipulatorState.m_worldFromLocal, manipulatorState.m_nonUniformScale, mouseInteraction.m_mousePick.m_rayOrigin,
mouseInteraction.m_mousePick.m_rayDirection, cameraState.m_farClip, m_localStart, m_localEnd);
const AZ::Vector3 worldLineHitPosition = manipulatorState.TransformPoint(action.m_localLineHitPosition);
debugDisplay.SetColor(AZ::Vector4(0.0f, 1.0f, 0.0f, 1.0f));
debugDisplay.DrawBall(
worldLineHitPosition, ManipulatorViewScaleMultiplier(worldLineHitPosition, cameraState)
* g_defaultManipulatorSphereRadius, false);
worldLineHitPosition, ManipulatorViewScaleMultiplier(worldLineHitPosition, cameraState) * g_defaultManipulatorSphereRadius,
false);
}
RefreshBoundInternal(managerId, manipulatorId, lineBound);
}
void ManipulatorViewCone::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const float viewScale = ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const float viewScale =
ManipulatorViewScaleMultiplier(manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
CameraCorrectAxis(
m_axis, m_cameraCorrectedAxis, managerState, mouseInteraction,
manipulatorState.m_worldFromLocal, manipulatorState.m_localPosition,
cameraState, &m_shouldCorrect);
m_axis, m_cameraCorrectedAxis, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState, &m_shouldCorrect);
CameraCorrectAxis(
m_offset, m_cameraCorrectedOffset, managerState, mouseInteraction,
manipulatorState.m_worldFromLocal, manipulatorState.m_localPosition, cameraState);
m_offset, m_cameraCorrectedOffset, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState);
const Picking::BoundShapeCone coneBound =
CalculateConeBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis,
m_cameraCorrectedOffset * viewScale,
m_length * viewScale,
m_radius * viewScale);
const Picking::BoundShapeCone coneBound = CalculateConeBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis, m_cameraCorrectedOffset * viewScale,
m_length * viewScale, m_radius * viewScale);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
if (m_shouldCorrect)
@@ -460,73 +479,77 @@ namespace AzToolsFramework
}
void ManipulatorViewBox::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const float viewScale = ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const float viewScale =
ManipulatorViewScaleMultiplier(manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const AZ::Quaternion orientation = m_orientation;
CameraCorrectAxis(
m_offset, m_cameraCorrectedOffset, managerState, mouseInteraction,
manipulatorState.m_worldFromLocal, manipulatorState.m_localPosition,
cameraState);
m_offset, m_cameraCorrectedOffset, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState);
const Picking::BoundShapeBox boxBound =
CalculateBoxBound(manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, orientation,
m_cameraCorrectedOffset * viewScale,
m_halfExtents * viewScale);
const Picking::BoundShapeBox boxBound = CalculateBoxBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, orientation, m_cameraCorrectedOffset * viewScale,
m_halfExtents * viewScale);
const AZ::Vector3 xAxis = boxBound.m_orientation.TransformVector(AZ::Vector3::CreateAxisX());
const AZ::Vector3 yAxis = boxBound.m_orientation.TransformVector(AZ::Vector3::CreateAxisY());
const AZ::Vector3 zAxis = boxBound.m_orientation.TransformVector(AZ::Vector3::CreateAxisZ());
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
debugDisplay.DrawSolidOBB(boxBound.m_center,
xAxis, yAxis, zAxis, boxBound.m_halfExtents);
debugDisplay.DrawSolidOBB(boxBound.m_center, xAxis, yAxis, zAxis, boxBound.m_halfExtents);
RefreshBoundInternal(managerId, manipulatorId, boxBound);
}
void ManipulatorViewCylinder::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const float viewScale = ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const float viewScale =
ManipulatorViewScaleMultiplier(manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
CameraCorrectAxis(
m_axis, m_cameraCorrectedAxis, managerState, mouseInteraction,
manipulatorState.m_worldFromLocal, manipulatorState.m_localPosition, cameraState);
m_axis, m_cameraCorrectedAxis, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState);
const Picking::BoundShapeCylinder cylinderBound =
CalculateCylinderBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis,
m_length * viewScale,
m_radius * viewScale);
const Picking::BoundShapeCylinder cylinderBound = CalculateCylinderBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis, m_length * viewScale,
m_radius * viewScale);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
debugDisplay.DrawSolidCylinder(cylinderBound.m_base + cylinderBound.m_axis * cylinderBound.m_height * 0.5f,
cylinderBound.m_axis, cylinderBound.m_radius, cylinderBound.m_height, false);
debugDisplay.DrawSolidCylinder(
cylinderBound.m_base + cylinderBound.m_axis * cylinderBound.m_height * 0.5f, cylinderBound.m_axis, cylinderBound.m_radius,
cylinderBound.m_height, false);
RefreshBoundInternal(managerId, manipulatorId, cylinderBound);
}
void ManipulatorViewSphere::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const Picking::BoundShapeSphere sphereBound =
CalculateSphereBound(manipulatorState.m_localPosition, manipulatorState,
m_radius * ManipulatorViewScaleMultiplier(
manipulatorState.TransformPoint(manipulatorState.m_localPosition), cameraState));
const Picking::BoundShapeSphere sphereBound = CalculateSphereBound(
manipulatorState.m_localPosition, manipulatorState,
m_radius * ManipulatorViewScaleMultiplier(manipulatorState.TransformPoint(manipulatorState.m_localPosition), cameraState));
if (m_depthTest)
{
@@ -545,31 +568,32 @@ namespace AzToolsFramework
}
void ManipulatorViewCircle::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& /*mouseInteraction*/)
{
const float viewScale = ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const float viewScale =
ManipulatorViewScaleMultiplier(manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const Picking::BoundShapeTorus torusBound =
CalculateTorusBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_axis,
m_radius * viewScale,
m_width * viewScale);
const Picking::BoundShapeTorus torusBound = CalculateTorusBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_axis, m_radius * viewScale, m_width * viewScale);
// transform circle based on delta between default z up axis and other axes
const AZ::Transform worldFromLocalWithOrientation =
AZ::Transform::CreateTranslation(manipulatorState.m_worldFromLocal.GetTranslation()) *
AZ::Transform::CreateFromQuaternion(
(QuaternionFromTransformNoScaling(manipulatorState.m_worldFromLocal) *
AZ::Quaternion::CreateShortestArc(AZ::Vector3::CreateAxisZ(), m_axis)).GetNormalized());
AZ::Transform::CreateFromQuaternion((QuaternionFromTransformNoScaling(manipulatorState.m_worldFromLocal) *
AZ::Quaternion::CreateShortestArc(AZ::Vector3::CreateAxisZ(), m_axis))
.GetNormalized());
debugDisplay.CullOn();
debugDisplay.PushMatrix(worldFromLocalWithOrientation);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
m_drawCircleFunc(debugDisplay, manipulatorState.m_localPosition, torusBound.m_majorRadius,
m_drawCircleFunc(
debugDisplay, manipulatorState.m_localPosition, torusBound.m_majorRadius,
worldFromLocalWithOrientation.GetInverse().TransformPoint(cameraState.m_position));
debugDisplay.PopMatrix();
debugDisplay.CullOff();
@@ -578,27 +602,28 @@ namespace AzToolsFramework
}
void DrawHalfDottedCircle(
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position,
const float radius, const AZ::Vector3& viewPos)
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position, const float radius, const AZ::Vector3& viewPos)
{
debugDisplay.DrawHalfDottedCircle(position, radius, viewPos);
}
void DrawFullCircle(
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position,
const float radius, const AZ::Vector3& /*viewPos*/)
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position, const float radius, const AZ::Vector3& /*viewPos*/)
{
debugDisplay.DrawCircle(position, radius);
debugDisplay.DrawCircle(position, radius);
}
void ManipulatorViewSplineSelect::Draw(
const ManipulatorManagerId managerId, const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
const ManipulatorManagerId managerId,
const ManipulatorManagerState& /*managerState*/,
const ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
const float viewScale = ManipulatorViewScaleMultiplier(
manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const float viewScale =
ManipulatorViewScaleMultiplier(manipulatorState.m_worldFromLocal.TransformPoint(manipulatorState.m_localPosition), cameraState);
const Picking::BoundShapeSpline splineBound =
CalculateSplineBound(m_spline, manipulatorState.m_worldFromLocal, m_width * viewScale);
@@ -606,16 +631,15 @@ namespace AzToolsFramework
if (manipulatorState.m_mouseOver)
{
const SplineSelectionManipulator::Action action = CalculateManipulationDataAction(
manipulatorState.m_worldFromLocal, mouseInteraction.m_mousePick.m_rayOrigin,
mouseInteraction.m_mousePick.m_rayDirection, m_spline);
manipulatorState.m_worldFromLocal, mouseInteraction.m_mousePick.m_rayOrigin, mouseInteraction.m_mousePick.m_rayDirection,
m_spline);
const AZ::Vector3 worldSplineHitPosition =
manipulatorState.m_worldFromLocal.TransformPoint(action.m_localSplineHitPosition);
const AZ::Vector3 worldSplineHitPosition = manipulatorState.m_worldFromLocal.TransformPoint(action.m_localSplineHitPosition);
debugDisplay.SetColor(m_color.GetAsVector4());
debugDisplay.DrawBall(
worldSplineHitPosition, ManipulatorViewScaleMultiplier(worldSplineHitPosition, cameraState)
* g_defaultManipulatorSphereRadius, false);
worldSplineHitPosition,
ManipulatorViewScaleMultiplier(worldSplineHitPosition, cameraState) * g_defaultManipulatorSphereRadius, false);
}
RefreshBoundInternal(managerId, manipulatorId, splineBound);
@@ -624,8 +648,7 @@ namespace AzToolsFramework
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
AZStd::unique_ptr<ManipulatorViewQuad> CreateManipulatorViewQuad(
const PlanarManipulator& planarManipulator, const AZ::Color& axis1Color,
const AZ::Color& axis2Color, const float size)
const PlanarManipulator& planarManipulator, const AZ::Color& axis1Color, const AZ::Color& axis2Color, const float size)
{
AZStd::unique_ptr<ManipulatorViewQuad> viewQuad = AZStd::make_unique<ManipulatorViewQuad>();
viewQuad->m_axis1 = planarManipulator.GetAxis1();
@@ -636,8 +659,7 @@ namespace AzToolsFramework
return viewQuad;
}
AZStd::unique_ptr<ManipulatorViewQuadBillboard> CreateManipulatorViewQuadBillboard(
const AZ::Color& color, const float size)
AZStd::unique_ptr<ManipulatorViewQuadBillboard> CreateManipulatorViewQuadBillboard(const AZ::Color& color, const float size)
{
AZStd::unique_ptr<ManipulatorViewQuadBillboard> viewQuad = AZStd::make_unique<ManipulatorViewQuadBillboard>();
viewQuad->m_size = size;
@@ -646,8 +668,7 @@ namespace AzToolsFramework
}
AZStd::unique_ptr<ManipulatorViewLine> CreateManipulatorViewLine(
const LinearManipulator& linearManipulator, const AZ::Color& color,
const float length, const float width)
const LinearManipulator& linearManipulator, const AZ::Color& color, const float length, const float width)
{
AZStd::unique_ptr<ManipulatorViewLine> viewLine = AZStd::make_unique<ManipulatorViewLine>();
viewLine->m_axis = linearManipulator.GetAxis();
@@ -658,8 +679,7 @@ namespace AzToolsFramework
}
AZStd::unique_ptr<ManipulatorViewLineSelect> CreateManipulatorViewLineSelect(
const LineSegmentSelectionManipulator& lineSegmentManipulator,
const AZ::Color& color, const float width)
const LineSegmentSelectionManipulator& lineSegmentManipulator, const AZ::Color& color, const float width)
{
AZStd::unique_ptr<ManipulatorViewLineSelect> viewLineSelect = AZStd::make_unique<ManipulatorViewLineSelect>();
viewLineSelect->m_localStart = lineSegmentManipulator.GetStart();
@@ -670,8 +690,11 @@ namespace AzToolsFramework
}
AZStd::unique_ptr<ManipulatorViewCone> CreateManipulatorViewCone(
const LinearManipulator& linearManipulator, const AZ::Color& color,
const AZ::Vector3& offset, const float length, const float radius)
const LinearManipulator& linearManipulator,
const AZ::Color& color,
const AZ::Vector3& offset,
const float length,
const float radius)
{
AZStd::unique_ptr<ManipulatorViewCone> viewCone = AZStd::make_unique<ManipulatorViewCone>();
viewCone->m_axis = linearManipulator.GetAxis();
@@ -683,8 +706,7 @@ namespace AzToolsFramework
}
AZStd::unique_ptr<ManipulatorViewBox> CreateManipulatorViewBox(
const AZ::Transform& transform, const AZ::Color& color,
const AZ::Vector3& offset, const AZ::Vector3& halfExtents)
const AZ::Transform& transform, const AZ::Color& color, const AZ::Vector3& offset, const AZ::Vector3& halfExtents)
{
AZStd::unique_ptr<ManipulatorViewBox> viewBox = AZStd::make_unique<ManipulatorViewBox>();
viewBox->m_orientation = transform.GetRotation();
@@ -695,8 +717,7 @@ namespace AzToolsFramework
}
AZStd::unique_ptr<ManipulatorViewCylinder> CreateManipulatorViewCylinder(
const LinearManipulator& linearManipulator, const AZ::Color& color,
const float length, const float radius)
const LinearManipulator& linearManipulator, const AZ::Color& color, const float length, const float radius)
{
AZStd::unique_ptr<ManipulatorViewCylinder> viewCylinder = AZStd::make_unique<ManipulatorViewCylinder>();
viewCylinder->m_axis = linearManipulator.GetAxis();
@@ -718,8 +739,11 @@ namespace AzToolsFramework
}
AZStd::unique_ptr<ManipulatorViewCircle> CreateManipulatorViewCircle(
const AngularManipulator& angularManipulator, const AZ::Color& color,
const float radius, const float width, const ManipulatorViewCircle::DrawCircleFunc drawFunc)
const AngularManipulator& angularManipulator,
const AZ::Color& color,
const float radius,
const float width,
const ManipulatorViewCircle::DrawCircleFunc drawFunc)
{
AZStd::unique_ptr<ManipulatorViewCircle> viewCircle = AZStd::make_unique<ManipulatorViewCircle>();
viewCircle->m_axis = angularManipulator.GetAxis();
@@ -731,8 +755,7 @@ namespace AzToolsFramework
}
AZStd::unique_ptr<ManipulatorViewSplineSelect> CreateManipulatorViewSplineSelect(
const SplineSelectionManipulator& splineManipulator,
const AZ::Color& color, const float width)
const SplineSelectionManipulator& splineManipulator, const AZ::Color& color, const float width)
{
AZStd::unique_ptr<ManipulatorViewSplineSelect> viewSplineSelect = AZStd::make_unique<ManipulatorViewSplineSelect>();
viewSplineSelect->m_spline = splineManipulator.GetSpline();
@@ -741,16 +764,12 @@ namespace AzToolsFramework
return viewSplineSelect;
}
AZ::Vector3 CalculateViewDirection(
const Manipulators& manipulators, const AZ::Vector3& worldViewPosition)
AZ::Vector3 CalculateViewDirection(const Manipulators& manipulators, const AZ::Vector3& worldViewPosition)
{
const AZ::Transform worldFromLocalWithTransform =
manipulators.GetSpace() * manipulators.GetLocalTransform();
const AZ::Transform worldFromLocalWithTransform = manipulators.GetSpace() * manipulators.GetLocalTransform();
AZ::Vector3 lookDirection =
(worldFromLocalWithTransform.GetTranslation() - worldViewPosition).GetNormalized();
AZ::Vector3 lookDirection = (worldFromLocalWithTransform.GetTranslation() - worldViewPosition).GetNormalized();
return TransformDirectionNoScaling(
worldFromLocalWithTransform.GetInverse(), lookDirection);
return TransformDirectionNoScaling(worldFromLocalWithTransform.GetInverse(), lookDirection);
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -26,13 +26,12 @@ namespace AzToolsFramework
class LineSegmentSelectionManipulator;
class SplineSelectionManipulator;
using DecideColorFn = AZStd::function<AZ::Color(
const ViewportInteraction::MouseInteraction&,
bool mouseOver, const AZ::Color& defaultColor)>;
using DecideColorFn =
AZStd::function<AZ::Color(const ViewportInteraction::MouseInteraction&, bool mouseOver, const AZ::Color& defaultColor)>;
extern const float g_defaultManipulatorSphereRadius;
/// State of an individual manipulator.
//! State of an individual manipulator.
struct ManipulatorState
{
AZ::Transform m_worldFromLocal;
@@ -40,18 +39,18 @@ namespace AzToolsFramework
AZ::Vector3 m_localPosition;
bool m_mouseOver;
/// Transforms a point, taking non-uniform scale into account.
//! Transforms a point, taking non-uniform scale into account.
AZ::Vector3 TransformPoint(const AZ::Vector3& point) const;
/// Rotates a direction into the space of the manipulator and normalizes it.
/// Non-uniform scaling and translation are not applied.
//! Rotates a direction into the space of the manipulator and normalizes it.
//! Non-uniform scaling and translation are not applied.
AZ::Vector3 TransformDirectionNoScaling(const AZ::Vector3& direction) const;
};
/// The base interface for the visual representation of manipulators.
/// The View represents the appearance and bounds of the manipulator for
/// the user to interact with. Any manipulator can have any view (some may
/// be more appropriate than others in certain cases).
//! The base interface for the visual representation of manipulators.
//! The View represents the appearance and bounds of the manipulator for
//! the user to interact with. Any manipulator can have any view (some may
//! be more appropriate than others in certain cases).
class ManipulatorView
{
public:
@@ -65,98 +64,107 @@ namespace AzToolsFramework
ManipulatorView& operator=(ManipulatorView&&) = default;
void SetBoundDirty(ManipulatorManagerId managerId);
void RefreshBound(
ManipulatorManagerId managerId, ManipulatorId manipulatorId, const Picking::BoundRequestShapeBase& bound);
void RefreshBound(ManipulatorManagerId managerId, ManipulatorId manipulatorId, const Picking::BoundRequestShapeBase& bound);
void Invalidate(ManipulatorManagerId managerId);
virtual void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) = 0;
bool ScreenSizeFixed() const { return m_screenSizeFixed; }
bool ScreenSizeFixed() const
{
return m_screenSizeFixed;
}
protected:
AZ::Color m_mouseOverColor = BaseManipulator::s_defaultMouseOverColor; ///< What color should the manipulator
///< be when the mouse is hovering over it.
/// Scale the manipulator based on the distance
/// from the camera if m_screenSizeFixed is true.
float ManipulatorViewScaleMultiplier(
const AZ::Vector3& worldPosition, const AzFramework::CameraState& cameraState) const;
AZ::Color m_mouseOverColor = BaseManipulator::s_defaultMouseOverColor; //!< What color should the manipulator
//!< be when the mouse is hovering over it.
//! Scale the manipulator based on the distance
//! from the camera if m_screenSizeFixed is true.
float ManipulatorViewScaleMultiplier(const AZ::Vector3& worldPosition, const AzFramework::CameraState& cameraState) const;
/// Wrap the logic for updating a bound.
/// Should be called at the end of the Draw function once a concrete BoundRequestShape has
/// been created to use for dimensions for rendering.
void RefreshBoundInternal(
ManipulatorManagerId managerId, ManipulatorId manipulatorId, const Picking::BoundRequestShapeBase& bound);
//! Wrap the logic for updating a bound.
//! Should be called at the end of the Draw function once a concrete BoundRequestShape has
//! been created to use for dimensions for rendering.
void RefreshBoundInternal(ManipulatorManagerId managerId, ManipulatorId manipulatorId, const Picking::BoundRequestShapeBase& bound);
private:
Picking::RegisteredBoundId m_boundId = Picking::InvalidBoundId; ///< Used for hit detection.
ManipulatorManagerId m_managerId = InvalidManipulatorManagerId; /// The manipulator manager this view has been registered with.
bool m_screenSizeFixed = true; ///< Should manipulator size be adjusted based on camera distance.
bool m_boundDirty = true; ///< Do the bounds need to be recalculated.
Picking::RegisteredBoundId m_boundId = Picking::InvalidBoundId; //!< Used for hit detection.
ManipulatorManagerId m_managerId = InvalidManipulatorManagerId; //! The manipulator manager this view has been registered with.
bool m_screenSizeFixed = true; //!< Should manipulator size be adjusted based on camera distance.
bool m_boundDirty = true; //!< Do the bounds need to be recalculated.
};
// A collection of views (a manipulator may have 1 - * views)
using ManipulatorViews = AZStd::vector<AZStd::shared_ptr<ManipulatorView>>;
/// Display a quad representing part of a plane, rendered as 4 lines.
class ManipulatorViewQuad
: public ManipulatorView
//! Display a quad representing part of a plane, rendered as 4 lines.
class ManipulatorViewQuad : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewQuad, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewQuad, "{D85E1B45-495E-4755-BCF2-6AE45F8BB2B0}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZ::Vector3 m_axis1 = AZ::Vector3(1.0f, 0.0f, 0.0f);
AZ::Vector3 m_axis2 = AZ::Vector3(0.0f, 1.0f, 0.0f);
AZ::Color m_axis1Color = AZ::Color(1.0f, 0.0f, 0.0f, 1.0f);
AZ::Color m_axis2Color = AZ::Color(1.0f, 0.0f, 0.0f, 1.0f);
float m_size = 0.06f; ///< size to render and do mouse ray intersection tests against.
float m_size = 0.06f; //!< size to render and do mouse ray intersection tests against.
private:
AZ::Vector3 m_cameraCorrectedAxis1;
AZ::Vector3 m_cameraCorrectedAxis2;
};
/// A screen aligned quad, centered at the position of the manipulator, display filled.
class ManipulatorViewQuadBillboard
: public ManipulatorView
//! A screen aligned quad, centered at the position of the manipulator, display filled.
class ManipulatorViewQuadBillboard : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewQuadBillboard, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewQuadBillboard, "{C205E967-E8C6-4A73-A31B-41EE5529B15B}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZ::Color m_color = AZ::Color(1.0f, 0.0f, 0.0f, 1.0f);
float m_size = 0.005f; ///< size to render and do mouse ray intersection tests against.
float m_size = 0.005f; //!< size to render and do mouse ray intersection tests against.
};
/// Displays a debug style line starting from the manipulator's transform,
/// width determines the click area.
class ManipulatorViewLine
: public ManipulatorView
//! Displays a debug style line starting from the manipulator's transform,
//! width determines the click area.
class ManipulatorViewLine : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewLine, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewLine, "{831EEF66-4A5C-450C-B152-EA4A0BC8A272}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZ::Vector3 m_axis;
@@ -168,19 +176,21 @@ namespace AzToolsFramework
AZ::Vector3 m_cameraCorrectedAxis;
};
/// Variant of ManipulatorViewLine which instead of using an axis, provides begin and end
/// points for the line. Used for selection when inserting points along a line.
class ManipulatorViewLineSelect
: public ManipulatorView
//! Variant of ManipulatorViewLine which instead of using an axis, provides begin and end
//! points for the line. Used for selection when inserting points along a line.
class ManipulatorViewLineSelect : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewLineSelect, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewLineSelect, "{BF26A947-91F8-4595-9A5B-481876EB2C48}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZ::Vector3 m_localStart;
@@ -189,20 +199,22 @@ namespace AzToolsFramework
float m_width = 0.0f;
};
/// Displays a filled cone along the specified axis, offset is local translation from
/// the manipulator transform (often used in conjunction with other views to build
/// aggregate views such as arrows - e.g. a line and cone).
class ManipulatorViewCone
: public ManipulatorView
//! Displays a filled cone along the specified axis, offset is local translation from
//! the manipulator transform (often used in conjunction with other views to build
//! aggregate views such as arrows - e.g. a line and cone).
class ManipulatorViewCone : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewCone, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewCone, "{BF042887-1F51-4FD8-8CA5-4A649B4AF356}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZ::Vector3 m_offset;
@@ -217,20 +229,22 @@ namespace AzToolsFramework
bool m_shouldCorrect = false;
};
/// Displays a filled box, offset is local translation from the manipulator
/// transform, box is often used in conjunction with other views, orientation allows
/// the box to be orientated separately from the manipulator transform.
class ManipulatorViewBox
: public ManipulatorView
//! Displays a filled box, offset is local translation from the manipulator
//! transform, box is often used in conjunction with other views, orientation allows
//! the box to be orientated separately from the manipulator transform.
class ManipulatorViewBox : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewBox, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewBox, "{2D082201-7878-4C1B-A3DD-7A629E5AD598}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZ::Vector3 m_offset;
@@ -242,18 +256,20 @@ namespace AzToolsFramework
AZ::Vector3 m_cameraCorrectedOffset;
};
/// Displays a filled cylinder along the axis provided.
class ManipulatorViewCylinder
: public ManipulatorView
//! Displays a filled cylinder along the axis provided.
class ManipulatorViewCylinder : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewCylinder, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewCylinder, "{9B8E5EF4-0F85-4CD0-A5FF-3C7097DF58AC}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZ::Vector3 m_axis;
@@ -265,20 +281,22 @@ namespace AzToolsFramework
AZ::Vector3 m_cameraCorrectedAxis;
};
/// Displays a filled sphere at the transform of the manipulator, often used as
/// a selection manipulator. DecideColorFn allows more complex logic to be used
/// to decide the color of the manipulator (based on hover state etc.)
class ManipulatorViewSphere
: public ManipulatorView
//! Displays a filled sphere at the transform of the manipulator, often used as
//! a selection manipulator. DecideColorFn allows more complex logic to be used
//! to decide the color of the manipulator (based on hover state etc.)
class ManipulatorViewSphere : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewSphere, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewSphere, "{324D8329-6E7B-4A5D-AC8A-8C0E1C984E38}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
float m_radius = 0.0f;
@@ -287,23 +305,24 @@ namespace AzToolsFramework
bool m_depthTest = false;
};
/// Displays a wire circle. DrawCircleFunc can be used to either draw a full
/// circle or a half dotted circle where the part of the circle facing away
/// from the camera is dotted (useful for angular/rotation manipulators).
class ManipulatorViewCircle
: public ManipulatorView
//! Displays a wire circle. DrawCircleFunc can be used to either draw a full
//! circle or a half dotted circle where the part of the circle facing away
//! from the camera is dotted (useful for angular/rotation manipulators).
class ManipulatorViewCircle : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewCircle, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewCircle, "{26563A03-3E48-49EB-9DCF-30EE4F567FCD}", ManipulatorView)
using DrawCircleFunc =
void(*)(AzFramework::DebugDisplayRequests&, const AZ::Vector3&, float, const AZ::Vector3&);
using DrawCircleFunc = void (*)(AzFramework::DebugDisplayRequests&, const AZ::Vector3&, float, const AZ::Vector3&);
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZ::Vector3 m_axis;
@@ -316,26 +335,26 @@ namespace AzToolsFramework
// helpers to provide consistent function pointer interface for deciding
// on type of circle to draw (see DrawCircleFunc in ManipulatorViewCircle above)
void DrawHalfDottedCircle(
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position,
float radius, const AZ::Vector3& viewPos);
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position, float radius, const AZ::Vector3& viewPos);
void DrawFullCircle(
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position,
float radius, const AZ::Vector3& viewPos);
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position, float radius, const AZ::Vector3& viewPos);
/// Used for interaction with spline primitive - it will generate a spline bound
/// to be interacted with and will display the intersection point on the spline
/// where a user may wish to insert a point.
class ManipulatorViewSplineSelect
: public ManipulatorView
//! Used for interaction with spline primitive - it will generate a spline bound
//! to be interacted with and will display the intersection point on the spline
//! where a user may wish to insert a point.
class ManipulatorViewSplineSelect : public ManipulatorView
{
public:
AZ_CLASS_ALLOCATOR(ManipulatorViewSplineSelect, AZ::SystemAllocator, 0)
AZ_RTTI(ManipulatorViewSplineSelect, "{60996E49-D6BF-4817-BAA3-D27A407DD21A}", ManipulatorView)
void Draw(
ManipulatorManagerId managerId, const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId, const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay, const AzFramework::CameraState& cameraState,
ManipulatorManagerId managerId,
const ManipulatorManagerState& managerState,
ManipulatorId manipulatorId,
const ManipulatorState& manipulatorState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
AZStd::weak_ptr<const AZ::Spline> m_spline;
@@ -343,65 +362,61 @@ namespace AzToolsFramework
AZ::Color m_color = AZ::Color(0.0f, 1.0f, 0.0f, 1.0f);
};
/// Returns true if axis is pointing away from us (we should flip it).
//! Returns true if axis is pointing away from us (we should flip it).
inline bool ShouldFlipCameraAxis(
const AZ::Transform& worldFromLocal, const AZ::Vector3& localPosition,
const AZ::Vector3& axis, const AzFramework::CameraState& cameraState)
const AZ::Transform& worldFromLocal,
const AZ::Vector3& localPosition,
const AZ::Vector3& axis,
const AzFramework::CameraState& cameraState)
{
return (worldFromLocal.TransformPoint(localPosition) - cameraState.m_position).Dot(
TransformDirectionNoScaling(worldFromLocal, axis)) > 0.0f;
return (worldFromLocal.TransformPoint(localPosition) - cameraState.m_position)
.Dot(TransformDirectionNoScaling(worldFromLocal, axis)) > 0.0f;
}
/// @brief Return the world transform of the entity with uniform scale - choose
/// the largest element.
//! @brief Return the world transform of the entity with uniform scale - choose
//! the largest element.
AZ::Transform WorldFromLocalWithUniformScale(AZ::EntityId entityId);
/// Get the non-uniform scale for this entity id.
//! Get the non-uniform scale for this entity id.
AZ::Vector3 GetNonUniformScale(AZ::EntityId entityId);
// Helpers to create various manipulator views.
AZStd::unique_ptr<ManipulatorViewQuad> CreateManipulatorViewQuad(
const PlanarManipulator& planarManipulator, const AZ::Color& axis1Color,
const AZ::Color& axis2Color, float size);
const PlanarManipulator& planarManipulator, const AZ::Color& axis1Color, const AZ::Color& axis2Color, float size);
AZStd::unique_ptr<ManipulatorViewQuadBillboard> CreateManipulatorViewQuadBillboard(
const AZ::Color& color, float size);
AZStd::unique_ptr<ManipulatorViewQuadBillboard> CreateManipulatorViewQuadBillboard(const AZ::Color& color, float size);
AZStd::unique_ptr<ManipulatorViewLine> CreateManipulatorViewLine(
const LinearManipulator& linearManipulator, const AZ::Color& color,
float length, float width);
const LinearManipulator& linearManipulator, const AZ::Color& color, float length, float width);
AZStd::unique_ptr<ManipulatorViewLineSelect> CreateManipulatorViewLineSelect(
const LineSegmentSelectionManipulator& lineSegmentManipulator, const AZ::Color& color,
float width);
const LineSegmentSelectionManipulator& lineSegmentManipulator, const AZ::Color& color, float width);
AZStd::unique_ptr<ManipulatorViewCone> CreateManipulatorViewCone(
const LinearManipulator& linearManipulator, const AZ::Color& color,
const AZ::Vector3& offset, float length, float radius);
const LinearManipulator& linearManipulator, const AZ::Color& color, const AZ::Vector3& offset, float length, float radius);
AZStd::unique_ptr<ManipulatorViewBox> CreateManipulatorViewBox(
const AZ::Transform& transform, const AZ::Color& color,
const AZ::Vector3& offset, const AZ::Vector3& halfExtents);
const AZ::Transform& transform, const AZ::Color& color, const AZ::Vector3& offset, const AZ::Vector3& halfExtents);
AZStd::unique_ptr<ManipulatorViewCylinder> CreateManipulatorViewCylinder(
const LinearManipulator& linearManipulator, const AZ::Color& color,
float length, float radius);
const LinearManipulator& linearManipulator, const AZ::Color& color, float length, float radius);
AZStd::unique_ptr<ManipulatorViewSphere> CreateManipulatorViewSphere(
const AZ::Color& color, float radius, const DecideColorFn& decideColor, bool enableDepthTest = false);
AZStd::unique_ptr<ManipulatorViewCircle> CreateManipulatorViewCircle(
const AngularManipulator& angularManipulator, const AZ::Color& color,
float radius, float width, ManipulatorViewCircle::DrawCircleFunc drawFunc);
const AngularManipulator& angularManipulator,
const AZ::Color& color,
float radius,
float width,
ManipulatorViewCircle::DrawCircleFunc drawFunc);
AZStd::unique_ptr<ManipulatorViewSplineSelect> CreateManipulatorViewSplineSelect(
const SplineSelectionManipulator& splineManipulator, const AZ::Color& color,
float width);
const SplineSelectionManipulator& splineManipulator, const AZ::Color& color, float width);
/// Returns the vector between the view (camera) and the manipulator in the space
/// of the Manipulator (manipulator space + local transform).
AZ::Vector3 CalculateViewDirection(
const Manipulators& manipulators, const AZ::Vector3& worldViewPosition);
//! Returns the vector between the view (camera) and the manipulator in the space
//! of the Manipulator (manipulator space + local transform).
AZ::Vector3 CalculateViewDirection(const Manipulators& manipulators, const AZ::Vector3& worldViewPosition);
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "MultiLinearManipulator.h"
@@ -56,10 +56,13 @@ namespace AzToolsFramework
}
static MultiLinearManipulator::Action BuildMultiLinearManipulatorAction(
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const ViewportInteraction::MouseInteraction& interaction,
const AZStd::vector<LinearManipulator::Fixed>& fixedAxes,
const AZStd::vector<LinearManipulator::Starter>& starterStates, const GridSnapParameters& gridSnapParams)
const AZStd::vector<LinearManipulator::Starter>& starterStates,
const GridSnapParameters& gridSnapParams)
{
MultiLinearManipulator::Action action;
action.m_viewportId = interaction.m_interactionId.m_viewportId;
@@ -96,8 +99,8 @@ namespace AzToolsFramework
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
// pass action containing all linear actions for each axis to handler
m_onLeftMouseDownCallback(BuildMultiLinearManipulatorAction(
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
interaction, m_fixedAxes, m_starters, gridSnapParams));
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(), interaction, m_fixedAxes, m_starters,
gridSnapParams));
}
}
@@ -108,8 +111,8 @@ namespace AzToolsFramework
const AZ::Transform worldFromLocalUniformScale = TransformUniformScale(GetSpace());
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
m_onMouseMoveCallback(BuildMultiLinearManipulatorAction(
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
interaction, m_fixedAxes, m_starters, gridSnapParams));
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(), interaction, m_fixedAxes, m_starters,
gridSnapParams));
}
}
@@ -120,8 +123,8 @@ namespace AzToolsFramework
const AZ::Transform worldFromLocalUniformScale = TransformUniformScale(GetSpace());
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
m_onLeftMouseUpCallback(BuildMultiLinearManipulatorAction(
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
interaction, m_fixedAxes, m_starters, gridSnapParams));
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(), interaction, m_fixedAxes, m_starters,
gridSnapParams));
m_starters.clear();
}
@@ -138,36 +141,31 @@ namespace AzToolsFramework
const AZ::Transform combined = TransformUniformScale(GetSpace()) * GetLocalTransform();
for (const auto& fixed : m_fixedAxes)
{
DrawAxis(
debugDisplay, combined.GetTranslation(), TransformDirectionNoScaling(combined, fixed.m_axis));
DrawAxis(debugDisplay, combined.GetTranslation(), TransformDirectionNoScaling(combined, fixed.m_axis));
}
}
for (auto& view : m_manipulatorViews)
{
view->Draw(
GetManipulatorManagerId(), managerState,
GetManipulatorId(), {
ApplySpace(GetLocalTransform()), GetNonUniformScale(),
AZ::Vector3::CreateZero(), MouseOver()
},
debugDisplay, cameraState, mouseInteraction);
GetManipulatorManagerId(), managerState, GetManipulatorId(),
{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay,
cameraState, mouseInteraction);
}
}
void MultiLinearManipulator::AddAxis(const AZ::Vector3& axis)
{
m_fixedAxes.push_back(LinearManipulator::Fixed{axis});
m_fixedAxes.push_back(LinearManipulator::Fixed{ axis });
}
void MultiLinearManipulator::AddAxes(const AZStd::vector<AZ::Vector3>& axes)
{
AZStd::transform(
axes.begin(), axes.end(),
AZStd::back_inserter(m_fixedAxes),
axes.begin(), axes.end(), AZStd::back_inserter(m_fixedAxes),
[](const AZ::Vector3& axis)
{
return LinearManipulator::Fixed{axis};
return LinearManipulator::Fixed{ axis };
});
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -80,12 +80,9 @@ namespace AzToolsFramework
}
private:
void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void InvalidateImpl() override;
void SetBoundsDirtyImpl() override;
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "PlanarManipulator.h"
@@ -22,12 +22,15 @@
namespace AzToolsFramework
{
PlanarManipulator::StartInternal PlanarManipulator::CalculateManipulationDataStart(
const Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
const ViewportInteraction::MouseInteraction& interaction, const float intersectionDistance)
const Fixed& fixed,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const ViewportInteraction::MouseInteraction& interaction,
const float intersectionDistance)
{
const ManipulatorInteraction manipulatorInteraction =
BuildManipulatorInteraction(
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
const ManipulatorInteraction manipulatorInteraction = BuildManipulatorInteraction(
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
const AZ::Vector3 normal = TransformDirectionNoScaling(localTransform, fixed.m_normal);
@@ -37,8 +40,8 @@ namespace AzToolsFramework
StartInternal startInternal;
Internal::CalculateRayPlaneIntersectingPoint(
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection,
localIntersectionPoint, normal, startInternal.m_localHitPosition);
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection, localIntersectionPoint, normal,
startInternal.m_localHitPosition);
startInternal.m_localPosition = localTransform.GetTranslation();
@@ -46,13 +49,16 @@ namespace AzToolsFramework
}
PlanarManipulator::Action PlanarManipulator::CalculateManipulationDataAction(
const Fixed& fixed, const StartInternal& startInternal, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform, const GridSnapParameters& gridSnapParams,
const Fixed& fixed,
const StartInternal& startInternal,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const GridSnapParameters& gridSnapParams,
const ViewportInteraction::MouseInteraction& interaction)
{
const ManipulatorInteraction manipulatorInteraction =
BuildManipulatorInteraction(
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
const ManipulatorInteraction manipulatorInteraction = BuildManipulatorInteraction(
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
const AZ::Vector3 normal = TransformDirectionNoScaling(localTransform, fixed.m_normal);
@@ -61,8 +67,8 @@ namespace AzToolsFramework
// if an invalid ray intersection is attempted
AZ::Vector3 localHitPosition = startInternal.m_localHitPosition;
Internal::CalculateRayPlaneIntersectingPoint(
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection,
startInternal.m_localHitPosition, normal, localHitPosition);
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection, startInternal.m_localHitPosition, normal,
localHitPosition);
localHitPosition = Internal::TryConstrainHitPositionToView(
localHitPosition, startInternal.m_localHitPosition, worldFromLocal.GetInverse(),
@@ -126,8 +132,8 @@ namespace AzToolsFramework
const AZ::Transform worldFromLocalUniformScale = TransformUniformScale(GetSpace());
m_startInternal = CalculateManipulationDataStart(
m_fixed, worldFromLocalUniformScale, GetNonUniformScale(), TransformNormalizedScale(GetLocalTransform()),
interaction, rayIntersectionDistance);
m_fixed, worldFromLocalUniformScale, GetNonUniformScale(), TransformNormalizedScale(GetLocalTransform()), interaction,
rayIntersectionDistance);
if (m_onLeftMouseDownCallback)
{
@@ -180,9 +186,10 @@ namespace AzToolsFramework
// display the exact hit (ray intersection) of the mouse pick on the manipulator
DrawTransformAxes(
debugDisplay, TransformUniformScale(GetSpace()) *
AZ::Transform::CreateTranslation(
action.m_start.m_localHitPosition + GetNonUniformScale() * action.m_current.m_localOffset));
debugDisplay,
TransformUniformScale(GetSpace()) *
AZ::Transform::CreateTranslation(
action.m_start.m_localHitPosition + GetNonUniformScale() * action.m_current.m_localOffset));
}
AZ::Transform combined = GetLocalTransform();
@@ -191,23 +198,16 @@ namespace AzToolsFramework
DrawTransformAxes(debugDisplay, combined);
DrawAxis(
debugDisplay, combined.GetTranslation(),
TransformDirectionNoScaling(GetLocalTransform(), m_fixed.m_axis1));
DrawAxis(
debugDisplay, combined.GetTranslation(),
TransformDirectionNoScaling(GetLocalTransform(), m_fixed.m_axis2));
DrawAxis(debugDisplay, combined.GetTranslation(), TransformDirectionNoScaling(GetLocalTransform(), m_fixed.m_axis1));
DrawAxis(debugDisplay, combined.GetTranslation(), TransformDirectionNoScaling(GetLocalTransform(), m_fixed.m_axis2));
}
for (auto& view : m_manipulatorViews)
{
view->Draw(
GetManipulatorManagerId(), managerState,
GetManipulatorId(), {
ApplySpace(GetLocalTransform()), GetNonUniformScale(),
AZ::Vector3::CreateZero(), MouseOver()
},
debugDisplay, cameraState, mouseInteraction);
GetManipulatorManagerId(), managerState, GetManipulatorId(),
{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay,
cameraState, mouseInteraction);
}
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -23,13 +23,13 @@ namespace AzToolsFramework
class ManipulatorView;
struct GridSnapParameters;
/// PlanarManipulator serves as a visual tool for users to modify values
/// in two dimension in a plane defined two non-collinear axes in 3D space.
//! PlanarManipulator serves as a visual tool for users to modify values
//! in two dimension in a plane defined two non-collinear axes in 3D space.
class PlanarManipulator
: public BaseManipulator
, public ManipulatorSpaceWithLocalTransform
{
/// Private constructor.
//! Private constructor.
explicit PlanarManipulator(const AZ::Transform& worldFromLocal);
public:
@@ -42,43 +42,51 @@ namespace AzToolsFramework
~PlanarManipulator() = default;
/// A Manipulator must only be created and managed through a shared_ptr.
//! A Manipulator must only be created and managed through a shared_ptr.
static AZStd::shared_ptr<PlanarManipulator> MakeShared(const AZ::Transform& worldFromLocal);
/// Unchanging data set once for the planar manipulator.
//! Unchanging data set once for the planar manipulator.
struct Fixed
{
AZ::Vector3 m_axis1 = AZ::Vector3::CreateAxisX(); ///< m_axis1 and m_axis2 have to be orthogonal, they together define a plane in 3d space.
AZ::Vector3 m_axis1 =
AZ::Vector3::CreateAxisX(); //!< m_axis1 and m_axis2 have to be orthogonal, they together define a plane in 3d space.
AZ::Vector3 m_axis2 = AZ::Vector3::CreateAxisY();
AZ::Vector3 m_normal = AZ::Vector3::CreateAxisZ(); ///< m_normal is calculated automatically when setting the axes.
AZ::Vector3 m_normal = AZ::Vector3::CreateAxisZ(); //!< m_normal is calculated automatically when setting the axes.
};
/// The state of the manipulator at the start of an interaction.
//! The state of the manipulator at the start of an interaction.
struct Start
{
AZ::Vector3 m_localPosition; ///< The current position of the manipulator in local space.
AZ::Vector3 m_localHitPosition; ///< The intersection point in local space between the ray and the manipulator when the mouse down event happens.
AZ::Vector3 m_localPosition; //!< The current position of the manipulator in local space.
AZ::Vector3 m_localHitPosition; //!< The intersection point in local space between the ray and the manipulator when the mouse
//!< down event happens.
};
/// The state of the manipulator during an interaction.
//! The state of the manipulator during an interaction.
struct Current
{
AZ::Vector3 m_localOffset; ///< The current position of the manipulator in local space.
AZ::Vector3 m_localOffset; //!< The current position of the manipulator in local space.
};
/// Mouse action data used by MouseActionCallback (wraps Start and Current manipulator state).
//! Mouse action data used by MouseActionCallback (wraps Start and Current manipulator state).
struct Action
{
Fixed m_fixed;
Start m_start;
Current m_current;
ViewportInteraction::KeyboardModifiers m_modifiers;
AZ::Vector3 LocalPosition() const { return m_start.m_localPosition + m_current.m_localOffset; }
AZ::Vector3 LocalPositionOffset() const { return m_current.m_localOffset; }
AZ::Vector3 LocalPosition() const
{
return m_start.m_localPosition + m_current.m_localOffset;
}
AZ::Vector3 LocalPositionOffset() const
{
return m_current.m_localOffset;
}
};
/// This is the function signature of callbacks that will be invoked whenever a manipulator
/// is being clicked on or dragged.
//! This is the function signature of callbacks that will be invoked whenever a manipulator
//! is being clicked on or dragged.
using MouseActionCallback = AZStd::function<void(const Action&)>;
void InstallLeftMouseDownCallback(const MouseActionCallback& onMouseDownCallback);
@@ -91,11 +99,17 @@ namespace AzToolsFramework
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
/// Ensure @param axis1 and @param axis2 are not collinear.
//! Ensure @param axis1 and @param axis2 are not collinear.
void SetAxes(const AZ::Vector3& axis1, const AZ::Vector3& axis2);
const AZ::Vector3& GetAxis1() const { return m_fixed.m_axis1; }
const AZ::Vector3& GetAxis2() const { return m_fixed.m_axis2; }
const AZ::Vector3& GetAxis1() const
{
return m_fixed.m_axis1;
}
const AZ::Vector3& GetAxis2() const
{
return m_fixed.m_axis2;
}
template<typename Views>
void SetViews(Views&& views)
@@ -104,21 +118,19 @@ namespace AzToolsFramework
}
private:
void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void InvalidateImpl() override;
void SetBoundsDirtyImpl() override;
/// Initial data recorded when a press first happens with a planar manipulator.
//! Initial data recorded when a press first happens with a planar manipulator.
struct StartInternal
{
AZ::Vector3 m_localPosition; ///< The starting position of the manipulator in local space.
AZ::Vector3 m_localHitPosition; ///< The intersection point in world space between the ray and the manipulator when the mouse down event happens.
AZ::Vector3 m_localPosition; //!< The starting position of the manipulator in local space.
AZ::Vector3 m_localHitPosition; //!< The intersection point in world space between the ray and the manipulator when the mouse
//!< down event happens.
};
Fixed m_fixed;
@@ -128,15 +140,23 @@ namespace AzToolsFramework
MouseActionCallback m_onLeftMouseUpCallback = nullptr;
MouseActionCallback m_onMouseMoveCallback = nullptr;
ManipulatorViews m_manipulatorViews; ///< Look of manipulator.
ManipulatorViews m_manipulatorViews; //!< Look of manipulator.
static StartInternal CalculateManipulationDataStart(
const Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform, const ViewportInteraction::MouseInteraction& interaction, float intersectionDistance);
const Fixed& fixed,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const ViewportInteraction::MouseInteraction& interaction,
float intersectionDistance);
static Action CalculateManipulationDataAction(
const Fixed& fixed, const StartInternal& startInternal, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform, const GridSnapParameters& gridSnapParams,
const Fixed& fixed,
const StartInternal& startInternal,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale,
const AZ::Transform& localTransform,
const GridSnapParameters& gridSnapParams,
const ViewportInteraction::MouseInteraction& interaction);
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "RotationManipulators.h"
@@ -28,8 +28,7 @@ namespace AzToolsFramework
m_manipulatorSpaceWithLocalTransform.SetSpace(worldFromLocal);
}
void RotationManipulators::InstallLeftMouseDownCallback(
const AngularManipulator::MouseActionCallback& onMouseDownCallback)
void RotationManipulators::InstallLeftMouseDownCallback(const AngularManipulator::MouseActionCallback& onMouseDownCallback)
{
for (AZStd::shared_ptr<AngularManipulator>& manipulator : m_localAngularManipulators)
{
@@ -39,8 +38,7 @@ namespace AzToolsFramework
m_viewAngularManipulator->InstallLeftMouseDownCallback(onMouseDownCallback);
}
void RotationManipulators::InstallMouseMoveCallback(
const AngularManipulator::MouseActionCallback& onMouseMoveCallback)
void RotationManipulators::InstallMouseMoveCallback(const AngularManipulator::MouseActionCallback& onMouseMoveCallback)
{
for (AZStd::shared_ptr<AngularManipulator>& manipulator : m_localAngularManipulators)
{
@@ -50,8 +48,7 @@ namespace AzToolsFramework
m_viewAngularManipulator->InstallMouseMoveCallback(onMouseMoveCallback);
}
void RotationManipulators::InstallLeftMouseUpCallback(
const AngularManipulator::MouseActionCallback& onMouseUpCallback)
void RotationManipulators::InstallLeftMouseUpCallback(const AngularManipulator::MouseActionCallback& onMouseUpCallback)
{
for (AZStd::shared_ptr<AngularManipulator>& manipulator : m_localAngularManipulators)
{
@@ -109,14 +106,13 @@ namespace AzToolsFramework
m_viewAngularManipulator->SetSpace(worldFromLocal);
}
void RotationManipulators::SetLocalAxes(
const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3)
void RotationManipulators::SetLocalAxes(const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3)
{
const AZ::Vector3 axes[] = { axis1, axis2, axis3 };
for (size_t manipulatorIndex = 0; manipulatorIndex < m_localAngularManipulators.size(); ++manipulatorIndex)
{
m_localAngularManipulators[manipulatorIndex]->SetAxis(axes[manipulatorIndex]);
m_localAngularManipulators[manipulatorIndex]->SetAxis(axes[manipulatorIndex]);
}
}
@@ -124,34 +120,25 @@ namespace AzToolsFramework
{
m_viewAngularManipulator->SetAxis(axis);
if (auto circleView = azrtti_cast<ManipulatorViewCircle*>(
m_viewAngularManipulator->GetView()))
if (auto circleView = azrtti_cast<ManipulatorViewCircle*>(m_viewAngularManipulator->GetView()))
{
circleView->m_axis = axis;
}
}
void RotationManipulators::ConfigureView(
const float radius, const AZ::Color& axis1Color,
const AZ::Color& axis2Color, const AZ::Color& axis3Color)
const float radius, const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color)
{
const AZ::Color colors[] = {
axis1Color, axis2Color, axis3Color
};
const AZ::Color colors[] = { axis1Color, axis2Color, axis3Color };
for (size_t manipulatorIndex = 0; manipulatorIndex < m_localAngularManipulators.size(); ++manipulatorIndex)
{
m_localAngularManipulators[manipulatorIndex]->SetView(
CreateManipulatorViewCircle(
*m_localAngularManipulators[manipulatorIndex], colors[manipulatorIndex],
radius, 0.05f, DrawHalfDottedCircle));
m_localAngularManipulators[manipulatorIndex]->SetView(CreateManipulatorViewCircle(
*m_localAngularManipulators[manipulatorIndex], colors[manipulatorIndex], radius, 0.05f, DrawHalfDottedCircle));
}
m_viewAngularManipulator->SetView(
CreateManipulatorViewCircle(
*m_viewAngularManipulator,
AZ::Color(1.0f, 1.0f, 1.0f, 1.0f),
radius + (radius * 0.12f), 0.05f, DrawFullCircle));
m_viewAngularManipulator->SetView(CreateManipulatorViewCircle(
*m_viewAngularManipulator, AZ::Color(1.0f, 1.0f, 1.0f, 1.0f), radius + (radius * 0.12f), 0.05f, DrawFullCircle));
}
bool RotationManipulators::PerformingActionViewAxis() const
@@ -1,27 +1,26 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Memory/SystemAllocator.h>
#include <AzToolsFramework/Manipulators/AngularManipulator.h>
#include <AzToolsFramework/API/EditorCameraBus.h>
#include <AzToolsFramework/Manipulators/AngularManipulator.h>
namespace AzToolsFramework
{
/// RotationManipulators is an aggregation of 3 angular manipulators who share the same origin
/// in addition to a view aligned angular manipulator (facing the camera).
class RotationManipulators
: public Manipulators
//! RotationManipulators is an aggregation of 3 angular manipulators who share the same origin
//! in addition to a view aligned angular manipulator (facing the camera).
class RotationManipulators : public Manipulators
{
public:
AZ_RTTI(RotationManipulators, "{5D1F1D47-1D5B-4E42-B47E-23F108F8BF7D}")
@@ -40,12 +39,10 @@ namespace AzToolsFramework
void SetLocalOrientationImpl(const AZ::Quaternion& localOrientation) override;
void RefreshView(const AZ::Vector3& worldViewPosition) override;
void SetLocalAxes(
const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3);
void SetLocalAxes(const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3);
void SetViewAxis(const AZ::Vector3& axis);
void ConfigureView(
float radius, const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color);
void ConfigureView(float radius, const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color);
bool PerformingActionViewAxis() const;
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ScaleManipulators.h"
@@ -28,8 +28,7 @@ namespace AzToolsFramework
m_manipulatorSpaceWithLocalTransform.SetSpace(worldFromLocal);
}
void ScaleManipulators::InstallAxisLeftMouseDownCallback(
const LinearManipulator::MouseActionCallback& onMouseDownCallback)
void ScaleManipulators::InstallAxisLeftMouseDownCallback(const LinearManipulator::MouseActionCallback& onMouseDownCallback)
{
for (AZStd::shared_ptr<LinearManipulator>& manipulator : m_axisScaleManipulators)
{
@@ -37,8 +36,7 @@ namespace AzToolsFramework
}
}
void ScaleManipulators::InstallAxisMouseMoveCallback(
const LinearManipulator::MouseActionCallback& onMouseMoveCallback)
void ScaleManipulators::InstallAxisMouseMoveCallback(const LinearManipulator::MouseActionCallback& onMouseMoveCallback)
{
for (AZStd::shared_ptr<LinearManipulator>& manipulator : m_axisScaleManipulators)
{
@@ -46,8 +44,7 @@ namespace AzToolsFramework
}
}
void ScaleManipulators::InstallAxisLeftMouseUpCallback(
const LinearManipulator::MouseActionCallback& onMouseUpCallback)
void ScaleManipulators::InstallAxisLeftMouseUpCallback(const LinearManipulator::MouseActionCallback& onMouseUpCallback)
{
for (AZStd::shared_ptr<LinearManipulator>& manipulator : m_axisScaleManipulators)
{
@@ -55,22 +52,19 @@ namespace AzToolsFramework
}
}
void ScaleManipulators::InstallUniformLeftMouseDownCallback(
const LinearManipulator::MouseActionCallback& onMouseDownCallback)
void ScaleManipulators::InstallUniformLeftMouseDownCallback(const LinearManipulator::MouseActionCallback& onMouseDownCallback)
{
m_uniformScaleManipulator->InstallLeftMouseDownCallback(onMouseDownCallback);
}
void ScaleManipulators::InstallUniformMouseMoveCallback(
const LinearManipulator::MouseActionCallback& onMouseMoveCallback)
void ScaleManipulators::InstallUniformMouseMoveCallback(const LinearManipulator::MouseActionCallback& onMouseMoveCallback)
{
m_uniformScaleManipulator->InstallMouseMoveCallback(onMouseMoveCallback);
m_uniformScaleManipulator->InstallMouseMoveCallback(onMouseMoveCallback);
}
void ScaleManipulators::InstallUniformLeftMouseUpCallback(
const LinearManipulator::MouseActionCallback& onMouseUpCallback)
void ScaleManipulators::InstallUniformLeftMouseUpCallback(const LinearManipulator::MouseActionCallback& onMouseUpCallback)
{
m_uniformScaleManipulator->InstallLeftMouseUpCallback(onMouseUpCallback);
m_uniformScaleManipulator->InstallLeftMouseUpCallback(onMouseUpCallback);
}
void ScaleManipulators::SetLocalTransformImpl(const AZ::Transform& localTransform)
@@ -80,8 +74,7 @@ namespace AzToolsFramework
manipulator->SetLocalTransform(localTransform);
}
m_uniformScaleManipulator->SetVisualOrientationOverride(
QuaternionFromTransformNoScaling(localTransform));
m_uniformScaleManipulator->SetVisualOrientationOverride(QuaternionFromTransformNoScaling(localTransform));
m_uniformScaleManipulator->SetLocalOrientation(AZ::Quaternion::CreateIdentity());
}
@@ -113,14 +106,13 @@ namespace AzToolsFramework
m_uniformScaleManipulator->SetSpace(worldFromLocal);
}
void ScaleManipulators::SetAxes(
const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3)
void ScaleManipulators::SetAxes(const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3)
{
AZ::Vector3 axes[] = { axis1, axis2, axis3 };
AZ::Vector3 axes[] = { axis1, axis2, axis3 };
for (size_t manipulatorIndex = 0; manipulatorIndex < m_axisScaleManipulators.size(); ++manipulatorIndex)
{
m_axisScaleManipulators[manipulatorIndex]->SetAxis(axes[manipulatorIndex]);
m_axisScaleManipulators[manipulatorIndex]->SetAxis(axes[manipulatorIndex]);
}
// uniform scale manipulator uses Z axis for scaling (always in world space)
@@ -129,32 +121,27 @@ namespace AzToolsFramework
}
void ScaleManipulators::ConfigureView(
const float axisLength, const AZ::Color& axis1Color,
const AZ::Color& axis2Color, const AZ::Color& axis3Color)
const float axisLength, const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color)
{
const float boxSize = 0.1f;
const float lineWidth = 0.05f;
const AZ::Color colors[] = {
axis1Color, axis2Color, axis3Color
};
const AZ::Color colors[] = { axis1Color, axis2Color, axis3Color };
for (size_t manipulatorIndex = 0; manipulatorIndex < m_axisScaleManipulators.size(); ++manipulatorIndex)
{
ManipulatorViews views;
views.emplace_back(CreateManipulatorViewLine(
*m_axisScaleManipulators[manipulatorIndex], colors[manipulatorIndex], axisLength, lineWidth));
views.emplace_back(
CreateManipulatorViewLine(*m_axisScaleManipulators[manipulatorIndex], colors[manipulatorIndex], axisLength, lineWidth));
views.emplace_back(CreateManipulatorViewBox(
AZ::Transform::CreateIdentity(), colors[manipulatorIndex],
m_axisScaleManipulators[manipulatorIndex]->GetAxis() * (axisLength - boxSize),
AZ::Vector3(boxSize)));
m_axisScaleManipulators[manipulatorIndex]->GetAxis() * (axisLength - boxSize), AZ::Vector3(boxSize)));
m_axisScaleManipulators[manipulatorIndex]->SetViews(AZStd::move(views));
}
ManipulatorViews views;
views.emplace_back(CreateManipulatorViewBox(
AZ::Transform::CreateIdentity(), AZ::Color::CreateOne(),
AZ::Vector3::CreateZero(), AZ::Vector3(boxSize)));
AZ::Transform::CreateIdentity(), AZ::Color::CreateOne(), AZ::Vector3::CreateZero(), AZ::Vector3(boxSize)));
m_uniformScaleManipulator->SetViews(AZStd::move(views));
}
@@ -167,4 +154,4 @@ namespace AzToolsFramework
manipulatorFn(m_uniformScaleManipulator.get());
}
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -17,11 +17,10 @@
namespace AzToolsFramework
{
/// ScaleManipulators is an aggregation of 3 linear manipulators for each basis axis who share
/// the same transform, and a single linear manipulator at the center of the transform whose
/// axis is world up (z).
class ScaleManipulators
: public Manipulators
//! ScaleManipulators is an aggregation of 3 linear manipulators for each basis axis who share
//! the same transform, and a single linear manipulator at the center of the transform whose
//! axis is world up (z).
class ScaleManipulators : public Manipulators
{
public:
AZ_RTTI(ScaleManipulators, "{C6350CE0-7B7A-46F8-B65F-D4A54DD9A7D9}")
@@ -42,16 +41,9 @@ namespace AzToolsFramework
void SetLocalPositionImpl(const AZ::Vector3& localPosition) override;
void SetLocalOrientationImpl(const AZ::Quaternion& localOrientation) override;
void SetAxes(
const AZ::Vector3& axis1,
const AZ::Vector3& axis2,
const AZ::Vector3& axis3);
void SetAxes(const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3);
void ConfigureView(
float axisLength,
const AZ::Color& axis1Color,
const AZ::Color& axis2Color,
const AZ::Color& axis3Color);
void ConfigureView(float axisLength, const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color);
private:
AZ_DISABLE_COPY_MOVE(ScaleManipulators)
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "SelectionManipulator.h"
@@ -16,8 +16,8 @@
namespace AzToolsFramework
{
AZStd::shared_ptr<SelectionManipulator> SelectionManipulator::MakeShared(const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale)
AZStd::shared_ptr<SelectionManipulator> SelectionManipulator::MakeShared(
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale)
{
return AZStd::shared_ptr<SelectionManipulator>(aznew SelectionManipulator(worldFromLocal, nonUniformScale));
}
@@ -93,12 +93,9 @@ namespace AzToolsFramework
for (auto& view : m_manipulatorViews)
{
view->Draw(
GetManipulatorManagerId(), managerState,
GetManipulatorId(), {
TransformUniformScale(GetSpace()), GetNonUniformScale(),
GetLocalPosition(), MouseOver()
},
debugDisplay, cameraState, mouseInteraction);
GetManipulatorManagerId(), managerState, GetManipulatorId(),
{ TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalPosition(), MouseOver() }, debugDisplay, cameraState,
mouseInteraction);
}
}
@@ -117,4 +114,4 @@ namespace AzToolsFramework
view->Invalidate(GetManipulatorManagerId());
}
}
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -20,13 +20,13 @@ namespace AzToolsFramework
{
class ManipulatorView;
/// Represents a sphere that can be clicked on to trigger a particular behavior
/// For example clicking a preview point to create a translation manipulator.
//! Represents a sphere that can be clicked on to trigger a particular behavior.
//! For example clicking a preview point to create a translation manipulator.
class SelectionManipulator
: public BaseManipulator
, public ManipulatorSpaceWithLocalPosition
{
/// Private constructor.
//! Private constructor.
SelectionManipulator(const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne());
public:
@@ -39,12 +39,12 @@ namespace AzToolsFramework
~SelectionManipulator() = default;
/// A Manipulator must only be created and managed through a shared_ptr.
static AZStd::shared_ptr<SelectionManipulator> MakeShared(const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne());
//! A Manipulator must only be created and managed through a shared_ptr.
static AZStd::shared_ptr<SelectionManipulator> MakeShared(
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne());
/// This is the function signature of callbacks that will be invoked
/// whenever a selection manipulator is clicked on.
//! This is the function signature of callbacks that will be invoked
//! whenever a selection manipulator is clicked on.
using MouseActionCallback = AZStd::function<void(const ViewportInteraction::MouseInteraction&)>;
void InstallLeftMouseDownCallback(const MouseActionCallback& onMouseDownCallback);
@@ -58,10 +58,25 @@ namespace AzToolsFramework
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
bool Selected() const { return m_selected; }
void Select() { m_selected = true; }
void Deselect() { m_selected = false; }
void ToggleSelected() { m_selected = !m_selected; }
bool Selected() const
{
return m_selected;
}
void Select()
{
m_selected = true;
}
void Deselect()
{
m_selected = false;
}
void ToggleSelected()
{
m_selected = !m_selected;
}
template<typename Views>
void SetViews(Views&& views)
@@ -70,13 +85,9 @@ namespace AzToolsFramework
}
private:
void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction,
float rayIntersectionDistance) override;
void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void OnRightMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction,
float rayIntersectionDistance) override;
void OnRightMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnRightMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void InvalidateImpl() override;
@@ -89,6 +100,6 @@ namespace AzToolsFramework
MouseActionCallback m_onRightMouseDownCallback = nullptr;
MouseActionCallback m_onRightMouseUpCallback = nullptr;
ManipulatorViews m_manipulatorViews; ///< Look of manipulator.
ManipulatorViews m_manipulatorViews; //!< Look of manipulator.
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "SplineHoverSelection.h"
@@ -20,11 +20,12 @@
namespace AzToolsFramework
{
static const AZ::Color s_splineSelectManipulatorColor = AZ::Color(0.0f, 1.0f, 0.0f, 1.0f);
static const AZ::Color SplineSelectManipulatorColor = AZ::Color(0.0f, 1.0f, 0.0f, 1.0f);
SplineHoverSelection::SplineHoverSelection(
const AZ::EntityComponentIdPair& entityComponentIdPair,
const ManipulatorManagerId managerId, const AZStd::shared_ptr<AZ::Spline>& spline)
const ManipulatorManagerId managerId,
const AZStd::shared_ptr<AZ::Spline>& spline)
{
m_splineSelectionManipulator = SplineSelectionManipulator::MakeShared();
m_splineSelectionManipulator->Register(managerId);
@@ -33,16 +34,14 @@ namespace AzToolsFramework
const float splineWidth = 0.05f;
m_splineSelectionManipulator->SetSpline(spline);
m_splineSelectionManipulator->SetView(CreateManipulatorViewSplineSelect(
*m_splineSelectionManipulator, s_splineSelectManipulatorColor, splineWidth));
m_splineSelectionManipulator->SetView(
CreateManipulatorViewSplineSelect(*m_splineSelectionManipulator, SplineSelectManipulatorColor, splineWidth));
m_splineSelectionManipulator->InstallLeftMouseUpCallback(
[entityComponentIdPair](const SplineSelectionManipulator::Action& action)
{
InsertVertexAfter(
entityComponentIdPair, action.m_splineAddress.m_segmentIndex,
action.m_localSplineHitPosition);
});
{
InsertVertexAfter(entityComponentIdPair, action.m_splineAddress.m_segmentIndex, action.m_localSplineHitPosition);
});
}
SplineHoverSelection::~SplineHoverSelection()
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -19,20 +19,20 @@ namespace AZ
{
class Spline;
class EntityComponentIdPair;
}
} // namespace AZ
namespace AzToolsFramework
{
class SplineSelectionManipulator;
/// SplineHoverSelection is a concrete implementation of HoverSelection wrapping a Spline and
/// SplineManipulator. The underlying manipulators are used to control selection.
class SplineHoverSelection
: public HoverSelection
//! SplineHoverSelection is a concrete implementation of HoverSelection wrapping a Spline and
//! SplineManipulator. The underlying manipulators are used to control selection.
class SplineHoverSelection : public HoverSelection
{
public:
explicit SplineHoverSelection(
const AZ::EntityComponentIdPair& entityComponentIdPair, ManipulatorManagerId managerId,
const AZ::EntityComponentIdPair& entityComponentIdPair,
ManipulatorManagerId managerId,
const AZStd::shared_ptr<AZ::Spline>& spline);
SplineHoverSelection(const SplineHoverSelection&) = delete;
SplineHoverSelection& operator=(const SplineHoverSelection&) = delete;
@@ -46,6 +46,6 @@ namespace AzToolsFramework
void SetNonUniformScale(const AZ::Vector3& nonUniformScale) override;
private:
AZStd::shared_ptr<SplineSelectionManipulator> m_splineSelectionManipulator; ///< Manipulator for adding points to spline.
AZStd::shared_ptr<SplineSelectionManipulator> m_splineSelectionManipulator; //!< Manipulator for adding points to spline.
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "SplineSelectionManipulator.h"
@@ -18,8 +18,10 @@
namespace AzToolsFramework
{
SplineSelectionManipulator::Action CalculateManipulationDataAction(
const AZ::Transform& worldFromLocal, const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection, const AZStd::weak_ptr<const AZ::Spline>& spline)
const AZ::Transform& worldFromLocal,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const AZStd::weak_ptr<const AZ::Spline>& spline)
{
SplineSelectionManipulator::Action action;
if (const AZStd::shared_ptr<const AZ::Spline> splinePtr = spline.lock())
@@ -65,9 +67,7 @@ namespace AzToolsFramework
if (m_onLeftMouseDownCallback)
{
m_onLeftMouseDownCallback(CalculateManipulationDataAction(
TransformUniformScale(GetSpace()),
interaction.m_mousePick.m_rayOrigin,
interaction.m_mousePick.m_rayDirection, m_spline));
TransformUniformScale(GetSpace()), interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection, m_spline));
}
}
@@ -76,9 +76,7 @@ namespace AzToolsFramework
if (MouseOver() && m_onLeftMouseUpCallback)
{
m_onLeftMouseUpCallback(CalculateManipulationDataAction(
TransformUniformScale(GetSpace()),
interaction.m_mousePick.m_rayOrigin,
interaction.m_mousePick.m_rayDirection, m_spline));
TransformUniformScale(GetSpace()), interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection, m_spline));
}
}
@@ -99,12 +97,9 @@ namespace AzToolsFramework
if (mouseInteraction.m_keyboardModifiers.Ctrl() && !mouseInteraction.m_keyboardModifiers.Shift())
{
m_manipulatorView->Draw(
GetManipulatorManagerId(), managerState,
GetManipulatorId(), {
TransformUniformScale(GetSpace()), GetNonUniformScale(),
AZ::Vector3::CreateZero(), MouseOver()
},
debugDisplay, cameraState, mouseInteraction);
GetManipulatorManagerId(), managerState, GetManipulatorId(),
{ TransformUniformScale(GetSpace()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay,
cameraState, mouseInteraction);
}
}
@@ -122,4 +117,4 @@ namespace AzToolsFramework
{
m_manipulatorView->Invalidate(GetManipulatorManagerId());
}
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -23,13 +23,13 @@ namespace AzToolsFramework
{
class ManipulatorView;
/// A manipulator to represent selection of a spline. Underlying spline data is
/// used to test mouse picking ray against to preview closest point on spline.
//! A manipulator to represent selection of a spline. Underlying spline data is
//! used to test mouse picking ray against to preview closest point on spline.
class SplineSelectionManipulator
: public BaseManipulator
, public ManipulatorSpace
{
/// Private constructor.
//! Private constructor.
SplineSelectionManipulator();
public:
@@ -41,10 +41,10 @@ namespace AzToolsFramework
~SplineSelectionManipulator();
/// A Manipulator must only be created and managed through a shared_ptr.
//! A Manipulator must only be created and managed through a shared_ptr.
static AZStd::shared_ptr<SplineSelectionManipulator> MakeShared();
/// Mouse action data used by MouseActionCallback.
//! Mouse action data used by MouseActionCallback.
struct Action
{
AZ::Vector3 m_localSplineHitPosition;
@@ -62,29 +62,36 @@ namespace AzToolsFramework
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteraction& mouseInteraction) override;
void SetSpline(AZStd::shared_ptr<const AZ::Spline> spline) { m_spline = AZStd::move(spline); }
AZStd::weak_ptr<const AZ::Spline> GetSpline() const { return m_spline; }
void SetSpline(AZStd::shared_ptr<const AZ::Spline> spline)
{
m_spline = AZStd::move(spline);
}
AZStd::weak_ptr<const AZ::Spline> GetSpline() const
{
return m_spline;
}
void SetView(AZStd::unique_ptr<ManipulatorView>&& view);
private:
void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void InvalidateImpl() override;
void SetBoundsDirtyImpl() override;
AZStd::weak_ptr<const AZ::Spline> m_spline;
AZStd::unique_ptr<ManipulatorView> m_manipulatorView = nullptr; ///< Look of manipulator and bounds for interaction.
AZStd::unique_ptr<ManipulatorView> m_manipulatorView = nullptr; //!< Look of manipulator and bounds for interaction.
MouseActionCallback m_onLeftMouseDownCallback = nullptr;
MouseActionCallback m_onLeftMouseUpCallback = nullptr;
ViewportInteraction::KeyboardModifiers m_keyboardModifiers; ///< What modifier keys are pressed when interacting with this manipulator.
ViewportInteraction::KeyboardModifiers
m_keyboardModifiers; //!< What modifier keys are pressed when interacting with this manipulator.
};
SplineSelectionManipulator::Action CalculateManipulationDataAction(
const AZ::Transform& worldFromLocal, const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection, const AZStd::weak_ptr<const AZ::Spline>& spline);
const AZ::Transform& worldFromLocal,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const AZStd::weak_ptr<const AZ::Spline>& spline);
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "SurfaceManipulator.h"
@@ -18,19 +18,22 @@
namespace AzToolsFramework
{
SurfaceManipulator::StartInternal SurfaceManipulator::CalculateManipulationDataStart(
const AZ::Transform& worldFromLocal, const AZ::Vector3& worldSurfacePosition,
const AZ::Vector3& localStartPosition, const bool snapping, const float gridSize, const int viewportId)
const AZ::Transform& worldFromLocal,
const AZ::Vector3& worldSurfacePosition,
const AZ::Vector3& localStartPosition,
const bool snapping,
const float gridSize,
const int viewportId)
{
const AZ::Transform worldFromLocalUniform = AzToolsFramework::TransformUniformScale(worldFromLocal);
const AZ::Transform localFromWorldUniform = worldFromLocalUniform.GetInverse();
const AZ::Vector3 localFinalSurfacePosition = snapping
? CalculateSnappedTerrainPosition(
// note: gridSize is not scaled by scaleRecip here as localStartPosition is
// unscaled itself so the position returned by CalculateSnappedTerrainPosition
// must be in the same space (if localStartPosition were also scaled, gridSize
// would need to be multiplied by scaleRecip)
worldSurfacePosition, worldFromLocalUniform, viewportId, gridSize)
// note: gridSize is not scaled by scaleRecip here as localStartPosition is
// unscaled itself so the position returned by CalculateSnappedTerrainPosition
// must be in the same space (if localStartPosition were also scaled, gridSize
// would need to be multiplied by scaleRecip)
? CalculateSnappedTerrainPosition(worldSurfacePosition, worldFromLocalUniform, viewportId, gridSize)
: localFromWorldUniform.TransformPoint(worldSurfacePosition);
// delta/offset between initial vertex position and terrain pick position
@@ -44,9 +47,13 @@ namespace AzToolsFramework
}
SurfaceManipulator::Action SurfaceManipulator::CalculateManipulationDataAction(
const StartInternal& startInternal, const AZ::Transform& worldFromLocal,
const AZ::Vector3& worldSurfacePosition, const bool snapping, const float gridSize,
const ViewportInteraction::KeyboardModifiers keyboardModifiers, const int viewportId)
const StartInternal& startInternal,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& worldSurfacePosition,
const bool snapping,
const float gridSize,
const ViewportInteraction::KeyboardModifiers keyboardModifiers,
const int viewportId)
{
const AZ::Transform worldFromLocalUniform = AzToolsFramework::TransformUniformScale(worldFromLocal);
const AZ::Transform localFromWorldUniform = worldFromLocalUniform.GetInverse();
@@ -54,8 +61,7 @@ namespace AzToolsFramework
const float scaleRecip = ScaleReciprocal(worldFromLocalUniform);
const AZ::Vector3 localFinalSurfacePosition = snapping
? CalculateSnappedTerrainPosition(
worldSurfacePosition, worldFromLocalUniform, viewportId, gridSize * scaleRecip)
? CalculateSnappedTerrainPosition(worldSurfacePosition, worldFromLocalUniform, viewportId, gridSize * scaleRecip)
: localFromWorldUniform.TransformPoint(worldSurfacePosition);
Action action;
@@ -106,17 +112,14 @@ namespace AzToolsFramework
interaction.m_mousePick.m_screenCoordinates);
m_startInternal = CalculateManipulationDataStart(
worldFromLocalUniformScale, worldSurfacePosition, GetLocalPosition(),
gridSnapParams.m_gridSnap, gridSnapParams.m_gridSize,
worldFromLocalUniformScale, worldSurfacePosition, GetLocalPosition(), gridSnapParams.m_gridSnap, gridSnapParams.m_gridSize,
interaction.m_interactionId.m_viewportId);
if (m_onLeftMouseDownCallback)
{
m_onLeftMouseDownCallback(CalculateManipulationDataAction(
m_startInternal, worldFromLocalUniformScale, worldSurfacePosition,
gridSnapParams.m_gridSnap, gridSnapParams.m_gridSize,
interaction.m_keyboardModifiers,
interaction.m_interactionId.m_viewportId));
m_startInternal, worldFromLocalUniformScale, worldSurfacePosition, gridSnapParams.m_gridSnap, gridSnapParams.m_gridSize,
interaction.m_keyboardModifiers, interaction.m_interactionId.m_viewportId));
}
}
@@ -133,10 +136,8 @@ namespace AzToolsFramework
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
m_onLeftMouseUpCallback(CalculateManipulationDataAction(
m_startInternal, TransformUniformScale(GetSpace()), worldSurfacePosition,
gridSnapParams.m_gridSnap,
gridSnapParams.m_gridSize,
interaction.m_keyboardModifiers, interaction.m_interactionId.m_viewportId));
m_startInternal, TransformUniformScale(GetSpace()), worldSurfacePosition, gridSnapParams.m_gridSnap,
gridSnapParams.m_gridSize, interaction.m_keyboardModifiers, interaction.m_interactionId.m_viewportId));
}
}
@@ -153,10 +154,8 @@ namespace AzToolsFramework
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
m_onMouseMoveCallback(CalculateManipulationDataAction(
m_startInternal, TransformUniformScale(GetSpace()), worldSurfacePosition,
gridSnapParams.m_gridSnap,
gridSnapParams.m_gridSize,
interaction.m_keyboardModifiers, interaction.m_interactionId.m_viewportId));
m_startInternal, TransformUniformScale(GetSpace()), worldSurfacePosition, gridSnapParams.m_gridSnap,
gridSnapParams.m_gridSize, interaction.m_keyboardModifiers, interaction.m_interactionId.m_viewportId));
}
}
@@ -172,12 +171,9 @@ namespace AzToolsFramework
const ViewportInteraction::MouseInteraction& mouseInteraction)
{
m_manipulatorView->Draw(
GetManipulatorManagerId(), managerState,
GetManipulatorId(), {
TransformUniformScale(GetSpace()), GetNonUniformScale(),
GetLocalPosition(), MouseOver()
},
debugDisplay, cameraState, mouseInteraction);
GetManipulatorManagerId(), managerState, GetManipulatorId(),
{ TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalPosition(), MouseOver() }, debugDisplay, cameraState,
mouseInteraction);
}
void SurfaceManipulator::InvalidateImpl()
@@ -189,4 +185,4 @@ namespace AzToolsFramework
{
m_manipulatorView = AZStd::move(view);
}
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -21,13 +21,13 @@ namespace AzToolsFramework
{
class ManipulatorView;
/// Surface manipulator will ensure the point(s) it controls snap precisely to the xy grid
/// while also staying aligned exactly to the height of the terrain.
//! Surface manipulator will ensure the point(s) it controls snap precisely to the xy grid
//! while also staying aligned exactly to the height of the terrain.
class SurfaceManipulator
: public BaseManipulator
, public ManipulatorSpaceWithLocalPosition
{
/// Private constructor.
//! Private constructor.
explicit SurfaceManipulator(const AZ::Transform& worldFromLocal);
public:
@@ -40,30 +40,36 @@ namespace AzToolsFramework
~SurfaceManipulator() = default;
/// A Manipulator must only be created and managed through a shared_ptr.
//! A Manipulator must only be created and managed through a shared_ptr.
static AZStd::shared_ptr<SurfaceManipulator> MakeShared(const AZ::Transform& worldFromLocal);
/// The state of the manipulator at the start of an interaction.
//! The state of the manipulator at the start of an interaction.
struct Start
{
AZ::Vector3 m_localPosition; ///< The current position of the manipulator in local space.
AZ::Vector3 m_snapOffset; ///< The snap offset amount to ensure manipulator is aligned to the grid.
AZ::Vector3 m_localPosition; //!< The current position of the manipulator in local space.
AZ::Vector3 m_snapOffset; //!< The snap offset amount to ensure manipulator is aligned to the grid.
};
/// The state of the manipulator during an interaction.
//! The state of the manipulator during an interaction.
struct Current
{
AZ::Vector3 m_localOffset; ///< The current offset of the manipulator from its starting position in local space.
AZ::Vector3 m_localOffset; //!< The current offset of the manipulator from its starting position in local space.
};
/// Mouse action data used by MouseActionCallback (wraps Start and Current manipulator state).
//! Mouse action data used by MouseActionCallback (wraps Start and Current manipulator state).
struct Action
{
Start m_start;
Current m_current;
ViewportInteraction::KeyboardModifiers m_modifiers;
AZ::Vector3 LocalPosition() const { return m_start.m_localPosition + m_current.m_localOffset; }
AZ::Vector3 LocalPositionOffset() const { return m_current.m_localOffset; }
AZ::Vector3 LocalPosition() const
{
return m_start.m_localPosition + m_current.m_localOffset;
}
AZ::Vector3 LocalPositionOffset() const
{
return m_current.m_localOffset;
}
};
using MouseActionCallback = AZStd::function<void(const Action&)>;
@@ -81,39 +87,44 @@ namespace AzToolsFramework
void SetView(AZStd::unique_ptr<ManipulatorView>&& view);
private:
void OnLeftMouseDownImpl(
const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(
const ViewportInteraction::MouseInteraction& interaction) override;
void OnLeftMouseDownImpl(const ViewportInteraction::MouseInteraction& interaction, float rayIntersectionDistance) override;
void OnLeftMouseUpImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void OnMouseMoveImpl(const ViewportInteraction::MouseInteraction& interaction) override;
void InvalidateImpl() override;
void SetBoundsDirtyImpl() override;
/// Initial data recorded when a press first happens with a surface manipulator.
//! Initial data recorded when a press first happens with a surface manipulator.
struct StartInternal
{
AZ::Vector3 m_localPosition; ///< The current position of the manipulator in local space.
AZ::Vector3 m_localHitPosition; ///< The hit position with the terrain in local space.
AZ::Vector3 m_snapOffset; ///< The snap offset amount to ensure manipulator is aligned to the grid.
AZ::Vector3 m_localPosition; //!< The current position of the manipulator in local space.
AZ::Vector3 m_localHitPosition; //!< The hit position with the terrain in local space.
AZ::Vector3 m_snapOffset; //!< The snap offset amount to ensure manipulator is aligned to the grid.
};
StartInternal m_startInternal; ///< Internal initial state recorded/created in OnMouseDown.
StartInternal m_startInternal; //!< Internal initial state recorded/created in OnMouseDown.
AZStd::unique_ptr<ManipulatorView> m_manipulatorView = nullptr; ///< Look of manipulator.
AZStd::unique_ptr<ManipulatorView> m_manipulatorView = nullptr; //!< Look of manipulator.
MouseActionCallback m_onLeftMouseDownCallback = nullptr;
MouseActionCallback m_onLeftMouseUpCallback = nullptr;
MouseActionCallback m_onMouseMoveCallback = nullptr;
static StartInternal CalculateManipulationDataStart(
const AZ::Transform& worldFromLocal, const AZ::Vector3& worldSurfacePosition,
const AZ::Vector3& localPosition, bool snapping, float gridSize, int viewportId);
const AZ::Transform& worldFromLocal,
const AZ::Vector3& worldSurfacePosition,
const AZ::Vector3& localPosition,
bool snapping,
float gridSize,
int viewportId);
static Action CalculateManipulationDataAction(
const StartInternal& startInternal, const AZ::Transform& worldFromLocal,
const AZ::Vector3& worldSurfacePosition, bool snapping, float gridSize,
ViewportInteraction::KeyboardModifiers keyboardModifiers, int viewportId);
const StartInternal& startInternal,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& worldSurfacePosition,
bool snapping,
float gridSize,
ViewportInteraction::KeyboardModifiers keyboardModifiers,
int viewportId);
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "TranslationManipulators.h"
@@ -77,8 +77,7 @@ namespace AzToolsFramework
}
}
void TranslationManipulators::InstallLinearManipulatorMouseUpCallback(
const LinearManipulator::MouseActionCallback& onMouseUpCallback)
void TranslationManipulators::InstallLinearManipulatorMouseUpCallback(const LinearManipulator::MouseActionCallback& onMouseUpCallback)
{
for (AZStd::shared_ptr<LinearManipulator>& manipulator : m_linearManipulators)
{
@@ -104,8 +103,7 @@ namespace AzToolsFramework
}
}
void TranslationManipulators::InstallPlanarManipulatorMouseUpCallback(
const PlanarManipulator::MouseActionCallback& onMouseUpCallback)
void TranslationManipulators::InstallPlanarManipulatorMouseUpCallback(const PlanarManipulator::MouseActionCallback& onMouseUpCallback)
{
for (AZStd::shared_ptr<PlanarManipulator>& manipulator : m_planarManipulators)
{
@@ -122,8 +120,7 @@ namespace AzToolsFramework
}
}
void TranslationManipulators::InstallSurfaceManipulatorMouseUpCallback(
const SurfaceManipulator::MouseActionCallback& onMouseUpCallback)
void TranslationManipulators::InstallSurfaceManipulatorMouseUpCallback(const SurfaceManipulator::MouseActionCallback& onMouseUpCallback)
{
if (m_surfaceManipulator)
{
@@ -242,7 +239,9 @@ namespace AzToolsFramework
}
void TranslationManipulators::ConfigureLinearView(
float axisLength, const AZ::Color& axis1Color, const AZ::Color& axis2Color,
float axisLength,
const AZ::Color& axis1Color,
const AZ::Color& axis2Color,
const AZ::Color& axis3Color /*= AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)*/)
{
const float coneLength = 0.28f;
@@ -251,15 +250,13 @@ namespace AzToolsFramework
const AZ::Color axesColor[] = { axis1Color, axis2Color, axis3Color };
const auto configureLinearView = [lineWidth, coneLength, axisLength, coneRadius](
LinearManipulator* linearManipulator, const AZ::Color& color)
const auto configureLinearView =
[lineWidth, coneLength, axisLength, coneRadius](LinearManipulator* linearManipulator, const AZ::Color& color)
{
ManipulatorViews views;
views.emplace_back(CreateManipulatorViewLine(
*linearManipulator, color, axisLength, lineWidth));
views.emplace_back(CreateManipulatorViewLine(*linearManipulator, color, axisLength, lineWidth));
views.emplace_back(CreateManipulatorViewCone(
*linearManipulator, color, linearManipulator->GetAxis() * (axisLength - coneLength),
coneLength, coneRadius));
*linearManipulator, color, linearManipulator->GetAxis() * (axisLength - coneLength), coneLength, coneRadius));
linearManipulator->SetViews(AZStd::move(views));
};
@@ -270,7 +267,8 @@ namespace AzToolsFramework
}
void TranslationManipulators::ConfigurePlanarView(
const AZ::Color& plane1Color, const AZ::Color& plane2Color /*= AZ::Color(0.0f, 1.0f, 0.0f, 0.5f)*/,
const AZ::Color& plane1Color,
const AZ::Color& plane2Color /*= AZ::Color(0.0f, 1.0f, 0.0f, 0.5f)*/,
const AZ::Color& plane3Color /*= AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)*/)
{
const float planeSize = 0.6f;
@@ -278,34 +276,29 @@ namespace AzToolsFramework
for (size_t manipulatorIndex = 0; manipulatorIndex < m_planarManipulators.size(); ++manipulatorIndex)
{
const AZStd::shared_ptr<ManipulatorViewQuad> manipulatorView =
CreateManipulatorViewQuad(
*m_planarManipulators[manipulatorIndex], planesColor[manipulatorIndex],
planesColor[(manipulatorIndex + 1) % 3],
planeSize);
const AZStd::shared_ptr<ManipulatorViewQuad> manipulatorView = CreateManipulatorViewQuad(
*m_planarManipulators[manipulatorIndex], planesColor[manipulatorIndex], planesColor[(manipulatorIndex + 1) % 3], planeSize);
m_planarManipulators[manipulatorIndex]->SetViews(ManipulatorViews{manipulatorView});
m_planarManipulators[manipulatorIndex]->SetViews(ManipulatorViews{ manipulatorView });
}
}
void TranslationManipulators::ConfigureSurfaceView(
const float radius, const AZ::Color& color)
void TranslationManipulators::ConfigureSurfaceView(const float radius, const AZ::Color& color)
{
if (m_surfaceManipulator)
{
m_surfaceManipulator->SetView(CreateManipulatorViewSphere(color, radius,
[](const ViewportInteraction::MouseInteraction& /*mouseInteraction*/,
bool mouseOver, const AZ::Color& defaultColor) -> AZ::Color
{
const AZ::Color color[2] =
m_surfaceManipulator->SetView(CreateManipulatorViewSphere(
color, radius,
[](const ViewportInteraction::MouseInteraction& /*mouseInteraction*/, bool mouseOver,
const AZ::Color& defaultColor) -> AZ::Color
{
defaultColor,
Vector3ToVector4(
BaseManipulator::s_defaultMouseOverColor.GetAsVector3(), s_surfaceManipulatorTransparency)
};
const AZ::Color color[2] = {
defaultColor,
Vector3ToVector4(BaseManipulator::s_defaultMouseOverColor.GetAsVector3(), s_surfaceManipulatorTransparency)
};
return color[mouseOver];
}));
return color[mouseOver];
}));
}
}
@@ -327,27 +320,17 @@ namespace AzToolsFramework
}
}
void ConfigureTranslationManipulatorAppearance3d(
TranslationManipulators* translationManipulators)
void ConfigureTranslationManipulatorAppearance3d(TranslationManipulators* translationManipulators)
{
translationManipulators->SetAxes(
AZ::Vector3::CreateAxisX(),
AZ::Vector3::CreateAxisY(),
AZ::Vector3::CreateAxisZ());
translationManipulators->ConfigurePlanarView(
s_xAxisColor, s_yAxisColor, s_zAxisColor);
translationManipulators->ConfigureLinearView(
s_axisLength, s_xAxisColor, s_yAxisColor, s_zAxisColor);
translationManipulators->ConfigureSurfaceView(
s_surfaceManipulatorRadius, s_surfaceManipulatorColor);
translationManipulators->SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
translationManipulators->ConfigurePlanarView(s_xAxisColor, s_yAxisColor, s_zAxisColor);
translationManipulators->ConfigureLinearView(s_axisLength, s_xAxisColor, s_yAxisColor, s_zAxisColor);
translationManipulators->ConfigureSurfaceView(s_surfaceManipulatorRadius, s_surfaceManipulatorColor);
}
void ConfigureTranslationManipulatorAppearance2d(
TranslationManipulators* translationManipulators)
void ConfigureTranslationManipulatorAppearance2d(TranslationManipulators* translationManipulators)
{
translationManipulators->SetAxes(
AZ::Vector3::CreateAxisX(),
AZ::Vector3::CreateAxisY());
translationManipulators->SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY());
translationManipulators->ConfigurePlanarView(s_xAxisColor);
translationManipulators->ConfigureLinearView(s_axisLength, s_xAxisColor, s_yAxisColor);
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -19,16 +19,15 @@
namespace AzToolsFramework
{
/// TranslationManipulators is an aggregation of 3 linear manipulators, 3 planar manipulators
/// and one surface manipulator who share the same transform.
class TranslationManipulators
: public Manipulators
//! TranslationManipulators is an aggregation of 3 linear manipulators, 3 planar manipulators
//! and one surface manipulator who share the same transform.
class TranslationManipulators : public Manipulators
{
public:
AZ_RTTI(TranslationManipulators, "{D5E49EA2-30E0-42BC-A51D-6A7F87818260}")
AZ_CLASS_ALLOCATOR(TranslationManipulators, AZ::SystemAllocator, 0)
/// How many dimensions does this translation manipulator have
//! How many dimensions does this translation manipulator have.
enum class Dimensions
{
Two,
@@ -55,9 +54,7 @@ namespace AzToolsFramework
void SetLocalOrientationImpl(const AZ::Quaternion& localOrientation) override;
void SetNonUniformScaleImpl(const AZ::Vector3& nonUniformScale) override;
void SetAxes(
const AZ::Vector3& axis1, const AZ::Vector3& axis2,
const AZ::Vector3& axis3 = AZ::Vector3::CreateAxisZ());
void SetAxes(const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3 = AZ::Vector3::CreateAxisZ());
void ConfigurePlanarView(
const AZ::Color& plane1Color,
@@ -66,11 +63,11 @@ namespace AzToolsFramework
void ConfigureLinearView(
float axisLength,
const AZ::Color& axis1Color, const AZ::Color& axis2Color,
const AZ::Color& axis1Color,
const AZ::Color& axis2Color,
const AZ::Color& axis3Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f));
void ConfigureSurfaceView(
float radius, const AZ::Color& color);
void ConfigureSurfaceView(float radius, const AZ::Color& color);
private:
AZ_DISABLE_COPY_MOVE(TranslationManipulators)
@@ -78,37 +75,43 @@ namespace AzToolsFramework
// Manipulators
void ProcessManipulators(const AZStd::function<void(BaseManipulator*)>&) override;
const Dimensions m_dimensions; ///< How many dimensions of freedom does this manipulator have.
const Dimensions m_dimensions; //!< How many dimensions of freedom does this manipulator have.
AZStd::vector<AZStd::shared_ptr<LinearManipulator>> m_linearManipulators;
AZStd::vector<AZStd::shared_ptr<PlanarManipulator>> m_planarManipulators;
AZStd::shared_ptr<SurfaceManipulator> m_surfaceManipulator = nullptr;
};
/// IndexedTranslationManipulator wraps a standard TranslationManipulators and allows it to be linked
/// to a particular index in a list of vertices/points.
//! IndexedTranslationManipulator wraps a standard TranslationManipulators and allows it to be linked
//! to a particular index in a list of vertices/points.
template<typename Vertex>
struct IndexedTranslationManipulator
{
explicit IndexedTranslationManipulator(
TranslationManipulators::Dimensions dimensions, AZ::u64 vertIndex,
const Vertex& position, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale)
: m_manipulator(dimensions, worldFromLocal, nonUniformScale)
TranslationManipulators::Dimensions dimensions,
AZ::u64 vertIndex,
const Vertex& position,
const AZ::Transform& worldFromLocal,
const AZ::Vector3& nonUniformScale)
: m_manipulator(dimensions, worldFromLocal, nonUniformScale)
{
m_vertices.push_back({ position, Vertex::CreateZero(), vertIndex });
}
/// Store vertex start position as manipulator event occurs, index refers to location in container.
//! Store vertex start position as manipulator event occurs, index refers to location in container.
struct VertexLookup
{
Vertex m_start;
Vertex m_offset;
AZ::u64 m_index;
Vertex CurrentPosition() const { return m_start + m_offset; }
Vertex CurrentPosition() const
{
return m_start + m_offset;
}
};
/// Helper to iterate over all vertices stored by the manipulator.
//! Helper to iterate over all vertices stored by the manipulator.
void Process(AZStd::function<void(VertexLookup&)> fn)
{
for (VertexLookup& vertex : m_vertices)
@@ -117,16 +120,14 @@ namespace AzToolsFramework
}
}
AZStd::vector<VertexLookup> m_vertices; ///< List of vertices currently associated with this translation manipulator.
AZStd::vector<VertexLookup> m_vertices; //!< List of vertices currently associated with this translation manipulator.
TranslationManipulators m_manipulator;
};
/// Function pointer to configure how a translation manipulator should look and behave (dimensions/axes/views).
using TranslationManipulatorConfiguratorFn = void(*)(TranslationManipulators*);
//! Function pointer to configure how a translation manipulator should look and behave (dimensions/axes/views).
using TranslationManipulatorConfiguratorFn = void (*)(TranslationManipulators*);
void ConfigureTranslationManipulatorAppearance3d(
TranslationManipulators* translationManipulators);
void ConfigureTranslationManipulatorAppearance2d(
TranslationManipulators* translationManipulators);
void ConfigureTranslationManipulatorAppearance3d(TranslationManipulators* translationManipulators);
void ConfigureTranslationManipulatorAppearance2d(TranslationManipulators* translationManipulators);
} // namespace AzToolsFramework
@@ -1,14 +1,15 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Vector3.h>
@@ -16,30 +17,44 @@
namespace AzToolsFramework
{
/**
* Provide unique type alias for AZ::u64 for manipulator, bounds and manager.
*/
//! Provide unique type alias for AZ::u64 for manipulator, bounds and manager.
template<typename T>
class IdType
{
public:
explicit IdType(AZ::u64 id = 0)
: m_id(id) {}
operator AZ::u64() const { return m_id; }
: m_id(id)
{
}
operator AZ::u64() const
{
return m_id;
}
bool operator==(IdType other) const
{
return m_id == other.m_id;
}
bool operator!=(IdType other) const
{
return m_id != other.m_id;
}
bool operator==(IdType other) const { return m_id == other.m_id; }
bool operator!=(IdType other) const { return m_id != other.m_id; }
IdType& operator++() // pre-increment
{
++m_id;
return *this;
}
IdType operator++(int) // post-increment
{
IdType temp = *this;
++*this;
return temp;
}
private:
AZ::u64 m_id;
};
@@ -51,10 +66,8 @@ namespace AzToolsFramework
using RegisteredBoundId = IdType<struct RegisteredBoundType>;
static const RegisteredBoundId InvalidBoundId = RegisteredBoundId(0);
/**
* This class serves as the base class for the actual bound shapes that various DefaultContextBoundManager-derived
* classes return from the function CreateShape.
*/
//! This class serves as the base class for the actual bound shapes that various DefaultContextBoundManager-derived
//! classes return from the function CreateShape.
class BoundShapeInterface
{
public:
@@ -63,25 +76,33 @@ namespace AzToolsFramework
explicit BoundShapeInterface(const RegisteredBoundId boundId)
: m_boundId(boundId)
, m_valid(false)
{}
{
}
virtual ~BoundShapeInterface() = default;
RegisteredBoundId GetBoundId() const { return m_boundId; }
RegisteredBoundId GetBoundId() const
{
return m_boundId;
}
/**
* @param rayOrigin The origin of the ray to test with.
* @param rayDir The direction of the ray to test with.
* @param[out] rayIntersectionDistance The distance of the intersecting point closest to the ray origin.
* @return Boolean indicating whether there is a least one intersecting point between this bound shape and the ray.
*/
virtual bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) = 0;
//! @param rayOrigin The origin of the ray to test with.
//! @param rayDir The direction of the ray to test with.
//! @param[out] rayIntersectionDistance The distance of the intersecting point closest to the ray origin.
//! @return Boolean indicating whether there is a least one intersecting point between this bound shape and the ray.
virtual bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) = 0;
virtual void SetShapeData(const BoundRequestShapeBase& shapeData) = 0;
void SetValidity(bool valid) { m_valid = valid; }
bool IsValid() const { return m_valid; }
void SetValidity(bool valid)
{
m_valid = valid;
}
bool IsValid() const
{
return m_valid;
}
private:
RegisteredBoundId m_boundId;
@@ -1,22 +1,22 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/Math/Spline.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/smart_ptr/make_shared.h>
@@ -27,9 +27,7 @@ namespace AzToolsFramework
{
namespace Picking
{
/**
* An interface concrete shape types can implement to create specific BoundShapeInterfaces.
*/
//! An interface concrete shape types can implement to create specific BoundShapeInterfaces.
class BoundRequestShapeBase
{
public:
@@ -114,11 +112,9 @@ namespace AzToolsFramework
float m_radius;
};
/**
* The quad shape consists of 4 points in 3D space. Please set them from \ref m_corner1 to \ref m_corner4
* in either clock-wise winding or counter clock-wise winding. In another word, \ref m_corner1 and
* \ref corner_2 cannot be diagonal corners.
*/
//! The quad shape consists of 4 points in 3D space. Please set them from \ref m_corner1 to \ref m_corner4
//! in either clock-wise winding or counter clock-wise winding. In another word, \ref m_corner1 and
//! \ref corner_2 cannot be diagonal corners.
class BoundShapeQuad : public BoundRequestShapeBase
{
public:
@@ -138,9 +134,7 @@ namespace AzToolsFramework
AZ::Vector3 m_corner4;
};
/**
* The line segment consists of two points in 3D space defining a line the user can interact with.
*/
//! The line segment consists of two points in 3D space defining a line the user can interact with.
class BoundShapeLineSegment : public BoundRequestShapeBase
{
public:
@@ -159,10 +153,8 @@ namespace AzToolsFramework
float m_width;
};
/**
* The torus shape is approximated by a cylinder whose radius is the sum of the torus's major radius
* and minor radius and height is twice the torus's minor radius.
*/
//! The torus shape is approximated by a cylinder whose radius is the sum of the torus's major radius
//! and minor radius and height is twice the torus's minor radius.
class BoundShapeTorus : public BoundRequestShapeBase
{
public:
@@ -182,10 +174,8 @@ namespace AzToolsFramework
float m_minorRadius;
};
/**
* The spline is specified by a number of vertices. A piecewise approximation of the curve
* is computed by using a number of linear steps (defined by the granularity of the curve).
*/
//! The spline is specified by a number of vertices. A piecewise approximation of the curve
//! is computed by using a number of linear steps (defined by the granularity of the curve).
class BoundShapeSpline : public BoundRequestShapeBase
{
public:
@@ -204,16 +194,14 @@ namespace AzToolsFramework
float m_width;
};
/**
* Ray query for intersection against bounds.
*/
//! Ray query for intersection against bounds.
struct RaySelectInfo
{
AZ::Vector3 m_origin; ///< Start of ray.
AZ::Vector3 m_direction; ///< Direction of ray - make sure m_direction is unit length.
AZStd::vector<AZStd::pair<RegisteredBoundId, float>> m_boundIdsHit; ///< Store the id of the intersected bound
///< and the parameter of the corresponding
///< intersecting point.
AZ::Vector3 m_origin; //!< Start of ray.
AZ::Vector3 m_direction; //!< Direction of ray - make sure m_direction is unit length.
AZStd::vector<AZStd::pair<RegisteredBoundId, float>> m_boundIdsHit; //!< Store the id of the intersected bound
//!< and the parameter of the corresponding
//!< intersecting point.
};
} // namespace Picking
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ManipulatorBoundManager.h"
@@ -16,8 +16,7 @@ namespace AzToolsFramework
{
namespace Picking
{
RegisteredBoundId ManipulatorBoundManager::UpdateOrRegisterBound(
const BoundRequestShapeBase& shapeData, RegisteredBoundId boundId)
RegisteredBoundId ManipulatorBoundManager::UpdateOrRegisterBound(const BoundRequestShapeBase& shapeData, RegisteredBoundId boundId)
{
if (boundId == InvalidBoundId)
{
@@ -25,8 +24,7 @@ namespace AzToolsFramework
boundId = m_nextBoundId++;
}
if (auto result = m_boundIdToShapeMap.find(boundId);
result == m_boundIdToShapeMap.end())
if (auto result = m_boundIdToShapeMap.find(boundId); result == m_boundIdToShapeMap.end())
{
if (AZStd::shared_ptr<BoundShapeInterface> createdShape = CreateShape(shapeData, boundId))
{
@@ -49,19 +47,16 @@ namespace AzToolsFramework
void ManipulatorBoundManager::UnregisterBound(const RegisteredBoundId boundId)
{
if (const auto findIter = m_boundIdToShapeMap.find(boundId);
findIter != m_boundIdToShapeMap.end())
if (const auto findIter = m_boundIdToShapeMap.find(boundId); findIter != m_boundIdToShapeMap.end())
{
DeleteShape(findIter->second.get());
m_boundIdToShapeMap.erase(findIter);
}
}
void ManipulatorBoundManager::SetBoundValidity(
const RegisteredBoundId boundId, const bool valid)
void ManipulatorBoundManager::SetBoundValidity(const RegisteredBoundId boundId, const bool valid)
{
if (auto found = m_boundIdToShapeMap.find(boundId);
found != m_boundIdToShapeMap.end())
if (auto found = m_boundIdToShapeMap.find(boundId); found != m_boundIdToShapeMap.end())
{
found->second->SetValidity(valid);
}
@@ -104,9 +99,9 @@ namespace AzToolsFramework
const auto hitItr = AZStd::lower_bound(
rayHits.begin(), rayHits.end(), BoundIdHitDistance(0, t),
[](const BoundIdHitDistance& lhs, const BoundIdHitDistance& rhs)
{
return lhs.second < rhs.second;
});
{
return lhs.second < rhs.second;
});
rayHits.insert(hitItr, AZStd::make_pair(bound->GetBoundId(), t));
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -21,10 +21,8 @@ namespace AzToolsFramework
{
class BoundShapeInterface;
/**
* Handle creating, destroying and storing all active manipulator
* bounds for performing raycasts/picking against.
*/
//! Handle creating, destroying and storing all active manipulator
//! bounds for performing raycasts/picking against.
class ManipulatorBoundManager
{
public:
@@ -35,21 +33,19 @@ namespace AzToolsFramework
ManipulatorBoundManager& operator=(const ManipulatorBoundManager&) = delete;
~ManipulatorBoundManager() = default;
RegisteredBoundId UpdateOrRegisterBound(
const BoundRequestShapeBase& shapeData, RegisteredBoundId id);
RegisteredBoundId UpdateOrRegisterBound(const BoundRequestShapeBase& shapeData, RegisteredBoundId id);
void UnregisterBound(RegisteredBoundId boundId);
void SetBoundValidity(RegisteredBoundId boundId, bool valid);
void RaySelect(RaySelectInfo &rayInfo);
void RaySelect(RaySelectInfo& rayInfo);
private:
AZStd::shared_ptr<BoundShapeInterface> CreateShape(
const BoundRequestShapeBase& ptrShape, RegisteredBoundId id);
AZStd::shared_ptr<BoundShapeInterface> CreateShape(const BoundRequestShapeBase& ptrShape, RegisteredBoundId id);
void DeleteShape(const BoundShapeInterface* boundShape);
AZStd::unordered_map<RegisteredBoundId, AZStd::shared_ptr<BoundShapeInterface>> m_boundIdToShapeMap;
AZStd::vector<AZStd::shared_ptr<BoundShapeInterface>> m_bounds; ///< All current manipulator bounds.
AZStd::vector<AZStd::shared_ptr<BoundShapeInterface>> m_bounds; //!< All current manipulator bounds.
RegisteredBoundId m_nextBoundId = RegisteredBoundId(1); ///< Next bound id to use when a bound is registered.
RegisteredBoundId m_nextBoundId = RegisteredBoundId(1); //!< Next bound id to use when a bound is registered.
};
} // namespace Picking
} // namespace AzToolsFramework
@@ -1,17 +1,18 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Math/IntersectSegment.h>
#include <AzCore/Math/Spline.h>
#include <AzCore/std/limits.h>
#include <AzToolsFramework/Picking/ContextBoundAPI.h>
#include <AzToolsFramework/Picking/Manipulators/ManipulatorBounds.h>
@@ -23,8 +24,7 @@ namespace AzToolsFramework
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
{
float vecRayIntersectionDistance;
if (AZ::Intersect::IntersectRaySphere(
rayOrigin, rayDirection, m_center, m_radius, vecRayIntersectionDistance) > 0)
if (AZ::Intersect::IntersectRaySphere(rayOrigin, rayDirection, m_center, m_radius, vecRayIntersectionDistance) > 0)
{
rayIntersectionDistance = vecRayIntersectionDistance;
return true;
@@ -45,8 +45,9 @@ namespace AzToolsFramework
bool ManipulatorBoundBox::IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
{
return AZ::Intersect::IntersectRayBox(rayOrigin, rayDirection, m_center, m_axis1, m_axis2, m_axis3,
m_halfExtents.GetX(), m_halfExtents.GetY(), m_halfExtents.GetZ(), rayIntersectionDistance) > 0;
return AZ::Intersect::IntersectRayBox(
rayOrigin, rayDirection, m_center, m_axis1, m_axis2, m_axis3, m_halfExtents.GetX(), m_halfExtents.GetY(),
m_halfExtents.GetZ(), rayIntersectionDistance) > 0;
}
void ManipulatorBoundBox::SetShapeData(const BoundRequestShapeBase& shapeData)
@@ -66,8 +67,7 @@ namespace AzToolsFramework
{
float t1 = std::numeric_limits<float>::max();
float t2 = std::numeric_limits<float>::max();
if (AZ::Intersect::IntersectRayCappedCylinder(
rayOrigin, rayDirection, m_base, m_axis, m_height, m_radius, t1, t2) > 0)
if (AZ::Intersect::IntersectRayCappedCylinder(rayOrigin, rayDirection, m_base, m_axis, m_height, m_radius, t1, t2) > 0)
{
rayIntersectionDistance = AZStd::GetMin(t1, t2);
return true;
@@ -92,8 +92,7 @@ namespace AzToolsFramework
{
float t1 = std::numeric_limits<float>::max();
float t2 = std::numeric_limits<float>::max();
if (AZ::Intersect::IntersectRayCone(
rayOrigin, rayDirection, m_apexPosition, m_dir, m_height, m_radius, t1, t2) > 0)
if (AZ::Intersect::IntersectRayCone(rayOrigin, rayDirection, m_apexPosition, m_dir, m_height, m_radius, t1, t2) > 0)
{
rayIntersectionDistance = AZStd::GetMin(t1, t2);
return true;
@@ -117,7 +116,7 @@ namespace AzToolsFramework
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
{
return AZ::Intersect::IntersectRayQuad(
rayOrigin, rayDirection, m_corner1, m_corner2, m_corner3, m_corner4, rayIntersectionDistance) > 0;
rayOrigin, rayDirection, m_corner1, m_corner2, m_corner3, m_corner4, rayIntersectionDistance) > 0;
}
void ManipulatorBoundQuad::SetShapeData(const BoundRequestShapeBase& shapeData)
@@ -157,8 +156,7 @@ namespace AzToolsFramework
float rayProportion, lineSegmentProportion;
// note: here out param is proportion/percentage of line
AZ::Intersect::ClosestSegmentSegment(
rayOrigin, rayOrigin + rayDirection * rayLength,
m_worldStart, m_worldEnd, rayProportion, lineSegmentProportion,
rayOrigin, rayOrigin + rayDirection * rayLength, m_worldStart, m_worldEnd, rayProportion, lineSegmentProportion,
closestPosRay, closestPosLineSegment);
float distanceFromLine = (closestPosRay - closestPosLineSegment).GetLength();
@@ -188,8 +186,7 @@ namespace AzToolsFramework
{
if (const AZStd::shared_ptr<const AZ::Spline> spline = m_spline.lock())
{
AZ::RaySplineQueryResult splineQueryResult =
AZ::IntersectSpline(m_transform, rayOrigin, rayDirection, *spline);
AZ::RaySplineQueryResult splineQueryResult = AZ::IntersectSpline(m_transform, rayOrigin, rayDirection, *spline);
if (splineQueryResult.m_distanceSq <= m_width * m_width)
{
@@ -214,22 +211,25 @@ namespace AzToolsFramework
}
bool IntersectHollowCylinder(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection,
const AZ::Vector3& center, const AZ::Vector3& axis,
const float minorRadius, const float majorRadius,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const AZ::Vector3& center,
const AZ::Vector3& axis,
const float minorRadius,
const float majorRadius,
float& rayIntersectionDistance)
{
float t1 = std::numeric_limits<float>::max();
float t2 = std::numeric_limits<float>::max();
float t1 = AZStd::numeric_limits<float>::max();
float t2 = AZStd::numeric_limits<float>::max();
const AZ::Vector3 base = center - axis * minorRadius;
if (AZ::Intersect::IntersectRayCappedCylinder(
rayOrigin, rayDirection, base, axis, minorRadius * 2.0f, majorRadius + minorRadius, t1, t2) > 0)
rayOrigin, rayDirection, base, axis, minorRadius * 2.0f, majorRadius + minorRadius, t1, t2) > 0)
{
const float thresholdSq = powf(majorRadius - minorRadius, 2.0f);
const float threshold = majorRadius - minorRadius;
const float thresholdSq = threshold * threshold;
// util lambda used for distance checks at both 't' values
const auto validHolowCylinderHit =
[&rayOrigin, &rayDirection, &center, thresholdSq](const float t)
const auto validHolowCylinderHit = [&rayOrigin, &rayDirection, &center, thresholdSq](const float t)
{
// only return a valid intersection if the hit was
// not in the 'hollow' part of the cylinder
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -27,36 +27,36 @@ namespace AzToolsFramework
{
namespace Picking
{
class ManipulatorBoundSphere
: public BoundShapeInterface
class ManipulatorBoundSphere : public BoundShapeInterface
{
public:
AZ_RTTI(ManipulatorBoundSphere, "{64D1B863-F574-4B31-A4F2-C9744D8567B3}", BoundShapeInterface);
AZ_CLASS_ALLOCATOR(ManipulatorBoundSphere, AZ::SystemAllocator, 0);
explicit ManipulatorBoundSphere(RegisteredBoundId boundId)
: BoundShapeInterface(boundId) {}
: BoundShapeInterface(boundId)
{
}
bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
void SetShapeData(const BoundRequestShapeBase& shapeData) override;
AZ::Vector3 m_center = AZ::Vector3::CreateZero();
float m_radius = 0.0f;
};
class ManipulatorBoundBox
: public BoundShapeInterface
class ManipulatorBoundBox : public BoundShapeInterface
{
public:
AZ_RTTI(ManipulatorBoundBox, "{3AD46067-933F-49B4-82E1-DBF12C7BC02E}", BoundShapeInterface);
AZ_CLASS_ALLOCATOR(ManipulatorBoundBox, AZ::SystemAllocator, 0);
explicit ManipulatorBoundBox(RegisteredBoundId boundId)
: BoundShapeInterface(boundId) {}
: BoundShapeInterface(boundId)
{
}
bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
void SetShapeData(const BoundRequestShapeBase& shapeData) override;
AZ::Vector3 m_center = AZ::Vector3::CreateZero();
@@ -66,38 +66,38 @@ namespace AzToolsFramework
AZ::Vector3 m_halfExtents = AZ::Vector3::CreateZero();
};
class ManipulatorBoundCylinder
: public BoundShapeInterface
class ManipulatorBoundCylinder : public BoundShapeInterface
{
public:
AZ_RTTI(ManipulatorBoundCylinder, "{D248F9E4-22E6-41A8-898D-704DF307B533}", BoundShapeInterface);
AZ_CLASS_ALLOCATOR(ManipulatorBoundCylinder, AZ::SystemAllocator, 0);
explicit ManipulatorBoundCylinder(RegisteredBoundId boundId)
: BoundShapeInterface(boundId) {}
: BoundShapeInterface(boundId)
{
}
bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
void SetShapeData(const BoundRequestShapeBase& shapeData) override;
AZ::Vector3 m_base = AZ::Vector3::CreateZero(); ///< The center of the circle at the base of the cylinder.
AZ::Vector3 m_base = AZ::Vector3::CreateZero(); //!< The center of the circle at the base of the cylinder.
AZ::Vector3 m_axis = AZ::Vector3::CreateZero();
float m_height = 0.0f;
float m_radius = 0.0f;
};
class ManipulatorBoundCone
: public BoundShapeInterface
class ManipulatorBoundCone : public BoundShapeInterface
{
public:
AZ_RTTI(ManipulatorBoundCone, "{9430440D-DFF2-4A60-9073-507C4E9DD65D}", BoundShapeInterface);
AZ_CLASS_ALLOCATOR(ManipulatorBoundCone, AZ::SystemAllocator, 0);
explicit ManipulatorBoundCone(RegisteredBoundId boundId)
: BoundShapeInterface(boundId) {}
: BoundShapeInterface(boundId)
{
}
bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
void SetShapeData(const BoundRequestShapeBase& shapeData) override;
AZ::Vector3 m_apexPosition = AZ::Vector3::CreateZero();
@@ -106,23 +106,21 @@ namespace AzToolsFramework
float m_height = 0.0f;
};
/**
* The quad shape consists of 4 points in 3D space. Please set them from \ref m_corner1 to \ref m_corner4
* in either clock-wise winding or counter clock-wise winding. In another word, \ref m_corner1 and
* \ref corner_2 cannot be diagonal corners.
*/
class ManipulatorBoundQuad
: public BoundShapeInterface
//! The quad shape consists of 4 points in 3D space. Please set them from \ref m_corner1 to \ref m_corner4
//! in either clock-wise winding or counter clock-wise winding. In another word, \ref m_corner1 and
//! \ref corner_2 cannot be diagonal corners.
class ManipulatorBoundQuad : public BoundShapeInterface
{
public:
AZ_RTTI(ManipulatorBoundQuad, "{3CDED61C-5786-4299-B5F2-5970DE4457AD}", BoundShapeInterface);
AZ_CLASS_ALLOCATOR(ManipulatorBoundQuad, AZ::SystemAllocator, 0);
explicit ManipulatorBoundQuad(RegisteredBoundId boundId)
: BoundShapeInterface(boundId) {}
: BoundShapeInterface(boundId)
{
}
bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
void SetShapeData(const BoundRequestShapeBase& shapeData) override;
AZ::Vector3 m_corner1 = AZ::Vector3::CreateZero();
@@ -131,18 +129,18 @@ namespace AzToolsFramework
AZ::Vector3 m_corner4 = AZ::Vector3::CreateZero();
};
class ManipulatorBoundTorus
: public BoundShapeInterface
class ManipulatorBoundTorus : public BoundShapeInterface
{
public:
AZ_RTTI(ManipulatorBoundTorus, "{46E4711C-178A-4F97-BC14-A048D096E7A1}", BoundShapeInterface);
AZ_CLASS_ALLOCATOR(ManipulatorBoundTorus, AZ::SystemAllocator, 0);
explicit ManipulatorBoundTorus(RegisteredBoundId boundId)
: BoundShapeInterface(boundId) {}
: BoundShapeInterface(boundId)
{
}
bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
void SetShapeData(const BoundRequestShapeBase& shapeData) override;
// Approximate a torus as a thin cylinder. A ray intersects a torus when the ray and the torus'
@@ -150,22 +148,22 @@ namespace AzToolsFramework
// center of the torus.
AZ::Vector3 m_center = AZ::Vector3::CreateZero();
AZ::Vector3 m_axis = AZ::Vector3::CreateZero();
float m_majorRadius = 0.0f; ///< Usually denoted as "R", the distance from the center of the tube to the center of the torus.
float m_minorRadius = 0.0f; ///< Usually denoted as "r", the radius of the tube.
float m_majorRadius = 0.0f; //!< Usually denoted as "R", the distance from the center of the tube to the center of the torus.
float m_minorRadius = 0.0f; //!< Usually denoted as "r", the radius of the tube.
};
class ManipulatorBoundLineSegment
: public BoundShapeInterface
class ManipulatorBoundLineSegment : public BoundShapeInterface
{
public:
AZ_RTTI(ManipulatorBoundLineSegment, "{66801554-1C1A-4E79-B1E7-342DFA779D53}", BoundShapeInterface);
AZ_CLASS_ALLOCATOR(ManipulatorBoundLineSegment, AZ::SystemAllocator, 0);
explicit ManipulatorBoundLineSegment(RegisteredBoundId boundId)
: BoundShapeInterface(boundId) {}
: BoundShapeInterface(boundId)
{
}
bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
void SetShapeData(const BoundRequestShapeBase& shapeData) override;
AZ::Vector3 m_worldStart = AZ::Vector3::CreateZero();
@@ -173,18 +171,18 @@ namespace AzToolsFramework
float m_width = 0.0f;
};
class ManipulatorBoundSpline
: public BoundShapeInterface
class ManipulatorBoundSpline : public BoundShapeInterface
{
public:
AZ_RTTI(ManipulatorBoundSpline, "{777760FF-8547-45AD-876F-16BA4D9D0584}", BoundShapeInterface);
AZ_CLASS_ALLOCATOR(ManipulatorBoundSpline, AZ::SystemAllocator, 0);
explicit ManipulatorBoundSpline(RegisteredBoundId boundId)
: BoundShapeInterface(boundId) {}
: BoundShapeInterface(boundId)
{
}
bool IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
bool IntersectRay(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDir, float& rayIntersectionDistance) override;
void SetShapeData(const BoundRequestShapeBase& shapeData) override;
AZStd::weak_ptr<const AZ::Spline> m_spline;
@@ -192,11 +190,14 @@ namespace AzToolsFramework
float m_width = 0.0f;
};
/// Approximate intersection with a torus-like shape.
//! Approximate intersection with a torus-like shape.
bool IntersectHollowCylinder(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection,
const AZ::Vector3& center, const AZ::Vector3& axis,
float minorRadius, float majorRadius,
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const AZ::Vector3& center,
const AZ::Vector3& axis,
float minorRadius,
float majorRadius,
float& rayIntersectionDistance);
} // namespace Picking
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorContextMenu.h"
@@ -16,8 +16,7 @@
namespace AzToolsFramework
{
void EditorContextMenuUpdate(
EditorContextMenu& contextMenu, const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
void EditorContextMenuUpdate(EditorContextMenu& contextMenu, const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -26,18 +25,17 @@ namespace AzToolsFramework
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
{
contextMenu.m_shouldOpen = true;
contextMenu.m_clickPoint = ViewportInteraction::QPointFromScreenPoint(
mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
contextMenu.m_clickPoint =
ViewportInteraction::QPointFromScreenPoint(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
}
// disable shouldOpen if right clicking an moving the mouse
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Move)
{
const QPoint currentScreenCoords = ViewportInteraction::QPointFromScreenPoint(
mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
const QPoint currentScreenCoords =
ViewportInteraction::QPointFromScreenPoint(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
contextMenu.m_shouldOpen = contextMenu.m_shouldOpen &&
(currentScreenCoords - contextMenu.m_clickPoint).manhattanLength() < 2;
contextMenu.m_shouldOpen = contextMenu.m_shouldOpen && (currentScreenCoords - contextMenu.m_clickPoint).manhattanLength() < 2;
}
// do show the context menu
@@ -58,16 +56,16 @@ namespace AzToolsFramework
// Populate global context menu.
const int contextMenuFlag = 0;
EditorEvents::Bus::BroadcastReverse(
&EditorEvents::PopulateEditorGlobalContextMenu,
contextMenu.m_menu.data(), AzFramework::Vector2FromScreenPoint(
mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates),
&EditorEvents::PopulateEditorGlobalContextMenu, contextMenu.m_menu.data(),
AzFramework::Vector2FromScreenPoint(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates),
contextMenuFlag);
if (!contextMenu.m_menu->isEmpty())
{
contextMenu.m_menu->exec(QCursor::pos());
// Use popup instead of exec; this avoids blocking input event processing while the menu dialog is active
contextMenu.m_menu->popup(QCursor::pos());
}
}
}
}
}
} // namespace AzToolsFramework
@@ -1,22 +1,22 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <QMenu>
#include <QPoint>
#include <QPointer>
#include <QMenu>
namespace AzToolsFramework
{
@@ -25,7 +25,7 @@ namespace AzToolsFramework
struct MouseInteractionEvent;
}
/// State of when and where the right-click context menu should appear.
//! State of when and where the right-click context menu should appear.
struct EditorContextMenu final
{
bool m_shouldOpen = false;
@@ -33,8 +33,6 @@ namespace AzToolsFramework
QPointer<QMenu> m_menu;
};
/// Update to run for context menu (when should it appear/disappear etc).
void EditorContextMenuUpdate(
EditorContextMenu& contextMenu,
const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
//! Update to run for context menu (when should it appear/disappear etc).
void EditorContextMenuUpdate(EditorContextMenu& contextMenu, const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "VertexContainerDisplay.h"
@@ -23,8 +23,7 @@ namespace AzToolsFramework
const AZ::Vector3 DefaultVertexTextOffset = AZ::Vector3(0.0f, 0.0f, -0.1f);
void DisplayVertexContainerIndex(
AzFramework::DebugDisplayRequests& debugDisplay,
const AZ::Vector3& position, const size_t index, const float textSize)
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position, const size_t index, const float textSize)
{
AZStd::string indexFormat = AZStd::string::format("[%zu]", index);
debugDisplay.DrawTextLabel(position, textSize, indexFormat.c_str(), true);
@@ -36,7 +35,8 @@ namespace AzToolsFramework
const AZ::FixedVertices<Vertex>& vertices,
const AZ::Transform& transform,
const AZ::Vector3& nonUniformScale,
const bool selected, const float textSize,
const bool selected,
const float textSize,
const AZ::Color& textColor,
const AZ::Vector3& textOffset)
{
@@ -52,11 +52,12 @@ namespace AzToolsFramework
if (vertices.GetVertex(vertIndex, vertex))
{
DisplayVertexContainerIndex(
debugDisplay, transform.TransformPoint(nonUniformScale * (AdaptVertexOut(vertex) + textOffset)), vertIndex, textSize);
debugDisplay, transform.TransformPoint(nonUniformScale * (AdaptVertexOut(vertex) + textOffset)), vertIndex,
textSize);
}
}
}
}
} // namespace VertexContainerDisplay
// explicit template instantiations
template void VertexContainerDisplay::DisplayVertexContainerIndices(
@@ -64,7 +65,8 @@ namespace AzToolsFramework
const AZ::FixedVertices<AZ::Vector2>& vertices,
const AZ::Transform& transform,
const AZ::Vector3& nonUniformScale,
bool selected, float textSize,
bool selected,
float textSize,
const AZ::Color& textColor,
const AZ::Vector3& textOffset);
template void VertexContainerDisplay::DisplayVertexContainerIndices(
@@ -72,7 +74,8 @@ namespace AzToolsFramework
const AZ::FixedVertices<AZ::Vector3>& vertices,
const AZ::Transform& transform,
const AZ::Vector3& nonUniformScale,
bool selected, float textSize,
bool selected,
float textSize,
const AZ::Color& textColor,
const AZ::Vector3& textOffset);
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -22,22 +22,23 @@ namespace AzFramework
namespace AzToolsFramework
{
/// Utility functions for rendering vertex container indices.
//! Utility functions for rendering vertex container indices.
namespace VertexContainerDisplay
{
extern const float DefaultVertexTextSize;
extern const AZ::Color DefaultVertexTextColor;
extern const AZ::Vector3 DefaultVertexTextOffset;
/// Displays all vertex container indices as text at the position of each vertex when selected
//! Displays all vertex container indices as text at the position of each vertex when selected
template<typename Vertex>
void DisplayVertexContainerIndices(
AzFramework::DebugDisplayRequests& debugDisplay,
const AZ::FixedVertices<Vertex>& vertices,
const AZ::Transform& transform,
const AZ::Vector3& nonUniformScale,
bool selected, float textSize = DefaultVertexTextSize,
bool selected,
float textSize = DefaultVertexTextSize,
const AZ::Color& textColor = DefaultVertexTextColor,
const AZ::Vector3& textOffset = DefaultVertexTextOffset);
}
} // namespace VertexContainerDisplay
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -17,8 +17,8 @@
#include <AzFramework/Entity/EntityContextBus.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Viewport/ViewportId.h>
#include <AzFramework/Viewport/ClickDetector.h>
#include <AzFramework/Viewport/ViewportId.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
@@ -31,45 +31,51 @@ namespace AzToolsFramework
{
namespace ViewportInteraction
{
/// Result of handling mouse interaction.
//! Result of handling mouse interaction.
enum class MouseInteractionResult
{
Manipulator, ///< The manipulator manager handled the interaction.
Viewport, ///< The viewport handled the interaction.
None ///< The interaction was not handled.
Manipulator, //!< The manipulator manager handled the interaction.
Viewport, //!< The viewport handled the interaction.
None //!< The interaction was not handled.
};
/// Interface for handling mouse viewport events.
//! Interface for handling mouse viewport events.
class MouseViewportRequests
{
public:
/// @cond
//! @cond
virtual ~MouseViewportRequests() = default;
/// @endcond
//! @endcond
/// Implement this function to handle a particular mouse event.
virtual bool HandleMouseInteraction(
const MouseInteractionEvent& /*mouseInteraction*/) { return false; }
//! Implement this function to handle a particular mouse event.
virtual bool HandleMouseInteraction(const MouseInteractionEvent& /*mouseInteraction*/)
{
return false;
}
};
/// Interface for internal handling mouse viewport events.
//! Interface for internal handling mouse viewport events.
class InternalMouseViewportRequests
{
public:
/// @cond
//! @cond
virtual ~InternalMouseViewportRequests() = default;
/// @endcond
//! @endcond
/// Implement this function to have the viewport handle this mouse event.
virtual bool InternalHandleMouseViewportInteraction(
const MouseInteractionEvent& /*mouseInteraction*/) { return false; }
//! Implement this function to have the viewport handle this mouse event.
virtual bool InternalHandleMouseViewportInteraction(const MouseInteractionEvent& /*mouseInteraction*/)
{
return false;
}
/// Implement this function to have manipulators handle this mouse event.
virtual bool InternalHandleMouseManipulatorInteraction(
const MouseInteractionEvent& /*mouseInteraction*/) { return false; }
//! Implement this function to have manipulators handle this mouse event.
virtual bool InternalHandleMouseManipulatorInteraction(const MouseInteractionEvent& /*mouseInteraction*/)
{
return false;
}
/// Helper to call both viewport and manipulator handle mouse events
/// @note Manipulators always attempt to intercept the event first.
//! Helper to call both viewport and manipulator handle mouse events
//! @note Manipulators always attempt to intercept the event first.
MouseInteractionResult InternalHandleAllMouseInteractions(const MouseInteractionEvent& mouseInteraction);
};
@@ -90,117 +96,118 @@ namespace AzToolsFramework
}
}
/// Interface for viewport selection behaviors.
//! Interface for viewport selection behaviors.
class ViewportDisplayNotifications
{
public:
/// @cond
//! @cond
virtual ~ViewportDisplayNotifications() = default;
/// @endcond
//! @endcond
/// Display drawing in world space.
/// \ref DisplayViewportSelection is called from \ref EditorInteractionSystemComponent::DisplayViewport.
/// DisplayViewport exists on the \ref AzFramework::ViewportDebugDisplayEventBus and is called from \ref CRenderViewport.
/// \ref DisplayViewportSelection is called after \ref CalculateVisibleEntityDatas on the \ref EditorVisibleEntityDataCache,
/// this ensures usage of the entity cache will be up to date (do not implement \ref AzFramework::ViewportDebugDisplayEventBus
/// directly if wishing to use the \ref EditorVisibleEntityDataCache).
//! Display drawing in world space.
//! \ref DisplayViewportSelection is called from \ref EditorInteractionSystemComponent::DisplayViewport.
//! DisplayViewport exists on the \ref AzFramework::ViewportDebugDisplayEventBus and is called from \ref CRenderViewport.
//! \ref DisplayViewportSelection is called after \ref CalculateVisibleEntityDatas on the \ref EditorVisibleEntityDataCache,
//! this ensures usage of the entity cache will be up to date (do not implement \ref AzFramework::ViewportDebugDisplayEventBus
//! directly if wishing to use the \ref EditorVisibleEntityDataCache).
virtual void DisplayViewportSelection(
const AzFramework::ViewportInfo& /*viewportInfo*/,
AzFramework::DebugDisplayRequests& /*debugDisplay*/) {}
/// Display drawing in screen space.
/// \ref DisplayViewportSelection2d is called after \ref DisplayViewportSelection when the viewport has been
/// configured to be orthographic in \ref CRenderViewport. All screen space drawing can be performed here.
const AzFramework::ViewportInfo& /*viewportInfo*/, AzFramework::DebugDisplayRequests& /*debugDisplay*/)
{
}
//! Display drawing in screen space.
//! \ref DisplayViewportSelection2d is called after \ref DisplayViewportSelection when the viewport has been
//! configured to be orthographic in \ref CRenderViewport. All screen space drawing can be performed here.
virtual void DisplayViewportSelection2d(
const AzFramework::ViewportInfo& /*viewportInfo*/,
AzFramework::DebugDisplayRequests& /*debugDisplay*/) {}
const AzFramework::ViewportInfo& /*viewportInfo*/, AzFramework::DebugDisplayRequests& /*debugDisplay*/)
{
}
};
/// Interface for internal handling mouse viewport events and display notifications.
/// Implement this for types wishing to provide viewport functionality and
/// set it by using \ref EditorInteractionSystemViewportSelectionRequestBus.
//! Interface for internal handling mouse viewport events and display notifications.
//! Implement this for types wishing to provide viewport functionality and
//! set it by using \ref EditorInteractionSystemViewportSelectionRequestBus.
class InternalViewportSelectionRequests
: public ViewportDisplayNotifications
, public InternalMouseViewportRequests
{
};
/// Interface for handling mouse viewport events and display notifications.
/// Use this interface for composition types used by InternalViewportSelectionRequests.
//! Interface for handling mouse viewport events and display notifications.
//! Use this interface for composition types used by InternalViewportSelectionRequests.
class ViewportSelectionRequests
: public ViewportDisplayNotifications
, public MouseViewportRequests
{
};
/// The EBusTraits for ViewportInteractionRequests.
class ViewportEBusTraits
: public AZ::EBusTraits
//! The EBusTraits for ViewportInteractionRequests.
class ViewportEBusTraits : public AZ::EBusTraits
{
public:
using BusIdType = AzFramework::ViewportId; ///< ViewportId - used to address requests to this EBus.
using BusIdType = AzFramework::ViewportId; //!< ViewportId - used to address requests to this EBus.
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
};
/// A ray projection, originating from a point and extending in a direction specified as a normal.
//! A ray projection, originating from a point and extending in a direction specified as a normal.
struct ProjectedViewportRay
{
AZ::Vector3 origin;
AZ::Vector3 direction;
};
/// Requests that can be made to the viewport to query and modify its state.
//! Requests that can be made to the viewport to query and modify its state.
class ViewportInteractionRequests
{
public:
/// Return the current camera state for this viewport.
//! Return the current camera state for this viewport.
virtual AzFramework::CameraState GetCameraState() = 0;
/// Return if grid snapping is enabled.
//! Return if grid snapping is enabled.
virtual bool GridSnappingEnabled() = 0;
/// Return the grid snapping size.
//! Return the grid snapping size.
virtual float GridSize() = 0;
/// Does the grid currently want to be displayed.
//! Does the grid currently want to be displayed.
virtual bool ShowGrid() = 0;
/// Return if angle snapping is enabled.
//! Return if angle snapping is enabled.
virtual bool AngleSnappingEnabled() = 0;
/// Return the angle snapping/step size.
//! Return the angle snapping/step size.
virtual float AngleStep() = 0;
/// Transform a point in world space to screen space coordinates in Qt Widget space.
/// Multiply by DeviceScalingFactor to get the position in viewport pixel space.
//! Transform a point in world space to screen space coordinates in Qt Widget space.
//! Multiply by DeviceScalingFactor to get the position in viewport pixel space.
virtual AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) = 0;
/// Transform a point from Qt widget screen space to world space based on the given clip space depth.
/// Depth specifies a relative camera depth to project in the range of [0.f, 1.f].
/// Returns the world space position if successful.
//! Transform a point from Qt widget screen space to world space based on the given clip space depth.
//! Depth specifies a relative camera depth to project in the range of [0.f, 1.f].
//! Returns the world space position if successful.
virtual AZStd::optional<AZ::Vector3> ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) = 0;
/// Casts a point in screen space to a ray in world space originating from the viewport camera frustum's near plane.
/// Returns a ray containing the ray's origin and a direction normal, if successful.
//! Casts a point in screen space to a ray in world space originating from the viewport camera frustum's near plane.
//! Returns a ray containing the ray's origin and a direction normal, if successful.
virtual AZStd::optional<ProjectedViewportRay> ViewportScreenToWorldRay(const AzFramework::ScreenPoint& screenPosition) = 0;
/// Gets the DPI scaling factor that translates Qt widget space into viewport pixel space.
//! Gets the DPI scaling factor that translates Qt widget space into viewport pixel space.
virtual float DeviceScalingFactor() = 0;
protected:
~ViewportInteractionRequests() = default;
};
/// Interface to return only viewport specific settings (e.g. snapping).
//! Interface to return only viewport specific settings (e.g. snapping).
class ViewportSettings
{
public:
virtual ~ViewportSettings() = default;
/// Return if grid snapping is enabled.
//! Return if grid snapping is enabled.
virtual bool GridSnappingEnabled() const = 0;
/// Return the grid snapping size.
//! Return the grid snapping size.
virtual float GridSize() const = 0;
/// Does the grid currently want to be displayed.
//! Does the grid currently want to be displayed.
virtual bool ShowGrid() const = 0;
/// Return if angle snapping is enabled.
//! Return if angle snapping is enabled.
virtual bool AngleSnappingEnabled() const = 0;
/// Return the angle snapping/step size.
//! Return the angle snapping/step size.
virtual float AngleStep() const = 0;
};
/// Type to inherit to implement ViewportInteractionRequests.
//! Type to inherit to implement ViewportInteractionRequests.
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
//! Requests to freeze the Viewport Input
@@ -221,62 +228,62 @@ namespace AzToolsFramework
//! Type to inherit to implement ViewportFreezeRequests.
using ViewportFreezeRequestBus = AZ::EBus<ViewportFreezeRequests, ViewportEBusTraits>;
/// Viewport requests that are only guaranteed to be serviced by the Main Editor viewport.
//! Viewport requests that are only guaranteed to be serviced by the Main Editor viewport.
class MainEditorViewportInteractionRequests
{
public:
/// Given a point in screen space, return the picked entity (if any).
/// Picked EntityId will be returned, InvalidEntityId will be returned on failure.
//! Given a point in screen space, return the picked entity (if any).
//! Picked EntityId will be returned, InvalidEntityId will be returned on failure.
virtual AZ::EntityId PickEntity(const AzFramework::ScreenPoint& point) = 0;
/// Given a point in screen space, return the terrain position in world space.
//! Given a point in screen space, return the terrain position in world space.
virtual AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) = 0;
/// Return the terrain height given a world position in 2d (xy plane).
//! Return the terrain height given a world position in 2d (xy plane).
virtual float TerrainHeight(const AZ::Vector2& position) = 0;
/// Given the current view frustum (viewport) return all visible entities.
//! Given the current view frustum (viewport) return all visible entities.
virtual void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) = 0;
/// Is the user holding a modifier key to move the manipulator space from local to world.
//! Is the user holding a modifier key to move the manipulator space from local to world.
virtual bool ShowingWorldSpace() = 0;
/// Return the widget to use as the parent for the viewport context menu.
//! Return the widget to use as the parent for the viewport context menu.
virtual QWidget* GetWidgetForViewportContextMenu() = 0;
/// Set the render context for the viewport.
//! Set the render context for the viewport.
virtual void BeginWidgetContext() = 0;
/// End the render context for the viewport.
/// Return to previous context before Begin was called.
//! End the render context for the viewport.
//! Return to previous context before Begin was called.
virtual void EndWidgetContext() = 0;
protected:
~MainEditorViewportInteractionRequests() = default;
};
/// Type to inherit to implement MainEditorViewportInteractionRequests.
//! Type to inherit to implement MainEditorViewportInteractionRequests.
using MainEditorViewportInteractionRequestBus = AZ::EBus<MainEditorViewportInteractionRequests, ViewportEBusTraits>;
/// Viewport requests for managing the viewport's cursor state.
//! Viewport requests for managing the viewport's cursor state.
class ViewportMouseCursorRequests
{
public:
/// Begins hiding the cursor and locking it in place, to prevent the cursor from escaping the viewport window.
//! Begins hiding the cursor and locking it in place, to prevent the cursor from escaping the viewport window.
virtual void BeginCursorCapture() = 0;
/// Restores the cursor and ends locking it in place, allowing it to be moved freely.
//! Restores the cursor and ends locking it in place, allowing it to be moved freely.
virtual void EndCursorCapture() = 0;
/// Gets the most recent recorded cursor position in the viewport in screen space coordinates.
//! Gets the most recent recorded cursor position in the viewport in screen space coordinates.
virtual AzFramework::ScreenPoint ViewportCursorScreenPosition() = 0;
/// Gets the cursor position recorded prior to the most recent cursor position.
/// Note: The cursor may be captured by the viewport, in which case this may not correspond to the last result
/// from ViewportCursorScreenPosition. This method will always return the correct position to generate a mouse
/// position delta.
//! Gets the cursor position recorded prior to the most recent cursor position.
//! Note: The cursor may be captured by the viewport, in which case this may not correspond to the last result
//! from ViewportCursorScreenPosition. This method will always return the correct position to generate a mouse
//! position delta.
virtual AZStd::optional<AzFramework::ScreenPoint> PreviousViewportCursorScreenPosition() = 0;
/// Is mouse over viewport.
//! Is mouse over viewport.
virtual bool IsMouseOver() const = 0;
protected:
~ViewportMouseCursorRequests() = default;
};
/// Type to inherit to implement MainEditorViewportInteractionRequests.
//! Type to inherit to implement MainEditorViewportInteractionRequests.
using ViewportMouseCursorRequestBus = AZ::EBus<ViewportMouseCursorRequests, ViewportEBusTraits>;
/// A helper to wrap Begin/EndWidgetContext.
//! A helper to wrap Begin/EndWidgetContext.
class WidgetContextGuard
{
public:
@@ -294,17 +301,16 @@ namespace AzToolsFramework
}
private:
int m_viewportId; ///< The viewport id the widget context is being set on.
int m_viewportId; //!< The viewport id the widget context is being set on.
};
} // namespace ViewportInteraction
/// Utility function to return EntityContextId.
//! Utility function to return EntityContextId.
inline AzFramework::EntityContextId GetEntityContextId()
{
AzFramework::EntityContextId entityContextId;
EditorEntityContextRequestBus::BroadcastResult(
entityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
EditorEntityContextRequestBus::BroadcastResult(entityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
return entityContextId;
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ViewportTypes.h"
@@ -23,26 +23,24 @@ namespace AzToolsFramework
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<KeyboardModifiers>()->
Field("KeyboardModifiers", &KeyboardModifiers::m_keyModifiers);
serializeContext->Class<KeyboardModifiers>()->Field("KeyboardModifiers", &KeyboardModifiers::m_keyModifiers);
serializeContext->Class<MouseButtons>()->
Field("MouseButtons", &MouseButtons::m_mouseButtons);
serializeContext->Class<MouseButtons>()->Field("MouseButtons", &MouseButtons::m_mouseButtons);
serializeContext->Class<InteractionId>()->
Field("CameraId", &InteractionId::m_cameraId)->
Field("ViewportId", &InteractionId::m_viewportId);
serializeContext->Class<InteractionId>()
->Field("CameraId", &InteractionId::m_cameraId)
->Field("ViewportId", &InteractionId::m_viewportId);
serializeContext->Class<MousePick>()->
Field("RayOrigin", &MousePick::m_rayOrigin)->
Field("RayDirection", &MousePick::m_rayDirection)->
Field("ScreenCoordinates", &MousePick::m_screenCoordinates);
serializeContext->Class<MousePick>()
->Field("RayOrigin", &MousePick::m_rayOrigin)
->Field("RayDirection", &MousePick::m_rayDirection)
->Field("ScreenCoordinates", &MousePick::m_screenCoordinates);
serializeContext->Class<MouseInteraction>()->
Field("MousePick", &MouseInteraction::m_mousePick)->
Field("MouseButtons", &MouseInteraction::m_mouseButtons)->
Field("InteractionId", &MouseInteraction::m_interactionId)->
Field("KeyboardModifiers", &MouseInteraction::m_keyboardModifiers);
serializeContext->Class<MouseInteraction>()
->Field("MousePick", &MouseInteraction::m_mousePick)
->Field("MouseButtons", &MouseInteraction::m_mouseButtons)
->Field("InteractionId", &MouseInteraction::m_interactionId)
->Field("KeyboardModifiers", &MouseInteraction::m_keyboardModifiers);
MouseInteractionEvent::Reflect(*serializeContext);
}
@@ -50,10 +48,10 @@ namespace AzToolsFramework
void MouseInteractionEvent::Reflect(AZ::SerializeContext& serializeContext)
{
serializeContext.Class<MouseInteractionEvent>()->
Field("MouseInteraction", &MouseInteractionEvent::m_mouseInteraction)->
Field("MouseEvent", &MouseInteractionEvent::m_mouseEvent)->
Field("WheelDelta", &MouseInteractionEvent::m_wheelDelta);
serializeContext.Class<MouseInteractionEvent>()
->Field("MouseInteraction", &MouseInteractionEvent::m_mouseInteraction)
->Field("MouseEvent", &MouseInteractionEvent::m_mouseEvent)
->Field("WheelDelta", &MouseInteractionEvent::m_wheelDelta);
}
}
}
} // namespace ViewportInteraction
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -27,57 +27,75 @@ namespace AZ
namespace AzToolsFramework
{
/// Viewport related types that are used when interacting with the viewport.
//! Viewport related types that are used when interacting with the viewport.
namespace ViewportInteraction
{
/// Flags to represent each modifier key.
//! Flags to represent each modifier key.
enum class KeyboardModifier : AZ::u32
{
None = 0, ///< No keyboard modifier.
Alt = 0x01, ///< Alt keyboard modifier.
Shift = 0x02, ///< Shift keyboard modifier.
Ctrl = 0x04, ///< Ctrl keyboard modifier.
Control = Ctrl ///< Alias for Ctrl modifier.
None = 0, //!< No keyboard modifier.
Alt = 0x01, //!< Alt keyboard modifier.
Shift = 0x02, //!< Shift keyboard modifier.
Ctrl = 0x04, //!< Ctrl keyboard modifier.
Control = Ctrl //!< Alias for Ctrl modifier.
};
/// Flags to represent each mouse button.
//! Flags to represent each mouse button.
enum class MouseButton : AZ::u32
{
None = 0, ///< No mouse buttons.
Left = 0x01, ///< Left mouse button.
Middle = 0x02, ///< Middle mouse button.
Right = 0x04 ///< Right mouse button.
None = 0, //!< No mouse buttons.
Left = 0x01, //!< Left mouse button.
Middle = 0x02, //!< Middle mouse button.
Right = 0x04 //!< Right mouse button.
};
/// The type of mouse event that occurred.
//! The type of mouse event that occurred.
enum class MouseEvent
{
Up, ///< Mouse up event,
Down, ///< Mouse down event.
DoubleClick, ///< Mouse double click event.
Wheel, ///< Mouse wheel event.
Move, ///< Mouse move event.
Up, //!< Mouse up event,
Down, //!< Mouse down event.
DoubleClick, //!< Mouse double click event.
Wheel, //!< Mouse wheel event.
Move, //!< Mouse move event.
};
/// Interface over keyboard modifier to query which key is pressed.
//! Interface over keyboard modifier to query which key is pressed.
struct KeyboardModifiers
{
/// @cond
//! @cond
AZ_TYPE_INFO(KeyboardModifiers, "{2635F4DF-E7DC-4919-A97B-9AE35FE086D8}");
KeyboardModifiers() = default;
/// @endcond
//! @endcond
/// Explicit constructor to create a KeyboardModifier struct.
explicit KeyboardModifiers(const AZ::u32 keyModifiers) : m_keyModifiers(keyModifiers) {}
//! Explicit constructor to create a KeyboardModifier struct.
explicit KeyboardModifiers(const AZ::u32 keyModifiers)
: m_keyModifiers(keyModifiers)
{
}
/// Given the current keyboard modifiers, is the Alt key held.
bool Alt() const { return (m_keyModifiers & static_cast<AZ::u32>(KeyboardModifier::Alt)) != 0; }
/// Given the current keyboard modifiers, is the Shift key held.
bool Shift() const { return (m_keyModifiers & static_cast<AZ::u32>(KeyboardModifier::Shift)) != 0; }
/// Given the current keyboard modifiers, is the Ctrl key held.
bool Ctrl() const { return (m_keyModifiers & static_cast<AZ::u32>(KeyboardModifier::Ctrl)) != 0; }
/// Given the current keyboard modifiers, are none being held.
bool None() const { return m_keyModifiers == static_cast<AZ::u32>(KeyboardModifier::None); }
//! Given the current keyboard modifiers, is the Alt key held.
bool Alt() const
{
return (m_keyModifiers & static_cast<AZ::u32>(KeyboardModifier::Alt)) != 0;
}
//! Given the current keyboard modifiers, is the Shift key held.
bool Shift() const
{
return (m_keyModifiers & static_cast<AZ::u32>(KeyboardModifier::Shift)) != 0;
}
//! Given the current keyboard modifiers, is the Ctrl key held.
bool Ctrl() const
{
return (m_keyModifiers & static_cast<AZ::u32>(KeyboardModifier::Ctrl)) != 0;
}
//! Given the current keyboard modifiers, are none being held.
bool None() const
{
return m_keyModifiers == static_cast<AZ::u32>(KeyboardModifier::None);
}
bool operator==(const KeyboardModifiers& keyboardModifiers) const
{
@@ -89,132 +107,162 @@ namespace AzToolsFramework
return m_keyModifiers != keyboardModifiers.m_keyModifiers;
}
AZ::u32 m_keyModifiers = 0; ///< Raw keyboard modifier state.
AZ::u32 m_keyModifiers = 0; //!< Raw keyboard modifier state.
};
/// Interface over mouse buttons to query which button is pressed.
//! Interface over mouse buttons to query which button is pressed.
struct MouseButtons
{
/// @cond
//! @cond
AZ_TYPE_INFO(MouseButtons, "{1D137B5D-73BF-4FD9-BECA-85E6DC3786CB}");
MouseButtons() = default;
/// @endcond
//! @endcond
/// Explicit constructor to create a MouseButton struct.
explicit MouseButtons(const AZ::u32 mouseButtons) : m_mouseButtons(mouseButtons) {}
//! Explicit constructor to create a MouseButton struct.
explicit MouseButtons(const AZ::u32 mouseButtons)
: m_mouseButtons(mouseButtons)
{
}
/// Given the current mouse state, is the left mouse button held.
bool Left() const { return (m_mouseButtons & static_cast<AZ::u32>(MouseButton::Left)) != 0; }
/// Given the current mouse state, is the middle mouse button held.
bool Middle() const { return (m_mouseButtons & static_cast<AZ::u32>(MouseButton::Middle)) != 0; }
/// Given the current mouse state, is the right mouse button held.
bool Right() const { return (m_mouseButtons & static_cast<AZ::u32>(MouseButton::Right)) != 0; }
/// Given the current mouse state, are no mouse buttons held.
bool None() const { return m_mouseButtons == static_cast<AZ::u32>(MouseButton::None); }
/// Given the current mouse state, are any mouse buttons held.
bool Any() const { return m_mouseButtons != static_cast<AZ::u32>(MouseButton::None); }
//! Given the current mouse state, is the left mouse button held.
bool Left() const
{
return (m_mouseButtons & static_cast<AZ::u32>(MouseButton::Left)) != 0;
}
AZ::u32 m_mouseButtons = 0; ///< Current mouse button state (flags).
//! Given the current mouse state, is the middle mouse button held.
bool Middle() const
{
return (m_mouseButtons & static_cast<AZ::u32>(MouseButton::Middle)) != 0;
}
//! Given the current mouse state, is the right mouse button held.
bool Right() const
{
return (m_mouseButtons & static_cast<AZ::u32>(MouseButton::Right)) != 0;
}
//! Given the current mouse state, are no mouse buttons held.
bool None() const
{
return m_mouseButtons == static_cast<AZ::u32>(MouseButton::None);
}
//! Given the current mouse state, are any mouse buttons held.
bool Any() const
{
return m_mouseButtons != static_cast<AZ::u32>(MouseButton::None);
}
AZ::u32 m_mouseButtons = 0; //!< Current mouse button state (flags).
};
/// Information relevant when interacting with a particular viewport.
//! Information relevant when interacting with a particular viewport.
struct InteractionId
{
/// @cond
//! @cond
AZ_TYPE_INFO(InteractionId, "{35593FC2-846F-4AAD-8044-4CD84EC84F9A}");
InteractionId() = default;
/// @endcond
//! @endcond
InteractionId(AZ::EntityId cameraId, int viewportId)
: m_cameraId(cameraId), m_viewportId(viewportId) {}
: m_cameraId(cameraId)
, m_viewportId(viewportId)
{
}
AZ::EntityId m_cameraId; ///< The entity id of the viewport camera.
int m_viewportId = 0; ///< The id of the viewport being interacted with.
AZ::EntityId m_cameraId; //!< The entity id of the viewport camera.
int m_viewportId = 0; //!< The id of the viewport being interacted with.
};
/// Data representing a mouse pick ray.
//! Data representing a mouse pick ray.
struct MousePick
{
/// @cond
//! @cond
AZ_TYPE_INFO(MousePick, "{A69B9562-FC8C-4DE7-9137-0FF867B1513D}");
MousePick() = default;
/// @endcond
//! @endcond
AZ::Vector3 m_rayOrigin = AZ::Vector3::CreateZero(); ///< World space.
AZ::Vector3 m_rayDirection = AZ::Vector3::CreateZero(); ///< World space - normalized.
AzFramework::ScreenPoint m_screenCoordinates = {}; ///< Screen space.
AZ::Vector3 m_rayOrigin = AZ::Vector3::CreateZero(); //!< World space.
AZ::Vector3 m_rayDirection = AZ::Vector3::CreateZero(); //!< World space - normalized.
AzFramework::ScreenPoint m_screenCoordinates = {}; //!< Screen space.
};
/// State relating to an individual mouse interaction.
//! State relating to an individual mouse interaction.
struct MouseInteraction
{
/// @cond
//! @cond
AZ_TYPE_INFO(MouseInteraction, "{E67357C3-DFE1-40DF-921F-9CBCFE63A68C}");
MouseInteraction() = default;
/// @endcond
//! @endcond
MousePick m_mousePick; ///< The mouse pick ray in world space and screen coordinates in screen space.
MouseButtons m_mouseButtons; ///< The current state of the mouse buttons.
MousePick m_mousePick; //!< The mouse pick ray in world space and screen coordinates in screen space.
MouseButtons m_mouseButtons; //!< The current state of the mouse buttons.
InteractionId m_interactionId; /**< The EntityId of the camera this click came from
* and the id of the viewport it originated from. */
KeyboardModifiers m_keyboardModifiers; ///< The state of the keyboard modifiers (Alt/Ctrl/Shift).
* and the id of the viewport it originated from. */
KeyboardModifiers m_keyboardModifiers; //!< The state of the keyboard modifiers (Alt/Ctrl/Shift).
};
/// Structure to compose MouseInteraction (mouse state) and
/// MouseEvent (MouseEvent::MouseUp/MouseEvent::DownMove etc.)
//! Structure to compose MouseInteraction (mouse state) and
//! MouseEvent (MouseEvent::MouseUp/MouseEvent::DownMove etc.)
struct MouseInteractionEvent
{
/// @cond
//! @cond
AZ_TYPE_INFO(MouseInteractionEvent, "{67FE0826-DD59-4B5B-BEFE-421E83EA7F31}");
MouseInteractionEvent() = default;
/// @endcond
//! @endcond
static void Reflect(AZ::SerializeContext& context);
/// Constructor to create a default MouseInteractionEvent
//! Constructor to create a default MouseInteractionEvent
MouseInteractionEvent(MouseInteraction mouseInteraction, const MouseEvent mouseEvent)
: m_mouseInteraction(std::move(mouseInteraction))
, m_mouseEvent(mouseEvent) {}
, m_mouseEvent(mouseEvent)
{
}
/// Special constructor for mouse wheel event.
//! Special constructor for mouse wheel event.
MouseInteractionEvent(MouseInteraction mouseInteraction, const float wheelDelta)
: m_mouseInteraction(std::move(mouseInteraction))
, m_mouseEvent(MouseEvent::Wheel)
, m_wheelDelta(wheelDelta) {}
, m_wheelDelta(wheelDelta)
{
}
MouseInteraction m_mouseInteraction; ///< Mouse state.
MouseEvent m_mouseEvent; ///< Mouse event.
MouseInteraction m_mouseInteraction; //!< Mouse state.
MouseEvent m_mouseEvent; //!< Mouse event.
/// Special friend function to return the mouse wheel delta (scroll amount)
/// if the event was of type MouseEvent::Wheel.
//! Special friend function to return the mouse wheel delta (scroll amount)
//! if the event was of type MouseEvent::Wheel.
friend float MouseWheelDelta(const MouseInteractionEvent& mouseInteractionEvent);
private:
float m_wheelDelta = 0.0f; ///< The amount the mouse wheel moved during a mouse wheel event.
float m_wheelDelta = 0.0f; //!< The amount the mouse wheel moved during a mouse wheel event.
};
/// Checked access to mouse wheel delta - ensure event originated from the mouse wheel.
//! Checked access to mouse wheel delta - ensure event originated from the mouse wheel.
inline float MouseWheelDelta(const MouseInteractionEvent& mouseInteractionEvent)
{
AZ_Assert(mouseInteractionEvent.m_mouseEvent == MouseEvent::Wheel,
AZ_Assert(
mouseInteractionEvent.m_mouseEvent == MouseEvent::Wheel,
"Attempting to access mouse wheel delta when mouse interaction event was not mouse wheel");
return mouseInteractionEvent.m_wheelDelta;
}
/// Return QPoint from AzFramework::ScreenPoint.
//! Return QPoint from AzFramework::ScreenPoint.
inline QPoint QPointFromScreenPoint(const AzFramework::ScreenPoint& screenPoint)
{
return {screenPoint.m_x, screenPoint.m_y};
return { screenPoint.m_x, screenPoint.m_y };
}
/// Return AzFramework::ScreenPoint from QPoint.
//! Return AzFramework::ScreenPoint from QPoint.
inline AzFramework::ScreenPoint ScreenPointFromQPoint(const QPoint& qpoint)
{
return AzFramework::ScreenPoint{qpoint.x(), qpoint.y()};
return AzFramework::ScreenPoint{ qpoint.x(), qpoint.y() };
}
/// Map from Qt -> Open 3D Engine buttons.>>>>>>> main
//! Map from Qt -> Open 3D Engine buttons.>>>>>>> main
inline AZ::u32 TranslateMouseButtons(const Qt::MouseButtons buttons)
{
AZ::u32 result = 0;
@@ -224,7 +272,7 @@ namespace AzToolsFramework
return result;
}
/// Map from Qt -> Open 3D Engine modifiers.
//! Map from Qt -> Open 3D Engine modifiers.
inline AZ::u32 TranslateKeyboardModifiers(const Qt::KeyboardModifiers modifiers)
{
AZ::u32 result = 0;
@@ -234,19 +282,19 @@ namespace AzToolsFramework
return result;
}
/// Interface to translate Qt modifiers to Open 3D Engine modifiers.
//! Interface to translate Qt modifiers to Open 3D Engine modifiers.
inline KeyboardModifiers BuildKeyboardModifiers(const Qt::KeyboardModifiers modifiers)
{
return KeyboardModifiers(TranslateKeyboardModifiers(modifiers));
}
/// Interface to translate Qt buttons to Open 3D Engine buttons.
//! Interface to translate Qt buttons to Open 3D Engine buttons.
inline MouseButtons BuildMouseButtons(const Qt::MouseButtons buttons)
{
return MouseButtons(TranslateMouseButtons(buttons));
}
/// Generate mouse buttons from single button enum.
//! Generate mouse buttons from single button enum.
inline MouseButtons MouseButtonsFromButton(MouseButton button)
{
MouseButtons mouseButtons;
@@ -254,7 +302,7 @@ namespace AzToolsFramework
return mouseButtons;
}
/// Reflect all viewport related types.
//! Reflect all viewport related types.
void ViewportInteractionReflect(AZ::ReflectContext* context);
} // namespace ViewportInteraction
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorDefaultSelection.h"
@@ -30,8 +30,7 @@ namespace AzToolsFramework
ActionOverrideRequestBus::Handler::BusConnect(GetEntityContextId());
ComponentModeFramework::ComponentModeSystemRequestBus::Handler::BusConnect();
m_manipulatorManager =
AZStd::make_shared<AzToolsFramework::ManipulatorManager>(AzToolsFramework::g_mainManipulatorManagerId);
m_manipulatorManager = AZStd::make_shared<AzToolsFramework::ManipulatorManager>(AzToolsFramework::g_mainManipulatorManagerId);
m_transformComponentSelection = AZStd::make_unique<EditorTransformComponentSelection>(entityDataCache);
}
@@ -75,23 +74,18 @@ namespace AzToolsFramework
for (const auto& componentModeBuilder : entityAndComponentModeBuilders.m_componentModeBuilders)
{
m_componentModeCollection.AddComponentMode(
AZ::EntityComponentIdPair(
entityAndComponentModeBuilders.m_entityId, componentModeBuilder.m_componentId),
componentModeBuilder.m_componentType,
componentModeBuilder.m_componentModeBuilder);
AZ::EntityComponentIdPair(entityAndComponentModeBuilders.m_entityId, componentModeBuilder.m_componentId),
componentModeBuilder.m_componentType, componentModeBuilder.m_componentModeBuilder);
}
}
void EditorDefaultSelection::TransitionToComponentMode()
{
// entering ComponentMode - disable all default actions in the ActionManager
EditorActionRequestBus::Broadcast(
&EditorActionRequests::DisableDefaultActions);
EditorActionRequestBus::Broadcast(&EditorActionRequests::DisableDefaultActions);
// attach widget to store ComponentMode specific actions
EditorActionRequestBus::Broadcast(
&EditorActionRequests::AttachOverride,
&PhantomWidget());
EditorActionRequestBus::Broadcast(&EditorActionRequests::AttachOverride, &PhantomWidget());
if (m_transformComponentSelection)
{
@@ -103,8 +97,7 @@ namespace AzToolsFramework
// refresh button ui
ToolsApplicationEvents::Bus::Broadcast(
&ToolsApplicationEvents::Bus::Events::InvalidatePropertyDisplay,
PropertyModificationRefreshLevel::Refresh_EntireTree);
&ToolsApplicationEvents::Bus::Events::InvalidatePropertyDisplay, PropertyModificationRefreshLevel::Refresh_EntireTree);
}
void EditorDefaultSelection::TransitionFromComponentMode()
@@ -117,19 +110,16 @@ namespace AzToolsFramework
m_transformComponentSelection->RegisterManipulator();
}
EditorActionRequestBus::Broadcast(
&EditorActionRequests::DetachOverride);
EditorActionRequestBus::Broadcast(&EditorActionRequests::DetachOverride);
ClearActionOverrides();
// leaving ComponentMode - enable all default actions in ActionManager
EditorActionRequestBus::Broadcast(
&EditorActionRequests::EnableDefaultActions);
EditorActionRequestBus::Broadcast(&EditorActionRequests::EnableDefaultActions);
// refresh button ui
ToolsApplicationEvents::Bus::Broadcast(
&ToolsApplicationEvents::Bus::Events::InvalidatePropertyDisplay,
PropertyModificationRefreshLevel::Refresh_EntireTree);
&ToolsApplicationEvents::Bus::Events::InvalidatePropertyDisplay, PropertyModificationRefreshLevel::Refresh_EntireTree);
}
void EditorDefaultSelection::EndComponentMode()
@@ -142,8 +132,7 @@ namespace AzToolsFramework
m_componentModeCollection.Refresh(entityComponentIdPair);
}
bool EditorDefaultSelection::AddedToComponentMode(
const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType)
bool EditorDefaultSelection::AddedToComponentMode(const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType)
{
return m_componentModeCollection.AddedToComponentMode(entityComponentIdPair, componentType);
}
@@ -152,10 +141,10 @@ namespace AzToolsFramework
{
ComponentModeFramework::ComponentModeDelegateRequestBus::EnumerateHandlers(
[componentType](ComponentModeFramework::ComponentModeDelegateRequestBus::InterfaceType* componentModeMouseRequests)
{
componentModeMouseRequests->AddComponentModeOfType(componentType);
return true;
});
{
componentModeMouseRequests->AddComponentModeOfType(componentType);
return true;
});
TransitionToComponentMode();
}
@@ -238,8 +227,7 @@ namespace AzToolsFramework
}
}
bool EditorDefaultSelection::InternalHandleMouseViewportInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
bool EditorDefaultSelection::InternalHandleMouseViewportInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
bool enterComponentModeAttempted = false;
const bool componentModeBefore = InComponentMode();
@@ -249,15 +237,15 @@ namespace AzToolsFramework
{
// enumerate all ComponentModeDelegateRequestBus and check if any triggered AddComponentModes
ComponentModeFramework::ComponentModeDelegateRequestBus::EnumerateHandlers(
[&mouseInteraction, &enterComponentModeAttempted]
(ComponentModeFramework::ComponentModeDelegateRequestBus::InterfaceType* componentModeMouseRequests)
{
// detect if a double click happened on any Component in the viewport, attempting
// to move it into ComponentMode (note: this is not guaranteed to succeed as an
// incompatible multi-selection may prevent it)
enterComponentModeAttempted = componentModeMouseRequests->DetectEnterComponentModeInteraction(mouseInteraction);
return !enterComponentModeAttempted;
});
[&mouseInteraction, &enterComponentModeAttempted](
ComponentModeFramework::ComponentModeDelegateRequestBus::InterfaceType* componentModeMouseRequests)
{
// detect if a double click happened on any Component in the viewport, attempting
// to move it into ComponentMode (note: this is not guaranteed to succeed as an
// incompatible multi-selection may prevent it)
enterComponentModeAttempted = componentModeMouseRequests->DetectEnterComponentModeInteraction(mouseInteraction);
return !enterComponentModeAttempted;
});
// here we know ComponentMode was entered successfully and was not prohibited
if (m_componentModeCollection.ModesAdded())
@@ -272,25 +260,24 @@ namespace AzToolsFramework
else
{
ComponentModeFramework::ComponentModeRequestBus::EnumerateHandlers(
[&mouseInteraction, &handled]
(ComponentModeFramework::ComponentModeRequestBus::InterfaceType* componentModeRequest)
{
if (componentModeRequest->HandleMouseInteraction(mouseInteraction))
[&mouseInteraction, &handled](ComponentModeFramework::ComponentModeRequestBus::InterfaceType* componentModeRequest)
{
handled = true;
}
if (componentModeRequest->HandleMouseInteraction(mouseInteraction))
{
handled = true;
}
return true;
});
return true;
});
if (!handled)
{
ComponentModeFramework::ComponentModeDelegateRequestBus::EnumerateHandlers(
[&mouseInteraction]
(ComponentModeFramework::ComponentModeDelegateRequestBus::InterfaceType* componentModeDelegateRequests)
{
return !componentModeDelegateRequests->DetectLeaveComponentModeInteraction(mouseInteraction);
});
[&mouseInteraction](
ComponentModeFramework::ComponentModeDelegateRequestBus::InterfaceType* componentModeDelegateRequests)
{
return !componentModeDelegateRequests->DetectLeaveComponentModeInteraction(mouseInteraction);
});
}
}
@@ -311,8 +298,7 @@ namespace AzToolsFramework
}
void EditorDefaultSelection::DisplayViewportSelection(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay)
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
if (m_transformComponentSelection)
{
@@ -330,8 +316,7 @@ namespace AzToolsFramework
}
void EditorDefaultSelection::DisplayViewportSelection2d(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay)
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
if (m_transformComponentSelection)
{
@@ -355,11 +340,12 @@ namespace AzToolsFramework
void EditorDefaultSelection::AddActionOverride(const ActionOverride& actionOverride)
{
// check if an action with this uri is already added
const auto actionIt = AZStd::find_if(m_actions.begin(), m_actions.end(),
const auto actionIt = AZStd::find_if(
m_actions.begin(), m_actions.end(),
[actionOverride](const AZStd::shared_ptr<ActionOverrideMapping>& actionOverrideMapping)
{
return actionOverride.m_uri == actionOverrideMapping->m_uri;
});
{
return actionOverride.m_uri == actionOverrideMapping->m_uri;
});
// if an action with the same uri is already added, store the callback for this action
if (actionIt != m_actions.end())
@@ -381,44 +367,45 @@ namespace AzToolsFramework
// set callbacks that should happen when this action is triggered
auto index = static_cast<int>(m_actions.size());
QObject::connect(action.get(), &QAction::triggered, [this, index]()
{
const auto vec = m_actions; // increment ref count of shared_ptr, callback may clear actions
for (auto& callback : vec[index]->m_callbacks)
QObject::connect(
action.get(), &QAction::triggered,
[this, index]()
{
callback();
}
});
const auto vec = m_actions; // increment ref count of shared_ptr, callback may clear actions
for (auto& callback : vec[index]->m_callbacks)
{
callback();
}
});
m_actions.emplace_back(
AZStd::make_shared<ActionOverrideMapping>(
actionOverride.m_uri, AZStd::vector<AZStd::function<void()>>{ actionOverride.m_callback },
AZStd::move(action)));
m_actions.emplace_back(AZStd::make_shared<ActionOverrideMapping>(
actionOverride.m_uri, AZStd::vector<AZStd::function<void()>>{ actionOverride.m_callback }, AZStd::move(action)));
// register action with edit menu
EditorMenuRequestBus::Broadcast(
&EditorMenuRequests::AddEditMenuAction, m_actions.back()->m_action.get());
EditorMenuRequestBus::Broadcast(&EditorMenuRequests::AddEditMenuAction, m_actions.back()->m_action.get());
}
}
void EditorDefaultSelection::ClearActionOverrides()
{
AZStd::for_each(m_actions.begin(), m_actions.end(),
AZStd::for_each(
m_actions.begin(), m_actions.end(),
[this](const AZStd::shared_ptr<ActionOverrideMapping>& actionMapping)
{
PhantomWidget().removeAction(actionMapping->m_action.get());
});
{
PhantomWidget().removeAction(actionMapping->m_action.get());
});
m_actions.clear();
}
void EditorDefaultSelection::RemoveActionOverride(const AZ::Crc32 actionOverrideUri)
{
const auto it = AZStd::find_if(m_actions.begin(), m_actions.end(),
const auto it = AZStd::find_if(
m_actions.begin(), m_actions.end(),
[actionOverrideUri](const AZStd::shared_ptr<ActionOverrideMapping>& actionMapping)
{
return actionMapping->m_uri == actionOverrideUri;
});
{
return actionMapping->m_uri == actionOverrideUri;
});
if (it != m_actions.end())
{
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -19,7 +19,7 @@
namespace AzToolsFramework
{
/// The default selection/input handler for the editor (includes handling ComponentMode).
//! The default selection/input handler for the editor (includes handling ComponentMode).
class EditorDefaultSelection
: public ViewportInteraction::InternalViewportSelectionRequests
, private ActionOverrideRequestBus::Handler
@@ -28,30 +28,26 @@ namespace AzToolsFramework
public:
AZ_CLASS_ALLOCATOR_DECL
/// @cond
//! @cond
explicit EditorDefaultSelection(const EditorVisibleEntityDataCache* entityDataCache);
EditorDefaultSelection(const EditorDefaultSelection&) = delete;
EditorDefaultSelection& operator=(const EditorDefaultSelection&) = delete;
virtual ~EditorDefaultSelection();
/// @endcond
//! @endcond
/// Override the default widget used to store QActions while in ComponentMode.
/// @note This should not be necessary during normal operation and is provided
/// as a customization point to aid with testing.
//! Override the default widget used to store QActions while in ComponentMode.
//! @note This should not be necessary during normal operation and is provided
//! as a customization point to aid with testing.
void SetOverridePhantomWidget(QWidget* phantomOverrideWidget);
private:
// ViewportInteraction::InternalMouseViewportRequests ...
bool InternalHandleMouseViewportInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
bool InternalHandleMouseManipulatorInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
bool InternalHandleMouseViewportInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
bool InternalHandleMouseManipulatorInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
void DisplayViewportSelection(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
void DisplayViewportSelection2d(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
// ActionOverrideRequestBus ...
void SetupActionOverrideHandler(QWidget* parent) override;
@@ -65,7 +61,10 @@ namespace AzToolsFramework
const AZStd::vector<ComponentModeFramework::EntityAndComponentModeBuilders>& entityAndComponentModeBuilders) override;
void AddComponentModes(const ComponentModeFramework::EntityAndComponentModeBuilders& entityAndComponentModeBuilders) override;
void EndComponentMode() override;
bool InComponentMode() override { return m_componentModeCollection.InComponentMode(); }
bool InComponentMode() override
{
return m_componentModeCollection.InComponentMode();
}
void Refresh(const AZ::EntityComponentIdPair& entityComponentIdPair) override;
bool AddedToComponentMode(const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType) override;
void AddSelectedComponentModesOfType(const AZ::Uuid& componentType) override;
@@ -77,41 +76,43 @@ namespace AzToolsFramework
bool HasMultipleComponentTypes() override;
void RefreshActions() override;
/// Helpers to deal with moving in and out of ComponentMode.
//! Helpers to deal with moving in and out of ComponentMode.
void TransitionToComponentMode();
void TransitionFromComponentMode();
/// Accessor used internally to refer to the phantom widget.
/// This will either be the default widget or the override if non-null.
//! Accessor used internally to refer to the phantom widget.
//! This will either be the default widget or the override if non-null.
QWidget& PhantomWidget();
QWidget m_phantomWidget; ///< The phantom widget responsible for holding QActions while in ComponentMode.
QWidget* m_phantomOverrideWidget = nullptr; ///< It's possible to override the phantom widget in special circumstances (eg testing).
ComponentModeFramework::ComponentModeCollection m_componentModeCollection; ///< Handles all active ComponentMode types.
AZStd::unique_ptr<EditorTransformComponentSelection> m_transformComponentSelection = nullptr; ///< Viewport selection (responsible for
///< manipulators and transform modifications).
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; ///< Reference to cached visible EntityData.
QWidget m_phantomWidget; //!< The phantom widget responsible for holding QActions while in ComponentMode.
QWidget* m_phantomOverrideWidget = nullptr; //!< It's possible to override the phantom widget in special circumstances (eg testing).
ComponentModeFramework::ComponentModeCollection m_componentModeCollection; //!< Handles all active ComponentMode types.
AZStd::unique_ptr<EditorTransformComponentSelection> m_transformComponentSelection =
nullptr; //!< Viewport selection (responsible for
//!< manipulators and transform modifications).
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Reference to cached visible EntityData.
/// Mapping between passed ActionOverride (AddActionOverride) and allocated QAction.
//! Mapping between passed ActionOverride (AddActionOverride) and allocated QAction.
struct ActionOverrideMapping
{
ActionOverrideMapping(
const AZ::Crc32 uri, const AZStd::vector<AZStd::function<void()>>& callbacks,
AZStd::unique_ptr<QAction> action)
const AZ::Crc32 uri, const AZStd::vector<AZStd::function<void()>>& callbacks, AZStd::unique_ptr<QAction> action)
: m_uri(uri)
, m_callbacks(callbacks)
, m_action(AZStd::move(action)) {}
, m_action(AZStd::move(action))
{
}
AZ::Crc32 m_uri; ///< Unique identifier for the Action. (In the form 'com.amazon.action.---").
AZStd::vector<AZStd::function<void()>> m_callbacks; ///< Callbacks associated with this Action (note: with multi-selections there
///< will be a callback per Entity/Component).
AZStd::unique_ptr<QAction> m_action; ///< The QAction associated with the overrideWidget for all ComponentMode actions.
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'com.amazon.action.---").
AZStd::vector<AZStd::function<void()>> m_callbacks; //!< Callbacks associated with this Action (note: with multi-selections
//!< there will be a callback per Entity/Component).
AZStd::unique_ptr<QAction> m_action; //!< The QAction associated with the overrideWidget for all ComponentMode actions.
};
AZStd::vector<AZStd::shared_ptr<ActionOverrideMapping>> m_actions; ///< Currently bound actions (corresponding to those set
///< on the override widget).
AZStd::vector<AZStd::shared_ptr<ActionOverrideMapping>> m_actions; //!< Currently bound actions (corresponding to those set
//!< on the override widget).
AZStd::shared_ptr<AzToolsFramework::ManipulatorManager> m_manipulatorManager; ///< The default manipulator manager.
ViewportInteraction::MouseInteraction m_currentInteraction; ///< Current mouse interaction to be used for drawing manipulators.
AZStd::shared_ptr<AzToolsFramework::ManipulatorManager> m_manipulatorManager; //!< The default manipulator manager.
ViewportInteraction::MouseInteraction m_currentInteraction; //!< Current mouse interaction to be used for drawing manipulators.
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorHelpers.h"
@@ -16,21 +16,33 @@
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Visibility/BoundsBus.h>
#include <AzToolsFramework/API/EditorViewportIconDisplayInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorEntityIconComponentBus.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzToolsFramework/API/EditorViewportIconDisplayInterface.h>
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
AZ_CVAR(
bool, ed_visibility_showAggregateEntitySelectionBounds, false, nullptr, AZ::ConsoleFunctorFlags::Null,
bool,
ed_visibility_showAggregateEntitySelectionBounds,
false,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"Display the aggregate selection bounds for a given entity (the union of all component Aabbs)");
AZ_CVAR(
bool, ed_visibility_showAggregateEntityTransformedLocalBounds, false, nullptr, AZ::ConsoleFunctorFlags::Null,
bool,
ed_visibility_showAggregateEntityTransformedLocalBounds,
false,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"Display the aggregate transformed local bounds for a given entity (the union of all local component Aabbs)");
AZ_CVAR(
bool, ed_visibility_showAggregateEntityWorldBounds, false, nullptr, AZ::ConsoleFunctorFlags::Null,
bool,
ed_visibility_showAggregateEntityWorldBounds,
false,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"Display the aggregate world bounds for a given entity (the union of all world component Aabbs)");
namespace AzToolsFramework
@@ -48,8 +60,7 @@ namespace AzToolsFramework
static bool HelpersVisible()
{
bool helpersVisible = false;
EditorRequestBus::BroadcastResult(
helpersVisible, &EditorRequests::DisplayHelpersVisible);
EditorRequestBus::BroadcastResult(helpersVisible, &EditorRequests::DisplayHelpersVisible);
return helpersVisible;
}
@@ -59,25 +70,23 @@ namespace AzToolsFramework
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
return s_iconMinScale + (s_iconMaxScale - s_iconMinScale) *
return s_iconMinScale +
(s_iconMaxScale - s_iconMinScale) *
(1.0f - AZ::GetClamp(AZ::GetMax(0.0f, sqrtf(distSq) - s_iconCloseDist) / s_iconFarDist, 0.0f, 1.0f));
}
static void DisplayComponents(
const AZ::EntityId entityId, const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay)
const AZ::EntityId entityId, const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
const AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
AzFramework::EntityDebugDisplayEventBus::Event(
entityId, &AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport,
viewportInfo, debugDisplay);
entityId, &AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport, viewportInfo, debugDisplay);
if (ed_visibility_showAggregateEntitySelectionBounds)
{
if (const AZ::Aabb aabb = AzToolsFramework::CalculateEditorEntitySelectionBounds(entityId, viewportInfo);
aabb.IsValid())
if (const AZ::Aabb aabb = AzToolsFramework::CalculateEditorEntitySelectionBounds(entityId, viewportInfo); aabb.IsValid())
{
debugDisplay.SetColor(AZ::Colors::Orange);
debugDisplay.DrawWireBox(aabb.GetMin(), aabb.GetMax());
@@ -107,8 +116,7 @@ namespace AzToolsFramework
}
AZ::EntityId EditorHelpers::HandleMouseInteraction(
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
const AzFramework::CameraState& cameraState, const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -127,8 +135,7 @@ namespace AzToolsFramework
{
const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex);
if ( m_entityDataCache->IsVisibleEntityLocked(entityCacheIndex)
|| !m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex))
if (m_entityDataCache->IsVisibleEntityLocked(entityCacheIndex) || !m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex))
{
continue;
}
@@ -148,10 +155,8 @@ namespace AzToolsFramework
const auto iconRange = static_cast<float>(GetIconScale(distSqFromCamera) * s_iconSize * 0.5f);
const auto screenCoords = mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates;
if ( screenCoords.m_x >= screenPosition.m_x - iconRange
&& screenCoords.m_x <= screenPosition.m_x + iconRange
&& screenCoords.m_y >= screenPosition.m_y - iconRange
&& screenCoords.m_y <= screenPosition.m_y + iconRange)
if (screenCoords.m_x >= screenPosition.m_x - iconRange && screenCoords.m_x <= screenPosition.m_x + iconRange &&
screenCoords.m_y >= screenPosition.m_y - iconRange && screenCoords.m_y <= screenPosition.m_y + iconRange)
{
entityIdUnderCursor = entityId;
break;
@@ -161,16 +166,13 @@ namespace AzToolsFramework
using AzFramework::ViewportInfo;
// check if components provide an aabb
if (const AZ::Aabb aabb = CalculateEditorEntitySelectionBounds(entityId, ViewportInfo{viewportId});
aabb.IsValid())
if (const AZ::Aabb aabb = CalculateEditorEntitySelectionBounds(entityId, ViewportInfo{ viewportId }); aabb.IsValid())
{
// coarse grain check
if (AabbIntersectMouseRay(mouseInteraction.m_mouseInteraction, aabb))
{
// if success, pick against specific component
if (PickEntity(
entityId, mouseInteraction.m_mouseInteraction,
closestDistance, viewportId))
if (PickEntity(entityId, mouseInteraction.m_mouseInteraction, closestDistance, viewportId))
{
entityIdUnderCursor = entityId;
}
@@ -182,7 +184,8 @@ namespace AzToolsFramework
}
void EditorHelpers::DisplayHelpers(
const AzFramework::ViewportInfo& viewportInfo, const AzFramework::CameraState& cameraState,
const AzFramework::ViewportInfo& viewportInfo,
const AzFramework::CameraState& cameraState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AZStd::function<bool(AZ::EntityId)>& showIconCheck)
{
@@ -202,8 +205,8 @@ namespace AzToolsFramework
// notify components to display
DisplayComponents(entityId, viewportInfo, debugDisplay);
if ( m_entityDataCache->IsVisibleEntityIconHidden(entityCacheIndex)
|| (m_entityDataCache->IsVisibleEntitySelected(entityCacheIndex) && !showIconCheck(entityId)))
if (m_entityDataCache->IsVisibleEntityIconHidden(entityCacheIndex) ||
(m_entityDataCache->IsVisibleEntitySelected(entityCacheIndex) && !showIconCheck(entityId)))
{
continue;
}
@@ -219,7 +222,8 @@ namespace AzToolsFramework
const float iconSize = s_iconSize * iconScale;
using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
const AZ::Color iconHighlight = [this, entityCacheIndex]() {
const AZ::Color iconHighlight = [this, entityCacheIndex]()
{
if (m_entityDataCache->IsVisibleEntityLocked(entityCacheIndex))
{
return AZ::Color(AZ::u8(100), AZ::u8(100), AZ::u8(100), AZ::u8(255));
@@ -233,14 +237,9 @@ namespace AzToolsFramework
return AZ::Color(1.0f, 1.0f, 1.0f, 1.0f);
}();
EditorViewportIconDisplay::Get()->DrawIcon({
viewportInfo.m_viewportId,
iconTextureId,
iconHighlight,
entityPosition,
EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace,
AZ::Vector2{iconSize, iconSize}
});
EditorViewportIconDisplay::Get()->DrawIcon({ viewportInfo.m_viewportId, iconTextureId, iconHighlight, entityPosition,
EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace,
AZ::Vector2{ iconSize, iconSize } });
}
}
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -21,7 +21,7 @@ namespace AzFramework
class DebugDisplayRequests;
struct ViewportInfo;
struct CameraState;
}
} // namespace AzFramework
namespace AzToolsFramework
{
@@ -32,37 +32,39 @@ namespace AzToolsFramework
struct MouseInteractionEvent;
}
/// EditorHelpers are the visualizations that appear for entities
/// when 'Display Helpers' is toggled on inside the editor.
/// These include but are not limited to entity icons and shape visualizations.
//! EditorHelpers are the visualizations that appear for entities
//! when 'Display Helpers' is toggled on inside the editor.
//! These include but are not limited to entity icons and shape visualizations.
class EditorHelpers
{
public:
AZ_CLASS_ALLOCATOR_DECL
/// An EditorVisibleEntityDataCache must be passed to EditorHelpers to allow it to
/// efficiently read entity data without resorting to EBus calls.
//! An EditorVisibleEntityDataCache must be passed to EditorHelpers to allow it to
//! efficiently read entity data without resorting to EBus calls.
explicit EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache)
: m_entityDataCache(entityDataCache) {}
: m_entityDataCache(entityDataCache)
{
}
EditorHelpers(const EditorHelpers&) = delete;
EditorHelpers& operator=(const EditorHelpers&) = delete;
~EditorHelpers() = default;
/// Handle any mouse interaction with the EditorHelpers.
/// Used to check if a particular entity was selected.
//! Handle any mouse interaction with the EditorHelpers.
//! Used to check if a particular entity was selected.
AZ::EntityId HandleMouseInteraction(
const AzFramework::CameraState& cameraState,
const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
const AzFramework::CameraState& cameraState, const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
/// Do the drawing responsible for the EditorHelpers.
/// @param showIconCheck Provide a custom callback to filter certain entities from
/// displaying an icon under certain conditions.
//! Do the drawing responsible for the EditorHelpers.
//! @param showIconCheck Provide a custom callback to filter certain entities from
//! displaying an icon under certain conditions.
void DisplayHelpers(
const AzFramework::ViewportInfo& viewportInfo, const AzFramework::CameraState& cameraState,
const AzFramework::ViewportInfo& viewportInfo,
const AzFramework::CameraState& cameraState,
AzFramework::DebugDisplayRequests& debugDisplay,
const AZStd::function<bool(AZ::EntityId)>& showIconCheck);
private:
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; ///< Entity Data queried by the EditorHelpers.
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorInteractionSystemComponent.h"
@@ -45,8 +45,7 @@ namespace AzToolsFramework
return m_interactionRequests->InternalHandleMouseManipulatorInteraction(mouseInteraction);
}
void EditorInteractionSystemComponent::SetHandler(
const ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder)
void EditorInteractionSystemComponent::SetHandler(const ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder)
{
// when setting a handler, make sure we're connected to the ViewportDebugDisplayEventBus so we
// can forward calls to the specific type implementing ViewportSelectionRequests
@@ -57,32 +56,30 @@ namespace AzToolsFramework
m_entityDataCache = AZStd::make_unique<EditorVisibleEntityDataCache>();
m_interactionRequests.reset(); // BusConnect/Disconnect in constructor/destructor,
m_interactionRequests.reset(); // BusConnect/Disconnect in constructor/destructor,
// so have to reset before assigning the new one
m_interactionRequests = interactionRequestsBuilder(m_entityDataCache.get());
}
void EditorInteractionSystemComponent::SetDefaultHandler()
{
SetHandler([](const EditorVisibleEntityDataCache* entityDataCache)
{
return AZStd::make_unique<EditorDefaultSelection>(entityDataCache);
});
SetHandler(
[](const EditorVisibleEntityDataCache* entityDataCache)
{
return AZStd::make_unique<EditorDefaultSelection>(entityDataCache);
});
}
void EditorInteractionSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<EditorInteractionSystemComponent, AZ::Component>()
->Version(0)
;
serializeContext->Class<EditorInteractionSystemComponent, AZ::Component>()->Version(0);
}
}
void EditorInteractionSystemComponent::DisplayViewport(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay)
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -93,8 +90,7 @@ namespace AzToolsFramework
}
void EditorInteractionSystemComponent::DisplayViewport2d(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay)
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
m_interactionRequests->DisplayViewportSelection2d(viewportInfo, debugDisplay);
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -18,9 +18,9 @@
namespace AzToolsFramework
{
/// System Component to wrap active input handler.
/// EditorInteractionSystemComponent is notified of viewport mouse events from RenderViewport
/// and forwards them to a concrete implementation of ViewportSelectionRequests.
//! System Component to wrap active input handler.
//! EditorInteractionSystemComponent is notified of viewport mouse events from RenderViewport
//! and forwards them to a concrete implementation of ViewportSelectionRequests.
class EditorInteractionSystemComponent
: public AZ::Component
, private EditorInteractionSystemViewportSelectionRequestBus::Handler
@@ -37,18 +37,12 @@ namespace AzToolsFramework
void SetDefaultHandler() override;
// EditorInteractionSystemViewportSelectionRequestBus ...
bool InternalHandleMouseViewportInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
bool InternalHandleMouseManipulatorInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
bool InternalHandleMouseViewportInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
bool InternalHandleMouseManipulatorInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
// AzFramework::ViewportDebugDisplayEventBus
void DisplayViewport(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
void DisplayViewport2d(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
void DisplayViewport2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
private:
// AZ::Component
@@ -58,11 +52,11 @@ namespace AzToolsFramework
// EditorEventsBus
void NotifyCentralWidgetInitialized() override;
AZStd::unique_ptr<EditorVisibleEntityDataCache> m_entityDataCache = nullptr; ///< Visible EntityData cache to be used by concrete
///< instantiations of ViewportSelectionRequests.
AZStd::unique_ptr<EditorVisibleEntityDataCache> m_entityDataCache = nullptr; //!< Visible EntityData cache to be used by concrete
//!< instantiations of ViewportSelectionRequests.
AZStd::unique_ptr<InternalViewportSelectionRequests> m_interactionRequests; ///< Hold a concrete implementation of
///< ViewportSelectionRequests to handle viewport
///< input and drawing for the Editor.
AZStd::unique_ptr<InternalViewportSelectionRequests> m_interactionRequests; //!< Hold a concrete implementation of
//!< ViewportSelectionRequests to handle viewport
//!< input and drawing for the Editor.
};
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -22,10 +22,9 @@ namespace AzToolsFramework
{
class EditorVisibleEntityDataCache;
/// Bus to handle all mouse events originating from the viewport.
/// Coordinated by the EditorInteractionSystemComponent
class EditorInteractionSystemViewportSelectionRequests
: public AZ::EBusTraits
//! Bus to handle all mouse events originating from the viewport.
//! Coordinated by the EditorInteractionSystemComponent
class EditorInteractionSystemViewportSelectionRequests : public AZ::EBusTraits
{
public:
using BusIdType = AzFramework::EntityContextId;
@@ -36,32 +35,31 @@ namespace AzToolsFramework
~EditorInteractionSystemViewportSelectionRequests() = default;
};
/// Alias for factory function to create a new type implementing the ViewportSelectionRequests interface.
//! Alias for factory function to create a new type implementing the ViewportSelectionRequests interface.
using ViewportSelectionRequestsBuilderFn =
AZStd::function<AZStd::unique_ptr<ViewportInteraction::InternalViewportSelectionRequests>(const EditorVisibleEntityDataCache*)>;
/// Interface for system component implementing the ViewportSelectionRequests interface.
/// This interface also includes a setter to set a custom handler also implementing
/// the ViewportSelectionRequests interface to customize editor behavior.
class EditorInteractionSystemViewportSelection
: public ViewportInteraction::InternalViewportSelectionRequests
//! Interface for system component implementing the ViewportSelectionRequests interface.
//! This interface also includes a setter to set a custom handler also implementing
//! the ViewportSelectionRequests interface to customize editor behavior.
class EditorInteractionSystemViewportSelection : public ViewportInteraction::InternalViewportSelectionRequests
{
public:
/// \ref SetHandler takes a factory function to create a new type implementing
/// the ViewportSelectionRequests interface.
/// It provides a handler implementing ViewportSelectionRequests to handle all
/// viewport mouse input and drawing.
//! \ref SetHandler takes a factory function to create a new type implementing
//! the ViewportSelectionRequests interface.
//! It provides a handler implementing ViewportSelectionRequests to handle all
//! viewport mouse input and drawing.
virtual void SetHandler(const ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder) = 0;
/// \ref SetDefaultHandler is a utility function to set the
/// default editor handler (currently \ref EditorDefaultSelection).
/// This is useful to call after setting another mode and then wishing
/// to return to normal operation of the editor.
//! \ref SetDefaultHandler is a utility function to set the
//! default editor handler (currently \ref EditorDefaultSelection).
//! This is useful to call after setting another mode and then wishing
//! to return to normal operation of the editor.
virtual void SetDefaultHandler() = 0;
};
/// Type to inherit to implement EditorInteractionSystemViewportSelection.
/// @note Called by viewport events (RenderViewport) and then handled by concrete
/// implementation of InternalViewportSelectionRequests.
//! Type to inherit to implement EditorInteractionSystemViewportSelection.
//! @note Called by viewport events (RenderViewport) and then handled by concrete
//! implementation of InternalViewportSelectionRequests.
using EditorInteractionSystemViewportSelectionRequestBus =
AZ::EBus<EditorInteractionSystemViewportSelection, EditorInteractionSystemViewportSelectionRequests>;
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorPickEntitySelection.h"
@@ -19,9 +19,8 @@ namespace AzToolsFramework
{
AZ_CLASS_ALLOCATOR_IMPL(EditorPickEntitySelection, AZ::SystemAllocator, 0)
EditorPickEntitySelection::EditorPickEntitySelection(
const EditorVisibleEntityDataCache* entityDataCache)
: m_editorHelpers(AZStd::make_unique<EditorHelpers>(entityDataCache))
EditorPickEntitySelection::EditorPickEntitySelection(const EditorVisibleEntityDataCache* entityDataCache)
: m_editorHelpers(AZStd::make_unique<EditorHelpers>(entityDataCache))
{
}
@@ -29,8 +28,7 @@ namespace AzToolsFramework
{
if (m_hoveredEntityId.IsValid())
{
ToolsApplicationRequestBus::Broadcast(
&ToolsApplicationRequests::SetEntityHighlighted, m_hoveredEntityId, false);
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetEntityHighlighted, m_hoveredEntityId, false);
}
}
@@ -41,8 +39,7 @@ namespace AzToolsFramework
// highlighted - hoveredEntityId is an in/out param that is updated based on the change in
// entityIdUnderCursor.
static void HandleAccents(
const AZ::EntityId entityIdUnderCursor, AZ::EntityId& hoveredEntityId,
const ViewportInteraction::MouseButtons mouseButtons)
const AZ::EntityId entityIdUnderCursor, AZ::EntityId& hoveredEntityId, const ViewportInteraction::MouseButtons mouseButtons)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -55,8 +52,7 @@ namespace AzToolsFramework
{
if (hoveredEntityId.IsValid())
{
ToolsApplicationRequestBus::Broadcast(
&ToolsApplicationRequests::SetEntityHighlighted, hoveredEntityId, false);
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetEntityHighlighted, hoveredEntityId, false);
hoveredEntityId.SetInvalid();
}
@@ -68,8 +64,7 @@ namespace AzToolsFramework
{
if (entityIdUnderCursor.IsValid() && entityIdUnderCursor != hoveredEntityId)
{
ToolsApplicationRequestBus::Broadcast(
&ToolsApplicationRequests::SetEntityHighlighted, entityIdUnderCursor, true);
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetEntityHighlighted, entityIdUnderCursor, true);
hoveredEntityId = entityIdUnderCursor;
}
@@ -93,8 +88,7 @@ namespace AzToolsFramework
if (m_cachedEntityIdUnderCursor.IsValid())
{
// if we clicked on a valid entity id, actually try to set it
EditorPickModeRequestBus::Broadcast(
&EditorPickModeRequests::PickModeSelectEntity, m_cachedEntityIdUnderCursor);
EditorPickModeRequestBus::Broadcast(&EditorPickModeRequests::PickModeSelectEntity, m_cachedEntityIdUnderCursor);
}
// after a click, always stop pick mode, whether we set an entity or not
@@ -105,16 +99,18 @@ namespace AzToolsFramework
}
void EditorPickEntitySelection::DisplayViewportSelection(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay)
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
const AzFramework::CameraState cameraState = GetCameraState(viewportInfo.m_viewportId);
m_editorHelpers->DisplayHelpers(
viewportInfo, cameraState, debugDisplay, [](AZ::EntityId){ return true; });
viewportInfo, cameraState, debugDisplay,
[](AZ::EntityId)
{
return true;
});
HandleAccents(
m_cachedEntityIdUnderCursor, m_hoveredEntityId,
ViewportInteraction::BuildMouseButtons(QGuiApplication::mouseButtons()));
m_cachedEntityIdUnderCursor, m_hoveredEntityId, ViewportInteraction::BuildMouseButtons(QGuiApplication::mouseButtons()));
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -17,10 +17,9 @@
namespace AzToolsFramework
{
/// Viewport interaction that will handle assigning an entity in the viewport to
/// an entity field in the entity inspector.
class EditorPickEntitySelection
: public ViewportInteraction::InternalViewportSelectionRequests
//! Viewport interaction that will handle assigning an entity in the viewport to
//! an entity field in the entity inspector.
class EditorPickEntitySelection : public ViewportInteraction::InternalViewportSelectionRequests
{
public:
AZ_CLASS_ALLOCATOR_DECL
@@ -30,15 +29,12 @@ namespace AzToolsFramework
private:
// ViewportInteraction::InternalViewportSelectionRequests ...
bool InternalHandleMouseViewportInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
bool InternalHandleMouseViewportInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
void DisplayViewportSelection(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
AZStd::unique_ptr<EditorHelpers> m_editorHelpers; ///< Editor visualization of entities (icons, shapes, debug visuals etc).
AZ::EntityId m_hoveredEntityId; ///< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; ///< Store the EntityId on each mouse move for use in Display.
AZStd::unique_ptr<EditorHelpers> m_editorHelpers; //!< Editor visualization of entities (icons, shapes, debug visuals etc).
AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
};
} // namespace AzToolsFramework
@@ -1,38 +1,36 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorSelectionUtil.h"
#include <AzCore/Math/Aabb.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/Math/IntersectSegment.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/Math/Aabb.h>
#include <AzCore/Math/IntersectSegment.h>
#include <AzFramework/Visibility/BoundsBus.h>
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
namespace AzToolsFramework
{
/// Default ray length for picking in the viewport.
// default ray length for picking in the viewport
static const float s_pickRayLength = 1000.0f;
AZ::Vector3 CalculateCenterOffset(
const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot)
AZ::Vector3 CalculateCenterOffset(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot)
{
if (Centered(pivot))
{
const AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
if (const AZ::Aabb localBound = AzFramework::CalculateEntityLocalBoundsUnion(entity);
localBound.IsValid())
if (const AZ::Aabb localBound = AzFramework::CalculateEntityLocalBoundsUnion(entity); localBound.IsValid())
{
return localBound.GetCenter();
}
@@ -41,76 +39,71 @@ namespace AzToolsFramework
return AZ::Vector3::CreateZero();
}
float CalculateScreenToWorldMultiplier(
const AZ::Vector3& worldPosition, const AzFramework::CameraState& cameraState)
float CalculateScreenToWorldMultiplier(const AZ::Vector3& worldPosition, const AzFramework::CameraState& cameraState)
{
const float apparentDistance = 10.0f;
// compute the distance from the camera, projected onto the camera's forward direction
// note: this keeps the scale value the same when positions are at the edge of the screen
const float projectedCameraDistance =
std::abs((cameraState.m_position - worldPosition).Dot(cameraState.m_forward));
const float projectedCameraDistance = std::abs((cameraState.m_position - worldPosition).Dot(cameraState.m_forward));
// author sizes of bounds/manipulators as they would appear
// in perspective 10 meters from the camera.
return AZ::GetMax(projectedCameraDistance, cameraState.m_nearClip) / apparentDistance;
}
AzFramework::ScreenPoint GetScreenPosition(const int viewportId, const AZ::Vector3& worldTranslation)
AzFramework::ScreenPoint GetScreenPosition(const int viewportId, const AZ::Vector3& worldTranslation)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
auto screenPosition = AzFramework::ScreenPoint(0, 0);
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
screenPosition, viewportId,
&ViewportInteraction::ViewportInteractionRequestBus::Events::ViewportWorldToScreen,
screenPosition, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::ViewportWorldToScreen,
worldTranslation);
return screenPosition;
}
bool AabbIntersectMouseRay(
const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb)
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
const AZ::Vector3 rayScaledDir =
mouseInteraction.m_mousePick.m_rayDirection * s_pickRayLength;
const AZ::Vector3 rayScaledDir = mouseInteraction.m_mousePick.m_rayDirection * s_pickRayLength;
AZ::Vector3 startNormal;
float t, end;
return AZ::Intersect::IntersectRayAABB(
mouseInteraction.m_mousePick.m_rayOrigin, rayScaledDir,
rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0;
mouseInteraction.m_mousePick.m_rayOrigin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0;
}
bool PickEntity(
const AZ::EntityId entityId, const ViewportInteraction::MouseInteraction& mouseInteraction,
float& closestDistance, const int viewportId)
const AZ::EntityId entityId,
const ViewportInteraction::MouseInteraction& mouseInteraction,
float& closestDistance,
const int viewportId)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Entity);
bool entityPicked = false;
EditorComponentSelectionRequestsBus::EnumerateHandlersId(
entityId, [mouseInteraction, &entityPicked, &closestDistance, viewportId]
(EditorComponentSelectionRequests* handler) -> bool
{
if (handler->SupportsEditorRayIntersect())
entityId,
[mouseInteraction, &entityPicked, &closestDistance, viewportId](EditorComponentSelectionRequests* handler) -> bool
{
float distance = std::numeric_limits<float>::max();
const bool intersection = handler->EditorSelectionIntersectRayViewport(
{ viewportId }, mouseInteraction.m_mousePick.m_rayOrigin,
mouseInteraction.m_mousePick.m_rayDirection, distance);
if (intersection && distance < closestDistance)
if (handler->SupportsEditorRayIntersect())
{
entityPicked = true;
closestDistance = distance;
}
}
float distance = std::numeric_limits<float>::max();
const bool intersection = handler->EditorSelectionIntersectRayViewport(
{ viewportId }, mouseInteraction.m_mousePick.m_rayOrigin, mouseInteraction.m_mousePick.m_rayDirection, distance);
return true; // iterate over all handlers
});
if (intersection && distance < closestDistance)
{
entityPicked = true;
closestDistance = distance;
}
}
return true; // iterate over all handlers
});
return entityPicked;
}
@@ -119,9 +112,8 @@ namespace AzToolsFramework
{
AzFramework::CameraState cameraState;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
cameraState, viewportId,
&ViewportInteraction::ViewportInteractionRequestBus::Events::GetCameraState);
cameraState, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GetCameraState);
return cameraState;
}
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -30,56 +30,53 @@ namespace AzFramework
namespace AzToolsFramework
{
/// Is the pivot at the center of the object (middle of extents) or at the
/// exported authored object root position.
//! Is the pivot at the center of the object (middle of extents) or at the
//! exported authored object root position.
inline bool Centered(const EditorTransformComponentSelectionRequests::Pivot pivot)
{
return pivot == EditorTransformComponentSelectionRequests::Pivot::Center;
}
/// Return offset from object pivot to center if center is true, otherwise Vector3::Zero.
//! Return offset from object pivot to center if center is true, otherwise Vector3::Zero.
AZ::Vector3 CalculateCenterOffset(AZ::EntityId entityId, EditorTransformComponentSelectionRequests::Pivot pivot);
/// Calculate scale factor based on distance from camera
float CalculateScreenToWorldMultiplier(
const AZ::Vector3& worldPosition, const AzFramework::CameraState& cameraState);
//! Calculate scale factor based on distance from camera
float CalculateScreenToWorldMultiplier(const AZ::Vector3& worldPosition, const AzFramework::CameraState& cameraState);
/// Map from world space to screen space.
AzFramework::ScreenPoint GetScreenPosition(int viewportId, const AZ::Vector3& worldTranslation);
//! Map from world space to screen space.
AzFramework::ScreenPoint GetScreenPosition(int viewportId, const AZ::Vector3& worldTranslation);
/// Given a mouse interaction, determine if the pick ray from its position
/// in screen space intersected an aabb in world space.
bool AabbIntersectMouseRay(
const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb);
//! Given a mouse interaction, determine if the pick ray from its position
//! in screen space intersected an aabb in world space.
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb);
/// Return if a mouse interaction (pick ray) did intersect the tested EntityId.
//! Return if a mouse interaction (pick ray) did intersect the tested EntityId.
bool PickEntity(
AZ::EntityId entityId, const ViewportInteraction::MouseInteraction& mouseInteraction,
float& closestDistance, int viewportId);
AZ::EntityId entityId, const ViewportInteraction::MouseInteraction& mouseInteraction, float& closestDistance, int viewportId);
/// Wrapper for EBus call to return the CameraState for a given viewport.
//! Wrapper for EBus call to return the CameraState for a given viewport.
AzFramework::CameraState GetCameraState(int viewportId);
/// Wrapper for EBus call to return the DPI scaling for a given viewport.
float GetScreenDisplayScaling(const int viewportId);
//! Wrapper for EBus call to return the DPI scaling for a given viewport.
float GetScreenDisplayScaling(int viewportId);
/// A utility to return the center of several points.
/// Take several positions and store the min and max of each in
/// turn - when all points have been added return the center/midpoint.
//! A utility to return the center of several points.
//! Take several positions and store the min and max of each in
//! turn - when all points have been added return the center/midpoint.
class MidpointCalculator
{
public:
/// Default constructed with min and max initialized to opposites.
//! Default constructed with min and max initialized to opposites.
MidpointCalculator() = default;
/// Call this for all positions you want to be considered.
//! Call this for all positions you want to be considered.
void AddPosition(const AZ::Vector3& position)
{
m_minPosition = position.GetMin(m_minPosition);
m_maxPosition = position.GetMax(m_maxPosition);
}
/// Once all positions have been added, call this to return the midpoint.
//! Once all positions have been added, call this to return the midpoint.
AZ::Vector3 CalculateMidpoint() const
{
return m_minPosition + (m_maxPosition - m_minPosition) * 0.5f;
@@ -1,17 +1,17 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/RTTI/BehaviorContext.h>
#include "EditorTransformComponentSelectionRequestBus.h"
#include <AzCore/RTTI/BehaviorContext.h>
namespace AzToolsFramework
{
@@ -19,50 +19,68 @@ namespace AzToolsFramework
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
#define TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests() \
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) \
->Attribute(AZ::Script::Attributes::Category, "Editor") \
->Attribute(AZ::Script::Attributes::Module, "editor")
#define TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests() \
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) \
->Attribute(AZ::Script::Attributes::Category, "Editor") \
->Attribute(AZ::Script::Attributes::Module, "editor")
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Mode::Rotation)>("TransformMode_Rotation")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Mode::Translation)>("TransformMode_Translation")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Mode::Rotation)>(
"TransformMode_Rotation") TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Mode::Translation)>(
"TransformMode_Translation") TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Mode::Scale)>("TransformMode_Scale")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::RefreshType::Translation)>("TransformRefreshType_Translation")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::RefreshType::Orientation)>("TransformRefreshType_Orientation")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::RefreshType::All)>("TransformRefreshType_All")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::RefreshType::Translation)>(
"TransformRefreshType_Translation") TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::RefreshType::Orientation)>(
"TransformRefreshType_Orientation") TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::RefreshType::All)>(
"TransformRefreshType_All") TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Pivot::Object)>("TransformPivot_Object")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Pivot::Center)>("TransformPivot_Center")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Pivot::Object)>(
"TransformPivot_Object") TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EnumProperty<static_cast<int>(EditorTransformComponentSelectionRequests::Pivot::Center)>(
"TransformPivot_Center") TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests();
behaviorContext->EBus<EditorTransformComponentSelectionRequestBus>("EditorTransformComponentSelectionRequestBus")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests()
behaviorContext
->EBus<EditorTransformComponentSelectionRequestBus>("EditorTransformComponentSelectionRequestBus")
TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests()
->Event("SetTransformMode", &EditorTransformComponentSelectionRequestBus::Events::SetTransformMode)
->Event("GetTransformMode", &EditorTransformComponentSelectionRequestBus::Events::GetTransformMode)
// Reflecting GetManipulatorTransform will require hash<AZ::Transform> to be implemented, a pending task.
//->Event("GetManipulatorTransform", &EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform)
->Event("RefreshManipulators", &EditorTransformComponentSelectionRequestBus::Events::RefreshManipulators)
->Event("OverrideManipulatorOrientation", &EditorTransformComponentSelectionRequestBus::Events::OverrideManipulatorOrientation)
->Event("OverrideManipulatorTranslation", &EditorTransformComponentSelectionRequestBus::Events::OverrideManipulatorTranslation)
->Event("CopyTranslationToSelectedEntitiesIndividual", &EditorTransformComponentSelectionRequestBus::Events::CopyTranslationToSelectedEntitiesIndividual)
->Event("CopyTranslationToSelectedEntitiesGroup", &EditorTransformComponentSelectionRequestBus::Events::CopyTranslationToSelectedEntitiesGroup)
->Event("ResetTranslationForSelectedEntitiesLocal", &EditorTransformComponentSelectionRequestBus::Events::ResetTranslationForSelectedEntitiesLocal)
->Event("CopyOrientationToSelectedEntitiesIndividual", &EditorTransformComponentSelectionRequestBus::Events::CopyOrientationToSelectedEntitiesIndividual)
->Event("CopyOrientationToSelectedEntitiesGroup", &EditorTransformComponentSelectionRequestBus::Events::CopyOrientationToSelectedEntitiesGroup)
->Event("ResetOrientationForSelectedEntitiesLocal", &EditorTransformComponentSelectionRequestBus::Events::ResetOrientationForSelectedEntitiesLocal)
->Event("CopyScaleToSelectedEntitiesIndividualLocal", &EditorTransformComponentSelectionRequestBus::Events::CopyScaleToSelectedEntitiesIndividualLocal)
->Event("CopyScaleToSelectedEntitiesIndividualWorld", &EditorTransformComponentSelectionRequestBus::Events::CopyScaleToSelectedEntitiesIndividualWorld)
;
->Event(
"OverrideManipulatorOrientation", &EditorTransformComponentSelectionRequestBus::Events::OverrideManipulatorOrientation)
->Event(
"OverrideManipulatorTranslation", &EditorTransformComponentSelectionRequestBus::Events::OverrideManipulatorTranslation)
->Event(
"CopyTranslationToSelectedEntitiesIndividual",
&EditorTransformComponentSelectionRequestBus::Events::CopyTranslationToSelectedEntitiesIndividual)
->Event(
"CopyTranslationToSelectedEntitiesGroup",
&EditorTransformComponentSelectionRequestBus::Events::CopyTranslationToSelectedEntitiesGroup)
->Event(
"ResetTranslationForSelectedEntitiesLocal",
&EditorTransformComponentSelectionRequestBus::Events::ResetTranslationForSelectedEntitiesLocal)
->Event(
"CopyOrientationToSelectedEntitiesIndividual",
&EditorTransformComponentSelectionRequestBus::Events::CopyOrientationToSelectedEntitiesIndividual)
->Event(
"CopyOrientationToSelectedEntitiesGroup",
&EditorTransformComponentSelectionRequestBus::Events::CopyOrientationToSelectedEntitiesGroup)
->Event(
"ResetOrientationForSelectedEntitiesLocal",
&EditorTransformComponentSelectionRequestBus::Events::ResetOrientationForSelectedEntitiesLocal)
->Event(
"CopyScaleToSelectedEntitiesIndividualLocal",
&EditorTransformComponentSelectionRequestBus::Events::CopyScaleToSelectedEntitiesIndividualLocal)
->Event(
"CopyScaleToSelectedEntitiesIndividualWorld",
&EditorTransformComponentSelectionRequestBus::Events::CopyScaleToSelectedEntitiesIndividualWorld);
#undef TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests
#undef TEMP_SET_ATTRIBUTES_FOR_EditorTransformComponentSelectionRequests
}
}
} // namespace AzToolsFramework
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -16,12 +16,10 @@
#include <AzCore/Math/Transform.h>
#include <AzFramework/Entity/EntityContextBus.h>
namespace AzToolsFramework
{
/// Provide interface for EditorTransformComponentSelection requests.
class EditorTransformComponentSelectionRequests
: public AZ::EBusTraits
//! Provide interface for EditorTransformComponentSelection requests.
class EditorTransformComponentSelectionRequests : public AZ::EBusTraits
{
public:
using BusIdType = AzFramework::EntityContextId;
@@ -30,7 +28,7 @@ namespace AzToolsFramework
static void Reflect(AZ::ReflectContext* context);
/// What type of transform editing are we in.
//! What type of transform editing are we in.
enum class Mode
{
// note: ordering of these is important - do not change.
@@ -40,7 +38,7 @@ namespace AzToolsFramework
Scale
};
/// Specify the type of refresh (what type of transform modification caused the refresh).
//! Specify the type of refresh (what type of transform modification caused the refresh).
enum class RefreshType
{
Translation,
@@ -48,69 +46,69 @@ namespace AzToolsFramework
All
};
/// How is the pivot aligned (object/authored position or center).
//! How is the pivot aligned (object/authored position or center).
enum class Pivot
{
Object,
Center
};
/// Set what kind of transform the type that implements this bus should use.
//! Set what kind of transform the type that implements this bus should use.
virtual void SetTransformMode(Mode mode) = 0;
/// Return what transform mode the type that implements this bus is using.
//! Return what transform mode the type that implements this bus is using.
virtual Mode GetTransformMode() = 0;
/// Return the current Entity Manipulator transform.
/// An AZStd::optional<AZ::Transform> is returned as if we do not have a selection
/// there will be no Manipulator present. In this case we return an empty optional.
//! Return the current Entity Manipulator transform.
//! An AZStd::optional<AZ::Transform> is returned as if we do not have a selection
//! there will be no Manipulator present. In this case we return an empty optional.
virtual AZStd::optional<AZ::Transform> GetManipulatorTransform() = 0;
/// Refresh the Manipulator based on the current entity selection.
/// This may be useful if the Entity transform has been set outside
/// of the EditorTransformComponentSelection and we want to make sure the
/// Manipulator stays up to date (in sync) with the current Entity transform.
//! Refresh the Manipulator based on the current entity selection.
//! This may be useful if the Entity transform has been set outside
//! of the EditorTransformComponentSelection and we want to make sure the
//! Manipulator stays up to date (in sync) with the current Entity transform.
virtual void RefreshManipulators(RefreshType refreshType) = 0;
/// Set an orientation override for the Manipulator.
/// Useful if we've picked another Entity transform to use as our reference point.
//! Set an orientation override for the Manipulator.
//! Useful if we've picked another Entity transform to use as our reference point.
virtual void OverrideManipulatorOrientation(const AZ::Quaternion& orientation) = 0;
/// Set a translation override for the Manipulator.
/// Useful if we've picked another Entity transform to use as our reference point.
//! Set a translation override for the Manipulator.
//! Useful if we've picked another Entity transform to use as our reference point.
virtual void OverrideManipulatorTranslation(const AZ::Vector3& translation) = 0;
/// Copy translation to each individual entity so they all appear in the exact same position.
//! Copy translation to each individual entity so they all appear in the exact same position.
virtual void CopyTranslationToSelectedEntitiesIndividual(const AZ::Vector3& translation) = 0;
/// Copy translation to manipulator position with each entity keeping the same relative position as before.
//! Copy translation to manipulator position with each entity keeping the same relative position as before.
virtual void CopyTranslationToSelectedEntitiesGroup(const AZ::Vector3& translation) = 0;
/// Reset the translation of an entity to the same position as its parent.
/// Note: This is a noop if the entity does not have a parent.
//! Reset the translation of an entity to the same position as its parent.
//! Note: This is a noop if the entity does not have a parent.
virtual void ResetTranslationForSelectedEntitiesLocal() = 0;
/// Copy orientation to each individual entity so they all appear in the exact same orientation.
//! Copy orientation to each individual entity so they all appear in the exact same orientation.
virtual void CopyOrientationToSelectedEntitiesIndividual(const AZ::Quaternion& orientation) = 0;
/// Copy orientation to manipulator with each entity keeping the same relative orientation as before.
//! Copy orientation to manipulator with each entity keeping the same relative orientation as before.
virtual void CopyOrientationToSelectedEntitiesGroup(const AZ::Quaternion& orientation) = 0;
/// Reset the orientation of an entity to the same orientation as its parent.
/// Note: This will be the aligned to the world axes (identity) if the entity does not have a parent.
//! Reset the orientation of an entity to the same orientation as its parent.
//! Note: This will be the aligned to the world axes (identity) if the entity does not have a parent.
virtual void ResetOrientationForSelectedEntitiesLocal() = 0;
/// Copy scale to each individual entity in local space without moving position.
//! Copy scale to each individual entity in local space without moving position.
virtual void CopyScaleToSelectedEntitiesIndividualLocal(float scale) = 0;
/// Copy scale to to each individual entity in world (absolute) space.
//! Copy scale to to each individual entity in world (absolute) space.
virtual void CopyScaleToSelectedEntitiesIndividualWorld(float scale) = 0;
protected:
~EditorTransformComponentSelectionRequests() = default;
};
/// Type to inherit to implement EditorTransformComponentSelectionRequests.
//! Type to inherit to implement EditorTransformComponentSelectionRequests.
using EditorTransformComponentSelectionRequestBus = AZ::EBus<EditorTransformComponentSelectionRequests>;
} // namespace AzToolsFramework
@@ -1,33 +1,31 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorVisibleEntityDataCache.h"
#include <AzCore/std/sort.h>
#include <AzToolsFramework/Entity/EditorEntityModel.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityModel.h>
namespace AzToolsFramework
{
/// Cached Entity data required by the selection.
//! Cached Entity data required by the selection.
struct EntityData final
{
using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
EntityData() = default;
EntityData(
AZ::EntityId entityId, const AZ::Transform& worldFromLocal,
bool locked, bool visible, bool selected, bool iconHidden);
EntityData(AZ::EntityId entityId, const AZ::Transform& worldFromLocal, bool locked, bool visible, bool selected, bool iconHidden);
AZ::Transform m_worldFromLocal;
AZ::EntityId m_entityId;
@@ -38,7 +36,7 @@ namespace AzToolsFramework
bool m_iconHidden = false;
};
using EntityDatas = AZStd::vector<EntityData>; ///< Alias for vector of EntityDatas.
using EntityDatas = AZStd::vector<EntityData>; //!< Alias for vector of EntityDatas.
// Predicate to sort EntityIds with EntityDatas interchangeably.
struct EntityDataComparer
@@ -52,18 +50,27 @@ namespace AzToolsFramework
class EditorVisibleEntityDataCache::EditorVisibleEntityDataCacheImpl
{
public:
EntityIdList m_visibleEntityIds; ///< The EntityIds that are visible this frame.
EntityIdList m_prevVisibleEntityIds; ///< The EntityIds that were visible the previous frame (unsorted).
EntityDatas m_visibleEntityDatas; ///< Cached EntityData required by EditorTransformComponentSelection.
EntityIdList m_visibleEntityIds; //!< The EntityIds that are visible this frame.
EntityIdList m_prevVisibleEntityIds; //!< The EntityIds that were visible the previous frame (unsorted).
EntityDatas m_visibleEntityDatas; //!< Cached EntityData required by EditorTransformComponentSelection.
};
// constructor for EntityData to support emplace_back in vector
EntityData::EntityData(
const AZ::EntityId entityId, const AZ::Transform& worldFromLocal,
const bool locked, const bool visible, const bool selected, const bool iconHidden)
: m_worldFromLocal(worldFromLocal), m_entityId(entityId)
, m_locked(locked), m_visible(visible), m_selected(selected)
, m_iconHidden(iconHidden) {}
const AZ::EntityId entityId,
const AZ::Transform& worldFromLocal,
const bool locked,
const bool visible,
const bool selected,
const bool iconHidden)
: m_worldFromLocal(worldFromLocal)
, m_entityId(entityId)
, m_locked(locked)
, m_visible(visible)
, m_selected(selected)
, m_iconHidden(iconHidden)
{
}
bool EntityDataComparer::operator()(const AZ::EntityId lhs, const EntityData& rhs) const
{
@@ -98,20 +105,17 @@ namespace AzToolsFramework
static EntityData EntityDataFromEntityId(const AZ::EntityId entityId)
{
bool visible = false;
EditorEntityInfoRequestBus::EventResult(
visible, entityId, &EditorEntityInfoRequestBus::Events::IsVisible);
EditorEntityInfoRequestBus::EventResult(visible, entityId, &EditorEntityInfoRequestBus::Events::IsVisible);
bool locked = false;
EditorEntityInfoRequestBus::EventResult(
locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked);
EditorEntityInfoRequestBus::EventResult(locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked);
bool iconHidden = false;
EditorEntityIconComponentRequestBus::EventResult(
iconHidden, entityId, &EditorEntityIconComponentRequests::IsEntityIconHiddenInViewport);
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(
worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
return { entityId, worldFromLocal, locked, visible, IsSelected(entityId), iconHidden };
}
@@ -155,16 +159,14 @@ namespace AzToolsFramework
AZStd::sort(m_impl->m_visibleEntityDatas.begin(), m_impl->m_visibleEntityDatas.end());
}
void EditorVisibleEntityDataCache::CalculateVisibleEntityDatas(
const AzFramework::ViewportInfo& viewportInfo)
void EditorVisibleEntityDataCache::CalculateVisibleEntityDatas(const AzFramework::ViewportInfo& viewportInfo)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
// request list of visible entities from authoritative system
EntityIdList nextVisibleEntityIds;
ViewportInteraction::MainEditorViewportInteractionRequestBus::Event(
viewportInfo.m_viewportId,
&ViewportInteraction::MainEditorViewportInteractionRequestBus::Events::FindVisibleEntities,
viewportInfo.m_viewportId, &ViewportInteraction::MainEditorViewportInteractionRequestBus::Events::FindVisibleEntities,
nextVisibleEntityIds);
// only bother resorting if we know the lists have changed
@@ -181,31 +183,26 @@ namespace AzToolsFramework
// find entities that are visible this frame but weren't last frame
AZStd::vector<AZ::EntityId> added;
std::set_difference(
m_impl->m_visibleEntityIds.begin(), m_impl->m_visibleEntityIds.end(),
m_impl->m_visibleEntityDatas.begin(), m_impl->m_visibleEntityDatas.end(),
std::back_inserter(added), EntityDataComparer());
m_impl->m_visibleEntityIds.begin(), m_impl->m_visibleEntityIds.end(), m_impl->m_visibleEntityDatas.begin(),
m_impl->m_visibleEntityDatas.end(), std::back_inserter(added), EntityDataComparer());
// find entities that are not visible this frame but were last frame
AZStd::vector<EntityData> removed;
std::set_difference(
m_impl->m_visibleEntityDatas.begin(), m_impl->m_visibleEntityDatas.end(),
m_impl->m_visibleEntityIds.begin(), m_impl->m_visibleEntityIds.end(),
std::back_inserter(removed), EntityDataComparer());
m_impl->m_visibleEntityDatas.begin(), m_impl->m_visibleEntityDatas.end(), m_impl->m_visibleEntityIds.begin(),
m_impl->m_visibleEntityIds.end(), std::back_inserter(removed), EntityDataComparer());
// search for entityData in removed list, return true if it is found
const auto removePredicate = [&removed](const EntityData& entityData)
{
const auto removeIt = std::equal_range(
removed.begin(), removed.end(), entityData);
const auto removeIt = std::equal_range(removed.begin(), removed.end(), entityData);
return removeIt.first != removeIt.second;
};
// erase-remove idiom - bubble entities to be removed to the end, then erase them in one go
m_impl->m_visibleEntityDatas.erase(
AZStd::remove_if(
m_impl->m_visibleEntityDatas.begin(),
m_impl->m_visibleEntityDatas.end(), removePredicate),
AZStd::remove_if(m_impl->m_visibleEntityDatas.begin(), m_impl->m_visibleEntityDatas.end(), removePredicate),
m_impl->m_visibleEntityDatas.end());
// for newly added entities, request their initial state when first cached
@@ -240,8 +237,7 @@ namespace AzToolsFramework
return m_impl->m_visibleEntityDatas[index].m_entityId;
}
EditorVisibleEntityDataCache::ComponentEntityAccentType EditorVisibleEntityDataCache::GetVisibleEntityAccent(
const size_t index) const
EditorVisibleEntityDataCache::ComponentEntityAccentType EditorVisibleEntityDataCache::GetVisibleEntityAccent(const size_t index) const
{
return m_impl->m_visibleEntityDatas[index].m_accent;
}
@@ -273,8 +269,8 @@ namespace AzToolsFramework
AZStd::optional<size_t> EditorVisibleEntityDataCache::GetVisibleEntityIndexFromId(const AZ::EntityId entityId) const
{
const auto entityIdIt = std::equal_range(
m_impl->m_visibleEntityDatas.begin(), m_impl->m_visibleEntityDatas.end(), entityId, EntityDataComparer());
const auto entityIdIt =
std::equal_range(m_impl->m_visibleEntityDatas.begin(), m_impl->m_visibleEntityDatas.end(), entityId, EntityDataComparer());
if (entityIdIt.first != entityIdIt.second)
{
@@ -318,8 +314,7 @@ namespace AzToolsFramework
}
}
void EditorVisibleEntityDataCache::OnTransformChanged(
const AZ::Transform& /*local*/, const AZ::Transform& world)
void EditorVisibleEntityDataCache::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -367,8 +362,7 @@ namespace AzToolsFramework
}
}
void EditorVisibleEntityDataCache::OnEntityIconChanged(
const AZ::Data::AssetId& /*entityIconAssetId*/)
void EditorVisibleEntityDataCache::OnEntityIconChanged(const AZ::Data::AssetId& /*entityIconAssetId*/)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
@@ -22,8 +22,8 @@
namespace AzToolsFramework
{
/// A cache of packed EntityData that can be iterated over efficiently without
/// the need to make individual EBus calls
//! A cache of packed EntityData that can be iterated over efficiently without
//! the need to make individual EBus calls
class EditorVisibleEntityDataCache
: private EditorEntityVisibilityNotificationBus::Router
, private EditorEntityLockComponentNotificationBus::Router
@@ -45,7 +45,7 @@ namespace AzToolsFramework
void CalculateVisibleEntityDatas(const AzFramework::ViewportInfo& viewportInfo);
/// EditorVisibleEntityDataCache interface
//! EditorVisibleEntityDataCache interface
size_t VisibleEntityDataCount() const;
AZ::Vector3 GetVisibleEntityPosition(size_t index) const;
const AZ::Transform& GetVisibleEntityTransform(size_t index) const;
@@ -72,8 +72,7 @@ namespace AzToolsFramework
void OnEntityLockChanged(bool locked) override;
// TransformNotificationBus
void OnTransformChanged(
const AZ::Transform& local, const AZ::Transform& world) override;
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
// EditorComponentSelectionNotificationsBus
void OnAccentTypeChanged(EntityAccentType accent) override;
@@ -86,6 +85,6 @@ namespace AzToolsFramework
void OnEntityIconChanged(const AZ::Data::AssetId& entityIconAssetId) override;
class EditorVisibleEntityDataCacheImpl;
AZStd::unique_ptr<EditorVisibleEntityDataCacheImpl> m_impl; ///< Internal representation of entity data cache.
AZStd::unique_ptr<EditorVisibleEntityDataCacheImpl> m_impl; //!< Internal representation of entity data cache.
};
} // namespace AzToolsFramework
@@ -108,6 +108,61 @@ namespace AzToolsFramework::ViewportUi::Internal
m_widgetCallbacks.Update();
}
void ViewportUiCluster::SetButtonLocked(const ButtonId buttonId, const bool isLocked)
{
const auto& buttons = m_buttonGroup->GetButtons();
// unlocked previously locked button
if (m_lockedButtonId.has_value() && isLocked)
{
// find the button to extract the old icon (without overlay)
auto findLocked = [this](const Button* button) { return (button->m_buttonId == m_lockedButtonId); };
if (auto lockedButtonIt = AZStd::find_if(buttons.begin(), buttons.end(), findLocked); lockedButtonIt != buttons.end())
{
// get the action corresponding to the lockedButtonId
if (auto actionEntry = m_buttonActionMap.find(m_lockedButtonId.value()); actionEntry != m_buttonActionMap.end())
{
// remove the overlay
auto action = actionEntry->second;
action->setIcon(QIcon(QString((*lockedButtonIt)->m_icon.c_str())));
}
}
}
auto found = [buttonId](Button* button) { return (button->m_buttonId == buttonId); };
if (auto buttonIt = AZStd::find_if(buttons.begin(), buttons.end(), found); buttonIt != buttons.end())
{
QIcon newIcon;
if (isLocked)
{
// overlay the locked icon ontop of the button's icon
QPixmap comboPixmap(24, 24);
comboPixmap.fill(Qt::transparent);
QPixmap firstImage(QString((*buttonIt)->m_icon.c_str()));
QPixmap secondImage(QString(":/stylesheet/img/UI20/toolbar/Locked_Status.svg"));
QPainter painter(&comboPixmap);
painter.drawPixmap(0, 0, firstImage);
painter.drawPixmap(0, 0, secondImage);
newIcon.addPixmap(comboPixmap);
m_lockedButtonId = buttonId;
}
else
{
// remove the overlay
newIcon = QIcon(QString((*buttonIt)->m_icon.c_str()));
m_lockedButtonId = AZStd::nullopt;
}
if (auto actionEntry = m_buttonActionMap.find(buttonId); actionEntry != m_buttonActionMap.end())
{
auto action = actionEntry->second;
action->setIcon(newIcon);
}
}
}
ViewportUiWidgetCallbacks ViewportUiCluster::GetWidgetCallbacks()
{
return m_widgetCallbacks;
@@ -17,6 +17,7 @@
#include <AzToolsFramework/ViewportUi/Button.h>
#include <AzToolsFramework/ViewportUi/ViewportUiWidgetCallbacks.h>
#include <QToolBar>
#include <QPainter>
namespace AzToolsFramework::ViewportUi::Internal
{
@@ -38,6 +39,8 @@ namespace AzToolsFramework::ViewportUi::Internal
void RemoveButton(ButtonId buttonId);
//! Updates all registered actions.
void Update();
//! Adds a locked overlay to the button's icon.
void SetButtonLocked(ButtonId buttonId, bool isLocked);
//! Returns the widget manager.
ViewportUiWidgetCallbacks GetWidgetCallbacks();
@@ -52,5 +55,6 @@ namespace AzToolsFramework::ViewportUi::Internal
AZStd::shared_ptr<ButtonGroup> m_buttonGroup; //!< Data structure which the cluster will be displaying to the Viewport UI.
AZStd::unordered_map<ButtonId, QPointer<QAction>> m_buttonActionMap; //!< Map for buttons to their corresponding actions.
ViewportUiWidgetCallbacks m_widgetCallbacks; //!< Registers actions and manages updates.
AZStd::optional<ButtonId> m_lockedButtonId = AZStd::nullopt; //!< Used to track the last button locked.
};
} // namespace AzToolsFramework::ViewportUi::Internal
@@ -100,6 +100,14 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
void ViewportUiDisplay::SetClusterButtonLocked(const ViewportUiElementId clusterId, const ButtonId buttonId, const bool isLocked)
{
if (auto viewportUiCluster = qobject_cast<ViewportUiCluster*>(GetViewportUiElement(clusterId).get()))
{
viewportUiCluster->SetButtonLocked(buttonId, isLocked);
}
}
void ViewportUiDisplay::RemoveClusterButton(ViewportUiElementId clusterId, ButtonId buttonId)
{
if (auto cluster = qobject_cast<ViewportUiCluster*>(GetViewportUiElement(clusterId).get()))
@@ -58,6 +58,7 @@ namespace AzToolsFramework::ViewportUi::Internal
void AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment align);
void AddClusterButton(ViewportUiElementId clusterId, Button* button);
void SetClusterButtonLocked(ViewportUiElementId clusterId, ButtonId buttonId, bool isLocked);
void RemoveClusterButton(ViewportUiElementId clusterId, ButtonId buttonId);
void UpdateCluster(const ViewportUiElementId clusterId);
@@ -67,6 +67,16 @@ namespace AzToolsFramework::ViewportUi
}
}
void ViewportUiManager::SetClusterButtonLocked(const ClusterId clusterId, const ButtonId buttonId, const bool isLocked)
{
if (auto clusterIt = m_clusterButtonGroups.find(clusterId); clusterIt != m_clusterButtonGroups.end())
{
auto cluster = clusterIt->second;
m_viewportUi->SetClusterButtonLocked(cluster->GetViewportUiElementId(), buttonId, isLocked);
UpdateButtonGroupUi(cluster.get());
}
}
void ViewportUiManager::RegisterClusterEventHandler(const ClusterId clusterId, AZ::Event<ButtonId>::Handler& handler)
{
if (auto clusterIt = m_clusterButtonGroups.find(clusterId); clusterIt != m_clusterButtonGroups.end())
@@ -35,6 +35,7 @@ namespace AzToolsFramework::ViewportUi
const SwitcherId CreateSwitcher(Alignment align) override;
void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) override;
void SetSwitcherActiveButton(SwitcherId switcherId, ButtonId buttonId) override;
void SetClusterButtonLocked(ClusterId clusterId, ButtonId buttonId, bool isLocked) override;
const ButtonId CreateClusterButton(ClusterId clusterId, const AZStd::string& icon) override;
const ButtonId CreateSwitcherButton(
SwitcherId switcherId, const AZStd::string& icon, const AZStd::string& name = AZStd::string()) override;

Some files were not shown because too many files have changed in this diff Show More