Merge branch 'main' into Atom/antonmic/PassChanges

This commit is contained in:
antonmic
2021-06-10 14:34:18 -07:00
213 changed files with 1514 additions and 2694 deletions
@@ -0,0 +1,5 @@
This is the UUID for libs / particles / milestone2particles . xml.
6BDE282B49C957F7B0714B26579BCA9A
This isn an invalid UUID
33bdee92F3225688ABEE534F6058593F
This is another invalid UUID B076CDDC-14DK-50F4-A5E9-7518ABB3E851
@@ -1,14 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// If you make changes in ICryPak.h, make changes here, to dirty the PCH.
#include "CrySystem_precompiled.h"
@@ -75,6 +75,5 @@ set(FILES
ViewSystem/View.h
ViewSystem/ViewSystem.cpp
ViewSystem/ViewSystem.h
CrySystem_precompiled.cpp
WindowsErrorReporting.cpp
)
@@ -37,9 +37,10 @@ namespace AzPhysics
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<TriggerEvent>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Method("GetTriggerEntityId", &TriggerEvent::GetTriggerEntityId)
->Method("GetOtherEntityId", &TriggerEvent::GetOtherEntityId)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "Physics")
->Method("Get Trigger EntityId", &TriggerEvent::GetTriggerEntityId)
->Method("Get Other EntityId", &TriggerEvent::GetOtherEntityId)
;
}
}
@@ -104,10 +105,11 @@ namespace AzPhysics
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<CollisionEvent>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Property("Contacts", BehaviorValueProperty(&CollisionEvent::m_contacts))
->Method("GetBody1EntityId", &CollisionEvent::GetBody1EntityId)
->Method("GetBody2EntityId", &CollisionEvent::GetBody2EntityId)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "Physics")
->Property("Contacts", BehaviorValueGetter(&CollisionEvent::m_contacts), nullptr)
->Method("Get Body 1 EntityId", &CollisionEvent::GetBody1EntityId)
->Method("Get Body 2 EntityId", &CollisionEvent::GetBody2EntityId)
;
}
}
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Camera </title>
<g id="Camera-" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icon-2" fill="#FFFFFF" transform="translate(1.666667, 4.166667)">
<path d="M11.5739175,9.2927927 C11.5739175,9.54639717 11.3384276,9.99926232 10.8312187,9.99926232 C10.3240097,9.99926232 2.37169783,10.0264342 2.13620796,10.0264342 C1.74674394,10.0264342 1.33916531,9.69131402 1.33916531,9.09353203 C1.33916531,8.76746913 1.35126587,5.13853395 1.35126587,4.84870026 C1.35126587,4.37772052 1.35727992,4.13013009 1.81014506,4.13013009 C2.2630102,4.13013009 10.840276,4.11201548 10.840276,4.11201548 C11.4199434,4.11201548 11.5829748,4.51959411 11.5829748,4.86377162 C11.5829748,5.20794912 11.5739175,9.03918822 11.5739175,9.2927927 L11.5739175,9.2927927 Z M2.65247422,1.24990779 C2.65247422,1.09593364 2.65247422,0.941959493 2.77927646,0.941959493 L9.83491536,0.941959493 C10.0070041,0.941959493 10.2062648,0.978188705 10.2062648,1.16839206 C10.2062648,1.35859542 10.1972075,2.73530545 10.1972075,2.73530545 L2.64943097,2.7111768 L2.65247422,1.24990779 Z M16.9539554,4.02144245 L16.374288,4.03049976 L14.6896297,5.50684012 L14.2548791,5.50684012 C14.2548791,5.50684012 13.1317736,3.56857731 13.0049713,3.31497283 C12.8781691,3.06136835 12.4615332,2.77153466 12.2622725,2.77153466 L11.139167,2.77153466 C11.139167,2.77153466 11.1210524,0.905730282 11.1210524,0.579667381 C11.1210524,0.253604479 10.8131041,2.81996648e-13 10.4145827,2.81996648e-13 L2.22678099,2.81996648e-13 C1.86144562,2.81996648e-13 1.66522821,0.208317965 1.66522821,0.45887919 L1.66522821,2.69907624 C1.3325716,2.7055975 1.26148988,2.70509029 1.06744623,2.70509029 C0.626681643,2.70509029 0.43343503,2.86812174 0.43343503,3.51423349 L0.43343503,9.83623086 C0.43343503,10.5698724 0.804784446,10.8778207 1.36633722,10.8778207 C1.72862933,10.8778207 11.5920321,10.8687634 12.0992411,10.8687634 C12.60645,10.8687634 12.8238253,10.4340129 13.0049713,10.198523 C13.1861174,9.9630331 14.309223,8.11534333 14.309223,8.11534333 L14.8164319,8.09722872 L16.4558037,9.60074099 L16.97207,9.60074099 L16.9539554,4.02144245 Z" id="Icon"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>debug</title>
<g id="debug" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M11.3615865,7.917238 L15.2274672,9.63843901 L16.4675037,9.16172668 C16.6979214,9.07292417 16.9553551,9.18924382 17.0442998,9.41972476 C17.1330234,9.64993705 17.0253844,9.89284574 16.7952509,9.98177479 L16.7952509,9.98177479 L15.3951151,10.4956726 C15.2842902,10.5384499 15.1889358,10.4726675 15.0806503,10.4244557 L15.0806503,10.4244557 L14.1703124,10.0191471 C14.3857263,10.9664393 14.4599954,12.0211666 14.2565873,12.952264 L14.2565873,12.952264 L15.6721159,13.5824979 C15.8976398,13.6829076 15.9908466,13.9650071 15.8904369,14.190531 C15.7900905,14.4159128 15.5180189,14.5355501 15.292495,14.4351404 L15.292495,14.4351404 L13.9556938,13.8399581 C13.6322377,14.54733 13.1335636,15.1766897 12.5630158,15.6037725 L12.5630158,15.6037725 L12.8756514,15.7429668 C12.983937,15.7911787 13.0605157,15.8995144 13.1027401,16.0104336 L13.1027401,16.0104336 L13.6353002,17.4447605 C13.7234077,17.6752093 13.6080984,17.9334334 13.3776496,18.021541 C13.2626228,18.0653422 13.1408059,18.058613 13.0364993,18.0121727 C12.9319085,17.9656059 12.8452864,17.8786807 12.8011855,17.7631798 L12.8011855,17.7631798 L12.3264968,16.520128 L11.644667,16.2165578 C10.4621412,16.7117239 8.87932984,16.9345084 7.56328989,16.4483518 L7.56328989,16.4483518 L11.3615865,7.917238 Z M5.52878415,4.3232224 C5.75937506,4.23517812 6.01946614,4.34552927 6.10779463,4.57624672 L6.10779463,4.57624672 L6.58675456,5.80894035 L10.4526353,7.53014136 L6.6529468,16.0643815 C5.4063142,15.4223335 4.43289769,14.215203 4.07288375,12.8629772 L4.07288375,12.8629772 L3.41379116,12.5695302 L2.17275891,13.0473317 C2.05755786,13.0919067 1.93523585,13.0847824 1.83064504,13.0382156 C1.72633845,12.9917753 1.64104404,12.9033978 1.59654788,12.7884022 C1.5078242,12.5581899 1.62471629,12.294881 1.85492858,12.2061574 L1.85492858,12.2061574 L3.27301757,11.6515537 C3.38384243,11.6087763 3.51545059,11.5931314 3.62387829,11.6414065 L3.62387829,11.6414065 L3.91988732,11.7731982 C3.85933759,11.0651327 3.99592287,10.2745607 4.30516824,9.5608618 L4.30516824,9.5608618 L2.97859873,8.970235 C2.7530748,8.86982528 2.6599312,8.58758374 2.76027765,8.36220193 C2.86068737,8.13667801 3.13269567,8.01718285 3.35821959,8.11759257 L3.35821959,8.11759257 L4.7450425,8.73504591 C5.26222301,7.94364898 6.01359598,7.25652125 6.89624338,6.79811742 L6.89624338,6.79811742 L6.10101221,6.4440577 C5.99258451,6.39578258 5.88032145,6.36759526 5.83803372,6.25681811 L5.83803372,6.25681811 L5.26971048,4.90243425 C5.18174504,4.67204872 5.29833534,4.41132994 5.52878415,4.3232224 Z M10.8942352,2.34455584 C11.1427316,2.24942103 11.4210854,2.3733521 11.5165098,2.62161032 L11.5165098,2.62161032 L11.9777045,3.8224019 C12.2035494,3.86678469 12.4283918,3.93403345 12.6476126,4.03163684 C12.8668334,4.12924023 13.0677354,4.25026013 13.2518379,4.38839772 L13.2518379,4.38839772 L14.4533966,3.92589245 C14.7019612,3.83060445 14.9816108,3.95162483 15.0770352,4.19988305 C15.1723915,4.44829447 15.0509158,4.72113321 14.8025726,4.81633622 L14.8025726,4.81633622 L13.9775725,5.12324418 C14.5520125,5.98310253 14.7248639,7.02632912 14.247419,8.09868801 L14.247419,8.09868801 L8.55503156,5.56427385 C9.03247651,4.49191495 9.9234901,3.92253515 10.946252,3.77379694 L10.946252,3.77379694 L10.6171125,2.96698358 C10.5217563,2.71857217 10.6457388,2.43969065 10.8942352,2.34455584 Z" id="Combined-Shape" fill="#FFFFFF"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>resolution</title>
<g id="resolution" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M17.7222222,2.5 L17.7222222,17.7222222 L2.5,17.7222222 L2.5,2.5 L17.7222222,2.5 Z M16.721,4.45 L3.499,4.45 L3.499,10.111 L10.1293705,10.1111111 L10.129,16.722 L16.722,16.722 L16.721,4.45 Z M9.128,11.722 L3.999,11.722 L4,16.222 L9.129,16.222 L9.128,11.722 Z" id="Combined-Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 654 B

@@ -15,4 +15,9 @@
<file alias="download.svg">Notifications/download.svg</file>
<file alias="link.svg">Notifications/link.svg</file>
</qresource>
<qresource prefix="/Menu">
<file alias="resolution.svg">Menu/resolution.svg</file>
<file alias="debug.svg">Menu/debug.svg</file>
<file alias="camera.svg">Menu/camera.svg</file>
</qresource>
</RCC>
@@ -42,6 +42,9 @@ namespace AzToolsFramework
bool detachedWindow = false; ///< set to true if the view pane should use a detached, non-dockable widget. This is to workaround a problem with QOpenGLWidget on macOS. Currently this has no effect on other platforms.
bool isDisabledInSimMode = false; ///< set to true if the view pane should not be openable from level editor menu when editor is in simulation mode.
bool showOnToolsToolbar = false; ///< set to true if the view pane should create a button on the tools toolbar to open/close the pane
QString toolbarIcon; ///< path to the icon to use for the toolbar button - only used if showOnToolsToolbar is set to true
};
} // namespace AzToolsFramework
@@ -1,13 +0,0 @@
/*
* 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 "AzToolsFramework_precompiled.h"
@@ -197,7 +197,7 @@ namespace AzToolsFramework
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override;
Prefab::InstanceOptionalReference GetRootPrefabInstance() override;
const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& GetPlayInEditorAssetData() override;
//////////////////////////////////////////////////////////////////////////
@@ -47,8 +47,13 @@ namespace AzToolsFramework
virtual void AppendEntityAliasToPatchPaths(PrefabDom& providedPatch, const AZ::EntityId& entityId) = 0;
//! Updates the template links (updating instances) for the given templateId using the providedPatch
virtual bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId) = 0;
//! Updates the template links (updating instances) for the given template and triggers propagation on its instances.
//! @param providedPatch The patch to apply to the template.
//! @param templateId The id of the template to update.
//! @param instanceToExclude An optional reference to an instance of the template being updated that should not be refreshes as part of propagation.
//! Defaults to nullopt, which means that all instances will be refreshed.
//! @return True if the template was patched correctly, false if the operation failed.
virtual bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
virtual void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) = 0;
@@ -172,7 +172,7 @@ namespace AzToolsFramework
}
}
bool InstanceToTemplatePropagator::PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId)
bool InstanceToTemplatePropagator::PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude)
{
PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
@@ -184,7 +184,7 @@ namespace AzToolsFramework
if (result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success)
{
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId);
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
return true;
}
else
@@ -37,7 +37,7 @@ namespace AzToolsFramework
InstanceOptionalReference GetTopMostInstanceInHierarchy(AZ::EntityId entityId);
bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId) override;
bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) override;
@@ -56,7 +56,7 @@ namespace AzToolsFramework
AZ::Interface<InstanceUpdateExecutorInterface>::Unregister(this);
}
void InstanceUpdateExecutor::AddTemplateInstancesToQueue(TemplateId instanceTemplateId)
void InstanceUpdateExecutor::AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude)
{
auto findInstancesResult =
m_templateInstanceMapperInterface->FindInstancesOwnedByTemplate(instanceTemplateId);
@@ -70,9 +70,18 @@ namespace AzToolsFramework
return;
}
Instance* instanceToExcludePtr = nullptr;
if (instanceToExclude.has_value())
{
instanceToExcludePtr = &(instanceToExclude->get());
}
for (auto instance : findInstancesResult->get())
{
m_instancesUpdateQueue.emplace_back(instance);
if (instance != instanceToExcludePtr)
{
m_instancesUpdateQueue.emplace_back(instance);
}
}
}
@@ -103,7 +112,7 @@ namespace AzToolsFramework
EntityIdList selectedEntityIds;
ToolsApplicationRequestBus::BroadcastResult(selectedEntityIds, &ToolsApplicationRequests::GetSelectedEntities);
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, EntityIdList());
PrefabDom instanceDomFromRootDocument;
// Process all instances in the queue, capped to the batch size.
// Even though we potentially initialized the batch size to the queue, it's possible for the queue size to shrink
@@ -148,13 +157,62 @@ namespace AzToolsFramework
continue;
}
Template& currentTemplate = currentTemplateReference->get();
Instance::EntityList newEntities;
if (PrefabDomUtils::LoadInstanceFromPrefabDom(*instanceToUpdate, newEntities, currentTemplate.GetPrefabDom()))
// Climb up to the root of the instance hierarchy from this instance
InstanceOptionalConstReference rootInstance = *instanceToUpdate;
AZStd::vector<InstanceOptionalConstReference> pathOfInstances;
while (rootInstance->get().GetParentInstance() != AZStd::nullopt)
{
// If a link was created for a nested instance before the changes were propagated,
// then we associate it correctly here
instanceToUpdate->GetNestedInstances([&](AZStd::unique_ptr<Instance>& nestedInstance) {
pathOfInstances.emplace_back(rootInstance);
rootInstance = rootInstance->get().GetParentInstance();
}
AZStd::string aliasPathResult = "";
for (auto instanceIter = pathOfInstances.rbegin(); instanceIter != pathOfInstances.rend(); ++instanceIter)
{
aliasPathResult.append("/Instances/");
aliasPathResult.append((*instanceIter)->get().GetInstanceAlias());
}
PrefabDomPath rootPrefabDomPath(aliasPathResult.c_str());
PrefabDom& rootPrefabTemplateDom =
m_prefabSystemComponentInterface->FindTemplateDom(rootInstance->get().GetTemplateId());
auto instanceDomFromRootValue = rootPrefabDomPath.Get(rootPrefabTemplateDom);
if (!instanceDomFromRootValue)
{
AZ_Assert(
false,
"InstanceUpdateExecutor::UpdateTemplateInstancesInQueue - "
"Could not load Instance DOM from the top level ancestor's DOM.");
isUpdateSuccessful = false;
continue;
}
PrefabDomValueReference instanceDomFromRoot = *instanceDomFromRootValue;
if (!instanceDomFromRoot.has_value())
{
AZ_Assert(
false,
"InstanceUpdateExecutor::UpdateTemplateInstancesInQueue - "
"Could not load Instance DOM from the top level ancestor's DOM.");
isUpdateSuccessful = false;
continue;
}
// If a link was created for a nested instance before the changes were propagated,
// then we associate it correctly here
instanceDomFromRootDocument.CopyFrom(instanceDomFromRoot->get(), instanceDomFromRootDocument.GetAllocator());
if (PrefabDomUtils::LoadInstanceFromPrefabDom(*instanceToUpdate, newEntities, instanceDomFromRootDocument))
{
Template& currentTemplate = currentTemplateReference->get();
instanceToUpdate->GetNestedInstances([&](AZStd::unique_ptr<Instance>& nestedInstance)
{
if (nestedInstance->GetLinkId() != InvalidLinkId)
{
return;
@@ -179,22 +237,11 @@ namespace AzToolsFramework
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, newEntities);
}
else
{
AZ_Error(
"Prefab", false,
"InstanceUpdateExecutor::UpdateTemplateInstancesInQueue - "
"Could not load Instance from Prefab DOM of Template with Id '%llu' on file path '%s'.",
currentTemplateId, currentTemplate.GetFilePath().c_str());
isUpdateSuccessful = false;
}
}
for (auto entityIdIterator = selectedEntityIds.begin(); entityIdIterator != selectedEntityIds.end(); entityIdIterator++)
{
// Since entities get recreated during propagation, we need to check whether the entities correspoding to the list
// of selected entity ids are present or not.
// Since entities get recreated during propagation, we need to check whether the entities
// corresponding to the list of selected entity ids are present or not.
AZ::Entity* entity = GetEntityById(*entityIdIterator);
if (entity == nullptr)
{
@@ -35,7 +35,7 @@ namespace AzToolsFramework
explicit InstanceUpdateExecutor(int instanceCountToUpdateInBatch = 0);
void AddTemplateInstancesToQueue(TemplateId instanceTemplateId) override;
void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
bool UpdateTemplateInstancesInQueue() override;
virtual void RemoveTemplateInstanceFromQueue(const Instance* instance) override;
@@ -27,7 +27,7 @@ namespace AzToolsFramework
virtual ~InstanceUpdateExecutorInterface() = default;
// Add all Instances of Template with given Id into a queue for updating them later.
virtual void AddTemplateInstancesToQueue(TemplateId instanceTemplateId) = 0;
virtual void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
// Update Instances in the waiting queue.
virtual bool UpdateTemplateInstancesInQueue() = 0;
@@ -242,11 +242,13 @@ namespace AzToolsFramework
m_instanceToTemplateInterface->GenerateDomForEntity(containerAfterReset, *containerEntity);
// Update the state of the entity
PrefabUndoEntityUpdate* state = aznew PrefabUndoEntityUpdate(AZStd::to_string(static_cast<AZ::u64>(containerEntityId)));
state->SetParent(undoBatch.GetUndoBatch());
state->Capture(containerBeforeReset, containerAfterReset, containerEntityId);
auto templateId = instanceToCreate->get().GetTemplateId();
state->Redo();
PrefabDom transformPatch;
m_instanceToTemplateInterface->GeneratePatch(transformPatch, containerBeforeReset, containerAfterReset);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(transformPatch, containerEntityId);
m_instanceToTemplateInterface->PatchTemplate(transformPatch, templateId);
}
// This clears any entities marked as dirty due to reparenting of entities during the process of creating a prefab.
@@ -661,12 +663,12 @@ namespace AzToolsFramework
else
{
Internal_HandleContainerOverride(
parentUndoBatch, entityId, patch, owningInstance->get().GetLinkId());
parentUndoBatch, entityId, patch, owningInstance->get().GetLinkId(), owningInstance->get().GetParentInstance());
}
}
else
{
Internal_HandleEntityChange(parentUndoBatch, entityId, beforeState, afterState);
Internal_HandleEntityChange(parentUndoBatch, entityId, beforeState, afterState, owningInstance);
if (isNewParentOwnedByDifferentInstance)
{
@@ -679,25 +681,27 @@ namespace AzToolsFramework
}
void PrefabPublicHandler::Internal_HandleContainerOverride(
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, const PrefabDom& patch, const LinkId linkId)
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, const PrefabDom& patch,
const LinkId linkId, InstanceOptionalReference parentInstance)
{
// Save these changes as patches to the link
PrefabUndoLinkUpdate* linkUpdate = aznew PrefabUndoLinkUpdate(AZStd::to_string(static_cast<AZ::u64>(entityId)));
linkUpdate->SetParent(undoBatch);
linkUpdate->Capture(patch, linkId);
linkUpdate->Redo();
linkUpdate->Redo(parentInstance);
}
void PrefabPublicHandler::Internal_HandleEntityChange(
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, PrefabDom& beforeState, PrefabDom& afterState)
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, PrefabDom& beforeState,
PrefabDom& afterState, InstanceOptionalReference instance)
{
// Update the state of the entity
PrefabUndoEntityUpdate* state = aznew PrefabUndoEntityUpdate(AZStd::to_string(static_cast<AZ::u64>(entityId)));
state->SetParent(undoBatch);
state->Capture(beforeState, afterState, entityId);
state->Redo();
state->Redo(instance);
}
void PrefabPublicHandler::Internal_HandleInstanceChange(
@@ -162,9 +162,11 @@ namespace AzToolsFramework
InstanceOptionalConstReference instance, const AZStd::unordered_set<AZ::IO::Path>& templateSourcePaths);
static void Internal_HandleContainerOverride(
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, const PrefabDom& patch, const LinkId linkId);
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, const PrefabDom& patch,
const LinkId linkId, InstanceOptionalReference parentInstance = AZStd::nullopt);
static void Internal_HandleEntityChange(
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, PrefabDom& beforeState, PrefabDom& afterState);
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId entityId, PrefabDom& beforeState,
PrefabDom& afterState, InstanceOptionalReference instance = AZStd::nullopt);
void Internal_HandleInstanceChange(UndoSystem::URSequencePoint* undoBatch, AZ::Entity* entity, AZ::EntityId beforeParentId, AZ::EntityId afterParentId);
void UpdateLinkPatchesWithNewEntityAliases(
@@ -141,8 +141,10 @@ namespace AzToolsFramework
return newInstance;
}
void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId)
void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude)
{
UpdatePrefabInstances(templateId, instanceToExclude);
auto templateIdToLinkIdsIterator = m_templateToLinkIdsMap.find(templateId);
if (templateIdToLinkIdsIterator != m_templateToLinkIdsMap.end())
{
@@ -153,10 +155,6 @@ namespace AzToolsFramework
templateIdToLinkIdsIterator->second.end()));
UpdateLinkedInstances(linkIdsToUpdateQueue);
}
else
{
UpdatePrefabInstances(templateId);
}
}
void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom)
@@ -174,9 +172,9 @@ namespace AzToolsFramework
}
}
void PrefabSystemComponent::UpdatePrefabInstances(const TemplateId& templateId)
void PrefabSystemComponent::UpdatePrefabInstances(const TemplateId& templateId, InstanceOptionalReference instanceToExclude)
{
m_instanceUpdateExecutor.AddTemplateInstancesToQueue(templateId);
m_instanceUpdateExecutor.AddTemplateInstancesToQueue(templateId, instanceToExclude);
}
void PrefabSystemComponent::UpdateLinkedInstances(AZStd::queue<LinkIds>& linkIdsQueue)
@@ -250,8 +248,6 @@ namespace AzToolsFramework
if (targetTemplateIdToLinkIdMap[targetTemplateId].first.empty() &&
targetTemplateIdToLinkIdMap[targetTemplateId].second)
{
UpdatePrefabInstances(targetTemplateId);
auto templateToLinkIter = m_templateToLinkIdsMap.find(targetTemplateId);
if (templateToLinkIter != m_templateToLinkIdsMap.end())
{
@@ -215,14 +215,14 @@ namespace AzToolsFramework
*/
void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) override;
void PropagateTemplateChanges(TemplateId templateId) override;
void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
/**
* Updates all Instances owned by a Template.
*
* @param templateId The id of the Template owning Instances to update.
*/
void UpdatePrefabInstances(const TemplateId& templateId);
void UpdatePrefabInstances(const TemplateId& templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt);
private:
AZ_DISABLE_COPY_MOVE(PrefabSystemComponent);
@@ -56,7 +56,7 @@ namespace AzToolsFramework
virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0;
virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0;
virtual void PropagateTemplateChanges(TemplateId templateId) = 0;
virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
virtual AZStd::unique_ptr<Instance> InstantiatePrefab(AZ::IO::PathView filePath) = 0;
virtual AZStd::unique_ptr<Instance> InstantiatePrefab(const TemplateId& templateId) = 0;
@@ -70,10 +70,10 @@ namespace AzToolsFramework
const AZ::EntityId& entityId)
{
//get the entity alias for future undo/redo
InstanceOptionalReference instanceOptionalReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
AZ_Error("Prefab", instanceOptionalReference,
auto instanceReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
AZ_Error("Prefab", instanceReference,
"Failed to find an owning instance for the entity with id %llu.", static_cast<AZ::u64>(entityId));
Instance& instance = instanceOptionalReference->get();
Instance& instance = instanceReference->get();
m_templateId = instance.GetTemplateId();
m_entityAlias = (instance.GetEntityAlias(entityId)).value();
@@ -106,6 +106,17 @@ namespace AzToolsFramework
m_templateId);
}
void PrefabUndoEntityUpdate::Redo(InstanceOptionalReference instanceToExclude)
{
[[maybe_unused]] bool isPatchApplicationSuccessful =
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, instanceToExclude);
AZ_Error(
"Prefab", isPatchApplicationSuccessful,
"Applying the patch on the entity with alias '%s' in template with id '%llu' was unsuccessful", m_entityAlias.c_str(),
m_templateId);
}
//PrefabInstanceLinkUndo
PrefabUndoInstanceLink::PrefabUndoInstanceLink(const AZStd::string& undoOperationName)
: PrefabUndoBase(undoOperationName)
@@ -290,7 +301,12 @@ namespace AzToolsFramework
UpdateLink(m_linkDomNext);
}
void PrefabUndoLinkUpdate::UpdateLink(PrefabDom& linkDom)
void PrefabUndoLinkUpdate::Redo(InstanceOptionalReference instanceToExclude)
{
UpdateLink(m_linkDomNext, instanceToExclude);
}
void PrefabUndoLinkUpdate::UpdateLink(PrefabDom& linkDom, InstanceOptionalReference instanceToExclude)
{
LinkReference link = m_prefabSystemComponentInterface->FindLink(m_linkId);
@@ -304,7 +320,7 @@ namespace AzToolsFramework
//propagate the link changes
link->get().UpdateTarget();
m_prefabSystemComponentInterface->PropagateTemplateChanges(link->get().GetTargetTemplateId());
m_prefabSystemComponentInterface->PropagateTemplateChanges(link->get().GetTargetTemplateId(), instanceToExclude);
//mark as dirty
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(link->get().GetTargetTemplateId(), true);
@@ -71,11 +71,12 @@ namespace AzToolsFramework
void Capture(
PrefabDom& initialState,
PrefabDom& endState,
const AZ::EntityId& entity);
PrefabDom& endState, const AZ::EntityId& entity);
void Undo() override;
void Redo() override;
//! Overload to allow to apply the change, but prevent instanceToExclude from being refreshed.
void Redo(InstanceOptionalReference instanceToExclude);
private:
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
@@ -139,9 +140,11 @@ namespace AzToolsFramework
void Undo() override;
void Redo() override;
//! Overload to allow to apply the change, but prevent instanceToExclude from being refreshed.
void Redo(InstanceOptionalReference instanceToExclude);
private:
void UpdateLink(PrefabDom& linkDom);
void UpdateLink(PrefabDom& linkDom, InstanceOptionalReference instanceToExclude = AZStd::nullopt);
LinkId m_linkId;
PrefabDom m_linkDomNext; //data for delete/update
@@ -62,7 +62,8 @@ namespace AzToolsFramework
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());
}
}
}
@@ -2240,42 +2240,31 @@ namespace AzToolsFramework
RegenerateManipulators();
});
bool isPrefabSystemEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
// duplicate selection
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::Key_D) },
/*ID_EDIT_CLONE =*/33525, s_duplicateTitle, s_duplicateDesc,
[]()
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
bool prefabWipFeaturesEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
if (!isPrefabSystemEnabled || (isPrefabSystemEnabled && prefabWipFeaturesEnabled))
{
// duplicate selection
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::Key_D) },
/*ID_EDIT_CLONE =*/33525, s_duplicateTitle, s_duplicateDesc,
[]()
// Clear Widget selection - Prevents issues caused by cloning entities while a property in the Reflected Property Editor
// is being edited.
if (QApplication::focusWidget())
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
QApplication::focusWidget()->clearFocus();
}
// Clear Widget selection - Prevents issues caused by cloning entities while a property in the Reflected Property Editor
// is being edited.
if (QApplication::focusWidget())
{
QApplication::focusWidget()->clearFocus();
}
ScopedUndoBatch undoBatch(s_duplicateUndoRedoDesc);
auto selectionCommand = AZStd::make_unique<SelectionCommand>(EntityIdList(), s_duplicateUndoRedoDesc);
selectionCommand->SetParent(undoBatch.GetUndoBatch());
selectionCommand.release();
ScopedUndoBatch undoBatch(s_duplicateUndoRedoDesc);
auto selectionCommand = AZStd::make_unique<SelectionCommand>(EntityIdList(), s_duplicateUndoRedoDesc);
selectionCommand->SetParent(undoBatch.GetUndoBatch());
selectionCommand.release();
bool handled = false;
EditorRequestBus::Broadcast(&EditorRequests::CloneSelection, handled);
bool handled = false;
EditorRequestBus::Broadcast(&EditorRequests::CloneSelection, handled);
// selection update handled in AfterEntitySelectionChanged
});
}
// selection update handled in AfterEntitySelectionChanged
});
// delete selection
AddAction(
@@ -11,7 +11,6 @@
set(FILES
AzToolsFramework_precompiled.h
AzToolsFramework_precompiled.cpp
AssetEditor/AssetEditorBus.h
AssetEditor/AssetEditorToolbar.ui
AssetEditor/AssetEditorStatusBar.ui
@@ -242,6 +242,7 @@ namespace UnitTest
// Patch the nested prefab to reference an entity in its parent
ASSERT_TRUE(m_instanceToTemplateInterface->PatchEntityInTemplate(patch, newEntity->GetId()));
m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(rootInstance->GetTemplateId());
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
// Using the aliases we saved grab the updated entities so we can verify the entity reference is still preserved
@@ -473,18 +473,8 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
// editMenu->addAction(ID_EDIT_PASTE);
// editMenu.AddSeparator();
bool isPrefabSystemEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
bool prefabWipFeaturesEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
if (!isPrefabSystemEnabled || (isPrefabSystemEnabled && prefabWipFeaturesEnabled))
{
// Duplicate
editMenu.AddAction(ID_EDIT_CLONE);
}
// Duplicate
editMenu.AddAction(ID_EDIT_CLONE);
// Delete
editMenu.AddAction(ID_EDIT_DELETE);
@@ -912,6 +902,12 @@ QAction* LevelEditorMenuHandler::CreateViewPaneAction(const QtViewPane* view)
action = new QAction(menuText, this);
action->setObjectName(view->m_name);
action->setCheckable(true);
if (view->m_options.showOnToolsToolbar)
{
action->setIcon(QIcon(view->m_options.toolbarIcon));
}
m_actionManager->AddAction(view->m_id, action);
if (!view->m_options.shortcut.isEmpty())
@@ -941,6 +937,11 @@ QAction* LevelEditorMenuHandler::CreateViewPaneMenuItem(
menu->addAction(action);
if (view->m_options.showOnToolsToolbar)
{
m_mainWindow->GetToolbarManager()->AddButtonToEditToolbar(action);
}
return action;
}
-394
View File
@@ -1,394 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorDefs.h"
#include "InfoBar.h"
// Editor
#include "MainWindow.h"
#include "DisplaySettings.h"
#include "GameEngine.h"
#include "Include/ITransformManipulator.h"
#include "ActionManager.h"
#include "Settings.h"
#include "Include/IObjectManager.h"
#include "MathConversion.h"
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <ui_InfoBar.h>
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <QLineEdit>
#include <AzQtComponents/Components/Style.h>
void BeautifyEulerAngles(Vec3& v)
{
if (v.x + v.y + v.z >= 360.0f)
{
v.x = 180.0f - v.x;
v.y = 180.0f - v.y;
v.z = 180.0f - v.z;
}
}
/////////////////////////////////////////////////////////////////////////////
// CInfoBar dialog
CInfoBar::CInfoBar(QWidget* parent)
: QWidget(parent)
, ui(new Ui::CInfoBar)
{
ui->setupUi(this);
m_bSelectionChanged = false;
m_bDragMode = false;
m_prevMoveSpeed = 0;
m_currValue = Vec3(-111, +222, -333); //this wasn't initialized. I don't know what a good value is
m_oldMainVolume = 1.0f;
GetIEditor()->RegisterNotifyListener(this);
//audio request setup
m_oMuteAudioRequest.pData = &m_oMuteAudioRequestData;
m_oUnmuteAudioRequest.pData = &m_oUnmuteAudioRequestData;
OnInitDialog();
auto comboBoxTextChanged = static_cast<void(QComboBox::*)(const QString&)>(&QComboBox::currentTextChanged);
connect(ui->m_moveSpeed, comboBoxTextChanged, this, &CInfoBar::OnUpdateMoveSpeedText);
connect(ui->m_moveSpeed->lineEdit(), &QLineEdit::returnPressed, this, &CInfoBar::OnSpeedComboBoxEnter);
// Hide some buttons from the expander menu
AzQtComponents::Style::addClass(ui->m_physDoStepBtn, "expanderMenu_hide");
AzQtComponents::Style::addClass(ui->m_physSingleStepBtn, "expanderMenu_hide");
connect(ui->m_physicsBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedPhysics);
connect(ui->m_physSingleStepBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedSingleStepPhys);
connect(ui->m_physDoStepBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedDoStepPhys);
connect(ui->m_syncPlayerBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedSyncplayer);
connect(ui->m_gotoPos, &QToolButton::clicked, this, &CInfoBar::OnBnClickedGotoPosition);
connect(ui->m_muteBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedMuteAudio);
connect(ui->m_vrBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedEnableVR);
connect(this, &CInfoBar::ActionTriggered, MainWindow::instance()->GetActionManager(), &ActionManager::ActionTriggered);
connect(ui->m_physicsBtn, &QAbstractButton::toggled, ui->m_physicsBtn, [this](bool checked) {
ui->m_physicsBtn->setToolTip(checked ? tr("Stop Simulation (Ctrl+P)") : tr("Simulate (Ctrl+P)"));
});
connect(ui->m_physSingleStepBtn, &QAbstractButton::toggled, ui->m_physSingleStepBtn, [this](bool checked) {
ui->m_physSingleStepBtn->setToolTip(checked ? tr("Disable Physics/AI Single-step Mode ('<' in Game Mode)") : tr("Enable Physics/AI Single-step Mode ('<' in Game Mode)"));
});
connect(ui->m_syncPlayerBtn, &QAbstractButton::toggled, ui->m_syncPlayerBtn, [this](bool checked) {
ui->m_syncPlayerBtn->setToolTip(checked ? tr("Synchronize Player with Camera") : tr("Move Player and Camera Separately"));
});
connect(ui->m_muteBtn, &QAbstractButton::toggled, ui->m_muteBtn, [this](bool checked) {
ui->m_muteBtn->setToolTip(checked ? tr("Un-mute Audio") : tr("Mute Audio"));
});
connect(ui->m_vrBtn, &QAbstractButton::toggled, ui->m_vrBtn, [this](bool checked) {
ui->m_vrBtn->setToolTip(checked ? tr("Disable VR Preview") : tr("Enable VR Preview"));
});
ui->m_moveSpeed->setValidator(new QDoubleValidator(m_minSpeed, m_maxSpeed, m_numDecimals, ui->m_moveSpeed));
// Save off the move speed here since setting up the combo box can cause it to update values in the background.
float cameraMoveSpeed = gSettings.cameraMoveSpeed;
// Populate the presets in the ComboBox
for (float presetValue : m_speedPresetValues)
{
ui->m_moveSpeed->addItem(QString().setNum(presetValue, 'f', m_numDecimals), presetValue);
}
SetSpeedComboBox(cameraMoveSpeed);
ui->m_moveSpeed->setInsertPolicy(QComboBox::NoInsert);
using namespace AzToolsFramework::ComponentModeFramework;
EditorComponentModeNotificationBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
}
//////////////////////////////////////////////////////////////////////////
CInfoBar::~CInfoBar()
{
using namespace AzToolsFramework::ComponentModeFramework;
EditorComponentModeNotificationBus::Handler::BusDisconnect();
GetIEditor()->UnregisterNotifyListener(this);
AZ::VR::VREventBus::Handler::BusDisconnect();
}
//////////////////////////////////////////////////////////////////////////
void CInfoBar::OnEditorNotifyEvent(EEditorNotifyEvent event)
{
if (event == eNotify_OnIdleUpdate)
{
IdleUpdate();
}
else if (event == eNotify_OnBeginGameMode || event == eNotify_OnEndGameMode)
{
// Audio: determine muted state of audio
//m_bMuted = gEnv->pAudioSystem->GetMainVolume() == 0.f;
ui->m_muteBtn->setChecked(gSettings.bMuteAudio);
}
else if (event == eNotify_OnBeginLoad || event == eNotify_OnCloseScene)
{
// make sure AI/Physics is disabled on level load (CE-4229)
if (GetIEditor()->GetGameEngine()->GetSimulationMode())
{
OnBnClickedPhysics();
}
ui->m_physicsBtn->setEnabled(false);
ui->m_physSingleStepBtn->setEnabled(false);
ui->m_physDoStepBtn->setEnabled(false);
}
else if (event == eNotify_OnEndLoad || event == eNotify_OnEndNewScene)
{
ui->m_physicsBtn->setEnabled(true);
ui->m_physSingleStepBtn->setEnabled(true);
ui->m_physDoStepBtn->setEnabled(true);
}
else if (event == eNotify_OnSelectionChange)
{
m_bSelectionChanged = true;
}
}
void CInfoBar::IdleUpdate()
{
if (!m_idleUpdateEnabled)
{
return;
}
bool updateUI = false;
// Update Width/Height of selection rectangle.
AABB box;
GetIEditor()->GetSelectedRegion(box);
float width = box.max.x - box.min.x;
float height = box.max.y - box.min.y;
if (m_width != width || m_height != height)
{
m_width = width;
m_height = height;
updateUI = true;
}
Vec3 marker = GetIEditor()->GetMarkerPosition();
int selectedEntitiesCount = 0;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
selectedEntitiesCount, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntitiesCount);
if (selectedEntitiesCount != m_numSelected)
{
m_numSelected = selectedEntitiesCount;
updateUI = true;
}
QString str;
if (updateUI)
{
if (m_numSelected == 0)
{
str = tr("None Selected");
}
else if (m_numSelected == 1)
{
str = tr("1 Object Selected");
}
else
{
str = tr("%1 Objects Selected").arg(m_numSelected);
}
ui->m_statusText->setText(str);
m_sLastText = str;
}
if (gSettings.cameraMoveSpeed != m_prevMoveSpeed &&
!ui->m_moveSpeed->lineEdit()->hasFocus())
{
m_prevMoveSpeed = gSettings.cameraMoveSpeed;
SetSpeedComboBox(gSettings.cameraMoveSpeed);
}
{
bool bPhysics = GetIEditor()->GetGameEngine()->GetSimulationMode();
if ((ui->m_physicsBtn->isChecked() && !bPhysics) ||
(!ui->m_physicsBtn->isChecked() && bPhysics))
{
ui->m_physicsBtn->setChecked(bPhysics);
}
// Unsupported for Phyics:: atm
bool bSingleStep = false;
if (ui->m_physSingleStepBtn->isChecked() != bSingleStep)
{
ui->m_physSingleStepBtn->setChecked(bSingleStep);
}
bool bSyncPlayer = GetIEditor()->GetGameEngine()->IsSyncPlayerPosition();
if ((!ui->m_syncPlayerBtn->isChecked() && !bSyncPlayer) ||
(ui->m_syncPlayerBtn->isChecked() && bSyncPlayer))
{
ui->m_syncPlayerBtn->setChecked(!bSyncPlayer);
}
}
// if our selection changed, or if our display values are out of date
if (m_bSelectionChanged)
{
m_bSelectionChanged = false;
}
}
inline double Round(double fVal, double fStep)
{
if (fStep > 0.f)
{
fVal = int_round(fVal / fStep) * fStep;
}
return fVal;
}
void CInfoBar::OnUpdateMoveSpeedText(const QString& text)
{
gSettings.cameraMoveSpeed = aznumeric_cast<float>(Round(text.toDouble(), m_speedStep));
}
void CInfoBar::OnSpeedComboBoxEnter()
{
ui->m_moveSpeed->clearFocus();
}
void CInfoBar::OnInitDialog()
{
QFontMetrics metrics({});
int width = metrics.boundingRect("-9999.99").width() * m_fieldWidthMultiplier;
ui->m_moveSpeed->setFixedWidth(width);
ui->m_physicsBtn->setEnabled(false);
ui->m_physSingleStepBtn->setEnabled(false);
ui->m_physDoStepBtn->setEnabled(false);
ui->m_muteBtn->setChecked(gSettings.bMuteAudio);
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, gSettings.bMuteAudio ? m_oMuteAudioRequest : m_oUnmuteAudioRequest);
//This is here just in case this class hasn't been created before
//a VR headset was initialized
ui->m_vrBtn->setEnabled(false);
if (AZ::VR::HMDDeviceRequestBus::GetTotalNumOfEventHandlers() != 0)
{
ui->m_vrBtn->setEnabled(true);
}
AZ::VR::VREventBus::Handler::BusConnect();
}
void CInfoBar::OnHMDInitialized()
{
ui->m_vrBtn->setEnabled(true);
}
void CInfoBar::OnHMDShutdown()
{
ui->m_vrBtn->setEnabled(false);
}
void CInfoBar::OnBnClickedTerrainCollision()
{
emit ActionTriggered(ID_TERRAIN_COLLISION);
}
void CInfoBar::OnBnClickedPhysics()
{
if (!ui->m_physicsBtn->isEnabled())
{
return;
}
bool bPhysics = GetIEditor()->GetGameEngine()->GetSimulationMode();
ui->m_physicsBtn->setChecked(bPhysics);
emit ActionTriggered(ID_SWITCH_PHYSICS);
if (bPhysics && ui->m_physSingleStepBtn->isChecked())
{
OnBnClickedSingleStepPhys();
}
}
void CInfoBar::OnBnClickedSingleStepPhys()
{
}
void CInfoBar::OnBnClickedDoStepPhys()
{
}
//////////////////////////////////////////////////////////////////////////
void CInfoBar::OnBnClickedSyncplayer()
{
emit ActionTriggered(ID_GAME_SYNCPLAYER);
}
//////////////////////////////////////////////////////////////////////////
void CInfoBar::OnBnClickedGotoPosition()
{
emit ActionTriggered(ID_DISPLAY_GOTOPOSITION);
}
//////////////////////////////////////////////////////////////////////////
void CInfoBar::OnBnClickedMuteAudio()
{
gSettings.bMuteAudio = !gSettings.bMuteAudio;
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, gSettings.bMuteAudio ? m_oMuteAudioRequest : m_oUnmuteAudioRequest);
ui->m_muteBtn->setChecked(gSettings.bMuteAudio);
}
void CInfoBar::OnBnClickedEnableVR()
{
gSettings.bEnableGameModeVR = !gSettings.bEnableGameModeVR;
ui->m_vrBtn->setChecked(gSettings.bEnableGameModeVR);
}
void CInfoBar::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
{
ui->m_physicsBtn->setDisabled(true);
}
void CInfoBar::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
{
ui->m_physicsBtn->setEnabled(true);
}
void CInfoBar::SetSpeedComboBox(double value)
{
value = AZStd::clamp(Round(value, m_speedStep), m_minSpeed, m_maxSpeed);
int index = ui->m_moveSpeed->findData(value);
if (index != -1)
{
ui->m_moveSpeed->setCurrentIndex(index);
}
else
{
ui->m_moveSpeed->lineEdit()->setText(QString().setNum(value, 'f', m_numDecimals));
}
}
#include <moc_InfoBar.cpp>
-121
View File
@@ -1,121 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITOR_INFOBAR_H
#define CRYINCLUDE_EDITOR_INFOBAR_H
#pragma once
// InfoBar.h : header file
//
#if !defined(Q_MOC_RUN)
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
#include <IAudioSystem.h>
#include <HMDBus.h>
#endif
/////////////////////////////////////////////////////////////////////////////
// CInfoBar dialog
namespace Ui {
class CInfoBar;
}
class CInfoBar
: public QWidget
, public IEditorNotifyListener
, public AZ::VR::VREventBus::Handler
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
{
Q_OBJECT
// Construction
public:
CInfoBar(QWidget* parent = nullptr);
~CInfoBar();
// Toggle the mute audio button
void ToggleAudio() { OnBnClickedMuteAudio(); }
void SetSpeedComboBox(double value);
Q_SIGNALS:
void ActionTriggered(int command);
// Implementation
protected:
void IdleUpdate();
virtual void OnEditorNotifyEvent(EEditorNotifyEvent event);
virtual void OnOK() {};
virtual void OnCancel() {};
void OnBnClickedSyncplayer();
void OnBnClickedGotoPosition();
void OnSpeedComboBoxEnter();
void OnUpdateMoveSpeedText(const QString&);
void OnBnClickedTerrainCollision();
void OnBnClickedPhysics();
void OnBnClickedSingleStepPhys();
void OnBnClickedDoStepPhys();
void OnBnClickedMuteAudio();
void OnBnClickedEnableVR();
void OnInitDialog();
//////////////////////////////////////////////////////////////////////////
/// VR Event Bus Implementation
//////////////////////////////////////////////////////////////////////////
void OnHMDInitialized() override;
void OnHMDShutdown() override;
//////////////////////////////////////////////////////////////////////////
// EditorComponentModeNotificationBus
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
float m_width, m_height;
//int m_heightMapX,m_heightMapY;
double m_fieldWidthMultiplier = 1.8;
int m_numSelected;
float m_prevMoveSpeed;
// Speed combobox/lineEdit settings
double m_minSpeed = 0.1;
double m_maxSpeed = 100.0;
double m_speedStep = 0.1;
int m_numDecimals = 1;
// Speed presets
float m_speedPresetValues[3] = { 0.1f, 1.0f, 10.0f };
bool m_bSelectionChanged;
bool m_bDragMode;
QString m_sLastText;
Vec3 m_lastValue;
Vec3 m_currValue;
float m_oldMainVolume;
Audio::SAudioRequest m_oMuteAudioRequest;
Audio::SAudioManagerRequestData<Audio::eAMRT_MUTE_ALL> m_oMuteAudioRequestData;
Audio::SAudioRequest m_oUnmuteAudioRequest;
Audio::SAudioManagerRequestData<Audio::eAMRT_UNMUTE_ALL> m_oUnmuteAudioRequestData;
QScopedPointer<Ui::CInfoBar> ui;
bool m_idleUpdateEnabled = true;
};
#endif // CRYINCLUDE_EDITOR_INFOBAR_H
-333
View File
@@ -1,333 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CInfoBar</class>
<widget class="QWidget" name="CInfoBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1600</width>
<height>27</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">b</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_statusText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>No Objects Selected</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_gotoPos">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Go to Position</string>
</property>
<property name="text">
<string>Go to Position</string>
</property>
<property name="icon">
<iconset resource="InfoBar.qrc">
<normaloff>:/InfoBar/GotoLocation-default.svg</normaloff>:/InfoBar/GotoLocation-default.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>22</width>
<height>18</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Speed</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="m_moveSpeed">
<property name="toolTip">
<string>Camera Movement Speed</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_syncPlayerBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Synchronize Player with Camera</string>
</property>
<property name="text">
<string>Synchronize Player with Camera</string>
</property>
<property name="icon">
<iconset resource="InfoBar.qrc">
<normaloff>:/InfoBar/NoPlayerSync-default.svg</normaloff>
<activeon>:/InfoBar/NoPlayerSync-selected.svg</activeon>
:/InfoBar/NoPlayerSync-default.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="m_physicsBtn">
<property name="toolTip">
<string>Simulate (Ctrl+P)</string>
</property>
<property name="text">
<string>Simulate (Ctrl+P)</string>
</property>
<property name="icon">
<iconset resource="InfoBar.qrc">
<normaloff>:/InfoBar/PhysicsCol-default.svg</normaloff>:/InfoBar/PhysicsCol-default.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_physSingleStepBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Enable Physics/AI Single-step Mode ('&lt;' in Game Mode)</string>
</property>
<property name="text">
<string>Enable Physics/AI Single-step Mode ('&lt;' in Game Mode)</string>
</property>
<property name="icon">
<iconset resource="InfoBar.qrc">
<normaloff>:/InfoBar/Pause-default.svg</normaloff>:/InfoBar/Pause-default.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_physDoStepBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Perform a Single Physics/AI Simulation Step ('&gt;' in Game Mode)</string>
</property>
<property name="text">
<string>Perform a Single Physics/AI Simulation Step ('&gt;' in Game Mode)</string>
</property>
<property name="icon">
<iconset resource="InfoBar.qrc">
<normaloff>:/InfoBar/PausePlay-default.svg</normaloff>:/InfoBar/PausePlay-default.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="m_muteBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Mute Audio</string>
</property>
<property name="text">
<string>Mute Audio</string>
</property>
<property name="icon">
<iconset resource="InfoBar.qrc">
<normaloff>:/InfoBar/Mute-default.svg</normaloff>:/InfoBar/Mute-default.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_vrBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Enable VR Preview</string>
</property>
<property name="text">
<string>Enable VR Preview</string>
</property>
<property name="icon">
<iconset resource="InfoBar.qrc">
<normaloff>:/InfoBar/VR-default.svg</normaloff>:/InfoBar/VR-default.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>18</width>
<height>18</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="InfoBar.qrc"/>
</resources>
<connections/>
</ui>
-138
View File
@@ -94,134 +94,12 @@ void CLayoutSplitter::CreateLayoutView(int row, int col, int id)
viewPane->SetId(id);
}
//////////////////////////////////////////////////////////////////////////
// InfoBarExpanderWatcher
//////////////////////////////////////////////////////////////////////////
class InfoBarExpanderWatcher
: public QObject
{
public:
InfoBarExpanderWatcher(QObject* parent = nullptr)
: QObject(parent)
{
}
bool eventFilter(QObject* obj, QEvent* event) override
{
switch (event->type())
{
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
{
if (qobject_cast<QToolButton*>(obj))
{
auto mouseEvent = static_cast<QMouseEvent*>(event);
auto expansion = qobject_cast<QToolButton*>(obj);
expansion->setPopupMode(QToolButton::InstantPopup);
auto menu = new QMenu(expansion);
auto toolbar = qobject_cast<QToolBar*>(expansion->parentWidget());
auto toolWidgets = toolbar->findChildren<QWidget*>();
if (toolWidgets.count() > 0)
{
for (auto toolWidget : toolWidgets)
{
if (AzQtComponents::Style::hasClass(toolWidget, "expanderMenu_hide"))
{
continue;
}
if (auto toolButton = qobject_cast<QToolButton*>(toolWidget))
{
if (!toolButton->isVisible())
{
// Skip some empty buttons
if (toolButton->text().isEmpty())
{
continue;
}
QString plainText = QTextDocumentFragment::fromHtml(toolButton->text()).toPlainText();
QAction* action = new QAction(plainText, menu);
if (!toolButton->isEnabled())
{
action->setEnabled(false);
}
connect(action, &QAction::triggered, toolButton, &QToolButton::clicked);
if (toolButton->isCheckable())
{
action->setCheckable(true);
}
action->setChecked(toolButton->isChecked());
menu->addAction(action);
}
}
else if (auto toolCombo = qobject_cast<QComboBox*>(toolWidget))
{
// Add custom menu for Speed
if (toolCombo->objectName() == "m_moveSpeed")
{
double currentValue = toolCombo->lineEdit()->text().toDouble();
QMenu* newMenu = menu->addMenu(QString("Speed: %1").arg(currentValue));
double presets[] = { 0.1, 1.0, 10.0 };
for (double preset : presets)
{
QAction* presetAction = new QAction(newMenu);
presetAction->setText(QString::number(preset));
connect(presetAction, &QAction::triggered, this, [preset, this]() {
if (m_infoBar)
{
m_infoBar->SetSpeedComboBox(preset);
}
});
newMenu->addAction(presetAction);
}
}
}
}
}
menu->exec(mouseEvent->globalPos());
return true;
}
break;
}
}
return QObject::eventFilter(obj, event);
}
void SetInfoBar(CInfoBar* infoBar)
{
m_infoBar = infoBar;
}
private:
CInfoBar* m_infoBar = nullptr;
};
//////////////////////////////////////////////////////////////////////////
// CLayoutWnd
//////////////////////////////////////////////////////////////////////////
CLayoutWnd::CLayoutWnd(QSettings* settings, QWidget* parent)
: AzQtComponents::ToolBarArea(parent)
, m_settings(settings)
, m_expanderWatcher(new InfoBarExpanderWatcher(this))
{
m_bMaximized = false;
m_maximizedView = 0;
@@ -230,23 +108,8 @@ CLayoutWnd::CLayoutWnd(QSettings* settings, QWidget* parent)
m_maximizedViewId = 0;
m_infoBarSize = QSize(0, 0);
m_infoBar = new CInfoBar(this);
connect(qApp, &QApplication::focusChanged, this, &CLayoutWnd::OnFocusChanged);
m_expanderWatcher->SetInfoBar(m_infoBar);
m_infoToolBar = CreateToolBarFromWidget(m_infoBar,
Qt::BottomToolBarArea,
QStringLiteral("Info Panel"));
m_infoToolBar->setMovable(false);
m_infoToolBar->setObjectName("InfoBar");
AzQtComponents::Style::addClass(m_infoToolBar, "DefaultSpacing");
if (QToolButton* expansion = AzQtComponents::ToolBar::getToolBarExpansionButton(m_infoToolBar))
{
expansion->installEventFilter(m_expanderWatcher);
}
setContextMenuPolicy(Qt::NoContextMenu);
}
@@ -415,7 +278,6 @@ void CLayoutWnd::CreateLayout(EViewLayout layout, bool bBindViewports, EViewport
}
QRect rcView = rect();
rcView.setBottom(rcView.bottom() - m_infoBar->height());
// Ensure we delete our old view immediately so it can relinquish its backing ViewportContext
if (m_maximizedView)
-8
View File
@@ -20,7 +20,6 @@
#if !defined(Q_MOC_RUN)
#include "Viewport.h"
#include "InfoBar.h"
#include <QSplitter>
#include <QPointer>
@@ -77,8 +76,6 @@ private:
friend class CLayoutWnd;
};
class InfoBarExpanderWatcher;
/** Main layout window.
*/
class CLayoutWnd
@@ -116,8 +113,6 @@ public:
//! Switch 2D viewports.
void Cycle2DViewport();
CInfoBar& GetInfoBar() { return *m_infoBar; }
public slots:
void ResetLayout();
@@ -162,11 +157,8 @@ private:
// Id of maximized view pane.
int m_maximizedViewId;
CInfoBar* m_infoBar;
QToolBar* m_infoToolBar;
QSize m_infoBarSize;
QSettings* m_settings;
InfoBarExpanderWatcher* m_expanderWatcher;
};
/////////////////////////////////////////////////////////////////////////////
+3 -99
View File
@@ -297,68 +297,6 @@ namespace
}
}
class SnapToWidget
: public QWidget
{
public:
typedef AZStd::function<void(double)> SetValueCallback;
typedef AZStd::function<double()> GetValueCallback;
SnapToWidget(QAction* defaultAction, SetValueCallback setValueCallback, GetValueCallback getValueCallback)
: m_setValueCallback(setValueCallback)
, m_getValueCallback(getValueCallback)
{
QHBoxLayout* layout = new QHBoxLayout();
setLayout(layout);
m_toolButton = new QToolButton();
m_toolButton->setAutoRaise(true);
m_toolButton->setCheckable(false);
m_toolButton->setDefaultAction(defaultAction);
m_spinBox = new AzQtComponents::DoubleSpinBox();
layout->addWidget(m_toolButton);
layout->addWidget(m_spinBox);
m_spinBox->setEnabled(defaultAction->isChecked());
m_spinBox->setMinimum(1e-2f);
{
QSignalBlocker signalBlocker(m_spinBox);
m_spinBox->setValue(m_getValueCallback());
}
QObject::connect(m_spinBox, QOverload<double>::of(&AzQtComponents::DoubleSpinBox::valueChanged), this, &SnapToWidget::OnValueChanged);
QObject::connect(defaultAction, &QAction::changed, this, &SnapToWidget::OnActionChanged);
}
void SetIcon(QIcon icon)
{
m_toolButton->setIcon(icon);
}
protected:
void OnValueChanged(double value)
{
m_setValueCallback(value);
}
void OnActionChanged()
{
m_spinBox->setEnabled(m_toolButton->isChecked());
}
private:
QToolButton* m_toolButton = nullptr;
AzQtComponents::DoubleSpinBox* m_spinBox = nullptr;
SetValueCallback m_setValueCallback;
GetValueCallback m_getValueCallback;
};
/////////////////////////////////////////////////////////////////////////////
// MainWindow
/////////////////////////////////////////////////////////////////////////////
@@ -532,9 +470,11 @@ void MainWindow::Initialize()
InitToolActionHandlers();
// Initialize toolbars before we setup the menu so that any tools can be added to the toolbar as needed
InitToolBars();
m_levelEditorMenuHandler->Initialize();
InitToolBars();
InitStatusBar();
AzToolsFramework::SourceControlNotificationBus::Handler::BusConnect();
@@ -1274,36 +1214,6 @@ void UndoRedoToolButton::Update(int count)
setEnabled(count > 0);
}
QWidget* MainWindow::CreateSnapToGridWidget()
{
SnapToWidget::SetValueCallback setCallback = [](double snapStep)
{
SandboxEditor::SetGridSnappingSize(snapStep);
};
SnapToWidget::GetValueCallback getCallback = []()
{
return SandboxEditor::GridSnappingSize();
};
return new SnapToWidget(m_actionManager->GetAction(ID_SNAP_TO_GRID), setCallback, getCallback);
}
QWidget* MainWindow::CreateSnapToAngleWidget()
{
SnapToWidget::SetValueCallback setCallback = [](double snapAngle)
{
SandboxEditor::SetAngleSnappingSize(snapAngle);
};
SnapToWidget::GetValueCallback getCallback = []()
{
return SandboxEditor::AngleSnappingSize();
};
return new SnapToWidget(m_actionManager->GetAction(ID_SNAPANGLE), setCallback, getCallback);
}
bool MainWindow::IsPreview() const
{
return GetIEditor()->IsInPreviewMode();
@@ -2016,12 +1926,6 @@ QWidget* MainWindow::CreateToolbarWidget(int actionId)
case ID_TOOLBAR_WIDGET_REDO:
w = CreateUndoRedoButton(ID_REDO);
break;
case ID_TOOLBAR_WIDGET_SNAP_GRID:
w = CreateSnapToGridWidget();
break;
case ID_TOOLBAR_WIDGET_SNAP_ANGLE:
w = CreateSnapToAngleWidget();
break;
case ID_TOOLBAR_WIDGET_SPACER_RIGHT:
w = CreateSpacerRightWidget();
break;
-2
View File
@@ -202,8 +202,6 @@ private:
// AzToolsFramework::SourceControlNotificationBus::Handler:
void ConnectivityStateChanged(const AzToolsFramework::SourceControlState state) override;
QWidget* CreateSnapToGridWidget();
QWidget* CreateSnapToAngleWidget();
QWidget* CreateSpacerRightWidget();
QToolButton* CreateUndoRedoButton(int command);
-14
View File
@@ -144,20 +144,6 @@ EditorWindow QToolBar
border-bottom: 2px solid #111111;
}
/* InfoBar (Toolbar below the main viewport) */
QToolBar#InfoBar
{
qproperty-iconSize: 22px 18px;
}
QToolBar#InfoBar AzQtComponents--VectorElement[Coordinate="X"] QLabel,
QToolBar#InfoBar AzQtComponents--VectorElement[Coordinate="Y"] QLabel,
QToolBar#InfoBar AzQtComponents--VectorElement[Coordinate="Z"] QLabel
{
background-color: #333333;
}
DockWidgetTitleBar #DockWidgetContextMenu
{
qproperty-icon: url(:/Cards/img/UI20/Cards/menu_ico.svg);
+14 -13
View File
@@ -582,19 +582,6 @@ AmazonToolbar ToolbarManager::GetEditModeToolbar() const
{
AmazonToolbar t = AmazonToolbar("EditMode", QObject::tr("Edit Mode Toolbar"));
t.SetMainToolbar(true);
t.AddAction(ID_TOOLBAR_WIDGET_UNDO, ORIGINAL_TOOLBAR_VERSION);
t.AddAction(ID_TOOLBAR_WIDGET_REDO, ORIGINAL_TOOLBAR_VERSION);
t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION);
t.AddAction(ID_EDITMODE_MOVE, ORIGINAL_TOOLBAR_VERSION);
t.AddAction(ID_EDITMODE_ROTATE, ORIGINAL_TOOLBAR_VERSION);
t.AddAction(ID_EDITMODE_SCALE, ORIGINAL_TOOLBAR_VERSION);
t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION);
t.AddAction(ID_TOOLBAR_WIDGET_SNAP_GRID, ORIGINAL_TOOLBAR_VERSION);
t.AddAction(ID_TOOLBAR_WIDGET_SNAP_ANGLE, ORIGINAL_TOOLBAR_VERSION);
return t;
}
@@ -636,6 +623,20 @@ AmazonToolbar ToolbarManager::GetMiscToolbar() const
return t;
}
void ToolbarManager::AddButtonToEditToolbar(QAction* action)
{
QString toolbarName = "EditMode";
const AmazonToolbar* toolbar = FindToolbar(toolbarName);
if (toolbar)
{
if (toolbar->Toolbar())
{
toolbar->Toolbar()->addAction(action);
}
}
}
const AmazonToolbar* ToolbarManager::FindDefaultToolbar(const QString& toolbarName) const
{
for (const AmazonToolbar& toolbar : m_standardToolbars)
+2
View File
@@ -169,6 +169,8 @@ public:
AmazonToolbar GetMiscToolbar() const;
AmazonToolbar GetPlayConsoleToolbar() const;
void AddButtonToEditToolbar(QAction* action);
private:
Q_DISABLE_COPY(ToolbarManager);
void SaveToolbars();
+439 -78
View File
@@ -21,6 +21,8 @@
// Qt
#include <QInputDialog>
#include <AtomLyIntegration/AtomViewportDisplayInfo/AtomViewportInfoDisplayBus.h>
// CryCommon
#include <CryCommon/SFunctor.h>
@@ -35,16 +37,20 @@
#include "Objects/SelectionGroup.h"
#include "UsedResources.h"
#include "Include/IObjectManager.h"
#include "ActionManager.h"
#include "MainWindow.h"
#include "GameEngine.h"
#include "MathConversion.h"
#include "EditorViewportSettings.h"
#include <AtomLyIntegration/AtomViewportDisplayInfo/AtomViewportInfoDisplayBus.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/Casting/numeric_cast.h>
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include "ui_ViewportTitleDlg.h"
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
#endif //!defined(Q_MOC_RUN)
// CViewportTitleDlg dialog
inline namespace Helpers
@@ -103,7 +109,9 @@ CViewportTitleDlg::CViewportTitleDlg(QWidget* pParent)
layout->addWidget(container);
container->setObjectName("ViewportTitleDlgContainer");
m_pViewPane = NULL;
m_prevMoveSpeed = 0;
m_pViewPane = nullptr;
GetIEditor()->RegisterNotifyListener(this);
GetISystem()->GetISystemEventDispatcher()->RegisterListener(this);
@@ -111,21 +119,176 @@ CViewportTitleDlg::CViewportTitleDlg(QWidget* pParent)
LoadCustomPresets("AspectRatioPresets", "AspectRatioPreset", m_customAspectRatioPresets);
LoadCustomPresets("ResPresets", "ResPreset", m_customResPresets);
OnInitDialog();
// audio request setup
m_oMuteAudioRequest.pData = &m_oMuteAudioRequestData;
m_oUnmuteAudioRequest.pData = &m_oUnmuteAudioRequestData;
connect(m_ui->m_fovLabel, &QWidget::customContextMenuRequested, this, &CViewportTitleDlg::PopUpFOVMenu);
connect(m_ui->m_fovStaticCtrl, &QWidget::customContextMenuRequested, this, &CViewportTitleDlg::PopUpFOVMenu);
connect(m_ui->m_ratioStaticCtrl, &QWidget::customContextMenuRequested, this, &CViewportTitleDlg::PopUpAspectMenu);
connect(m_ui->m_ratioLabel, &QWidget::customContextMenuRequested, this, &CViewportTitleDlg::PopUpAspectMenu);
connect(m_ui->m_sizeStaticCtrl, &QWidget::customContextMenuRequested, this, &CViewportTitleDlg::PopUpResolutionMenu);
SetupCameraDropdownMenu();
SetupResolutionDropdownMenu();
SetupViewportInformationMenu();
SetupOverflowMenu();
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, gSettings.bMuteAudio ? m_oMuteAudioRequest : m_oUnmuteAudioRequest);
connect(this, &CViewportTitleDlg::ActionTriggered, MainWindow::instance()->GetActionManager(), &ActionManager::ActionTriggered);
AZ::VR::VREventBus::Handler::BusConnect();
OnInitDialog();
}
CViewportTitleDlg::~CViewportTitleDlg()
{
AZ::VR::VREventBus::Handler::BusDisconnect();
GetISystem()->GetISystemEventDispatcher()->RemoveListener(this);
GetIEditor()->UnregisterNotifyListener(this);
}
void CViewportTitleDlg::SetupCameraDropdownMenu()
{
// Setup the camera dropdown menu
QMenu* cameraMenu = new QMenu(this);
cameraMenu->addMenu(GetFovMenu());
m_ui->m_cameraMenu->setMenu(cameraMenu);
m_ui->m_cameraMenu->setPopupMode(QToolButton::InstantPopup);
QAction* gotoPositionAction = new QAction("Go to position", cameraMenu);
connect(gotoPositionAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedGotoPosition);
cameraMenu->addAction(gotoPositionAction);
m_syncPlayerToCameraAction = new QAction("Sync camera to player", cameraMenu);
m_syncPlayerToCameraAction->setCheckable(true);
connect(m_syncPlayerToCameraAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedSyncplayer);
cameraMenu->addAction(m_syncPlayerToCameraAction);
cameraMenu->addSeparator();
auto cameraSpeedActionWidget = new QWidgetAction(cameraMenu);
auto cameraSpeedContainer = new QWidget(cameraMenu);
auto cameraSpeedLabel = new QLabel(tr("Camera Speed"), cameraMenu);
m_cameraSpeed = new QComboBox(cameraMenu);
m_cameraSpeed->setEditable(true);
m_cameraSpeed->setValidator(new QDoubleValidator(m_minSpeed, m_maxSpeed, m_numDecimals, m_cameraSpeed));
QHBoxLayout* cameraSpeedLayout = new QHBoxLayout;
cameraSpeedLayout->addWidget(cameraSpeedLabel);
cameraSpeedLayout->addWidget(m_cameraSpeed);
cameraSpeedContainer->setLayout(cameraSpeedLayout);
cameraSpeedActionWidget->setDefaultWidget(cameraSpeedContainer);
// Save off the move speed here since setting up the combo box can cause it to update values in the background.
float cameraMoveSpeed = gSettings.cameraMoveSpeed;
// Populate the presets in the ComboBox
for (float presetValue : m_speedPresetValues)
{
m_cameraSpeed->addItem(QString().setNum(presetValue, 'f', m_numDecimals), presetValue);
}
auto comboBoxTextChanged = static_cast<void (QComboBox::*)(const QString&)>(&QComboBox::currentTextChanged);
SetSpeedComboBox(cameraMoveSpeed);
m_cameraSpeed->setInsertPolicy(QComboBox::NoInsert);
connect(m_cameraSpeed, comboBoxTextChanged, this, &CViewportTitleDlg::OnUpdateMoveSpeedText);
connect(m_cameraSpeed->lineEdit(), &QLineEdit::returnPressed, this, &CViewportTitleDlg::OnSpeedComboBoxEnter);
cameraMenu->addAction(cameraSpeedActionWidget);
}
void CViewportTitleDlg::SetupResolutionDropdownMenu()
{
// Setup the resolution dropdown menu
QMenu* resolutionMenu = new QMenu(this);
resolutionMenu->addMenu(GetAspectMenu());
resolutionMenu->addMenu(GetResolutionMenu());
m_ui->m_resolutionMenu->setMenu(resolutionMenu);
m_ui->m_resolutionMenu->setPopupMode(QToolButton::InstantPopup);
}
void CViewportTitleDlg::SetupViewportInformationMenu()
{
// Setup the debug information button
m_ui->m_debugInformationMenu->setMenu(GetViewportInformationMenu());
connect(m_ui->m_debugInformationMenu, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleDisplayInfo);
m_ui->m_debugInformationMenu->setPopupMode(QToolButton::MenuButtonPopup);
}
void CViewportTitleDlg::SetupOverflowMenu()
{
// Setup the overflow menu
QMenu* overFlowMenu = new QMenu(this);
m_debugHelpersAction = new QAction("Debug Helpers", overFlowMenu);
m_debugHelpersAction->setCheckable(true);
m_debugHelpersAction->setChecked(Helpers::IsHelpersShown());
connect(m_debugHelpersAction, &QAction::triggered, this, &CViewportTitleDlg::OnToggleHelpers);
overFlowMenu->addAction(m_debugHelpersAction);
m_audioMuteAction = new QAction("Mute Audio", overFlowMenu);
connect(m_audioMuteAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedMuteAudio);
overFlowMenu->addAction(m_audioMuteAction);
m_enableVRAction = new QAction("Enable VR Preview", overFlowMenu);
connect(m_enableVRAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedEnableVR);
overFlowMenu->addAction(m_enableVRAction);
overFlowMenu->addSeparator();
m_enableGridSnappingAction = new QAction("Enable Grid Snapping", overFlowMenu);
connect(m_enableGridSnappingAction, &QAction::triggered, this, &CViewportTitleDlg::OnGridSnappingToggled);
m_enableGridSnappingAction->setCheckable(true);
overFlowMenu->addAction(m_enableGridSnappingAction);
m_gridSizeActionWidget = new QWidgetAction(overFlowMenu);
auto gridSizeContainer = new QWidget(overFlowMenu);
auto gridSizeLabel = new QLabel(tr("Grid Size"), overFlowMenu);
m_gridSpinBox = new AzQtComponents::DoubleSpinBox();
m_gridSpinBox->setValue(SandboxEditor::GridSnappingSize());
m_gridSpinBox->setMinimum(1e-2f);
QObject::connect(
m_gridSpinBox, QOverload<double>::of(&AzQtComponents::DoubleSpinBox::valueChanged), this, &CViewportTitleDlg::OnGridSpinBoxChanged);
QHBoxLayout* gridSizeLayout = new QHBoxLayout;
gridSizeLayout->addWidget(gridSizeLabel);
gridSizeLayout->addWidget(m_gridSpinBox);
gridSizeContainer->setLayout(gridSizeLayout);
m_gridSizeActionWidget->setDefaultWidget(gridSizeContainer);
overFlowMenu->addAction(m_gridSizeActionWidget);
overFlowMenu->addSeparator();
m_enableAngleSnappingAction = new QAction("Enable Grid Snapping", overFlowMenu);
connect(m_enableAngleSnappingAction, &QAction::triggered, this, &CViewportTitleDlg::OnAngleSnappingToggled);
m_enableAngleSnappingAction->setCheckable(true);
overFlowMenu->addAction(m_enableAngleSnappingAction);
m_angleSizeActionWidget = new QWidgetAction(overFlowMenu);
auto angleSizeContainer = new QWidget(overFlowMenu);
auto angleSizeLabel = new QLabel(tr("Angle Snapping"), overFlowMenu);
m_angleSpinBox = new AzQtComponents::DoubleSpinBox();
m_angleSpinBox->setValue(SandboxEditor::AngleSnappingSize());
m_angleSpinBox->setMinimum(1e-2f);
QObject::connect(
m_angleSpinBox, QOverload<double>::of(&AzQtComponents::DoubleSpinBox::valueChanged), this,
&CViewportTitleDlg::OnAngleSpinBoxChanged);
QHBoxLayout* angleSizeLayout = new QHBoxLayout;
angleSizeLayout->addWidget(angleSizeLabel);
angleSizeLayout->addWidget(m_angleSpinBox);
angleSizeContainer->setLayout(angleSizeLayout);
m_angleSizeActionWidget->setDefaultWidget(angleSizeContainer);
overFlowMenu->addAction(m_angleSizeActionWidget);
m_ui->m_overflowBtn->setMenu(overFlowMenu);
m_ui->m_overflowBtn->setPopupMode(QToolButton::InstantPopup);
connect(overFlowMenu, &QMenu::aboutToShow, this, &CViewportTitleDlg::UpdateOverFlowMenuState);
UpdateMuteActionText();
}
//////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::SetViewPane(CLayoutViewPane* pViewPane)
{
@@ -140,21 +303,27 @@ void CViewportTitleDlg::SetViewPane(CLayoutViewPane* pViewPane)
void CViewportTitleDlg::OnInitDialog()
{
m_ui->m_titleBtn->setText(m_title);
m_ui->m_sizeStaticCtrl->setText(QString());
m_ui->m_toggleHelpersBtn->setChecked(GetIEditor()->GetDisplaySettings()->IsDisplayHelpers());
// Add a child parented to us that listens for r_displayInfo changes.
auto displayInfoHelper = new CViewportTitleDlgDisplayInfoHelper(this);
connect(displayInfoHelper, &CViewportTitleDlgDisplayInfoHelper::ViewportInfoStatusUpdated, this, &CViewportTitleDlg::UpdateDisplayInfo);
UpdateDisplayInfo();
connect(m_ui->m_toggleHelpersBtn, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleHelpers);
connect(m_ui->m_toggleDisplayInfoBtn, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleDisplayInfo);
// This is here just in case this class hasn't been created before
// a VR headset was initialized
m_enableVRAction->setEnabled(false);
if (AZ::VR::HMDDeviceRequestBus::GetTotalNumOfEventHandlers() != 0)
{
m_enableVRAction->setEnabled(true);
}
AZ::VR::VREventBus::Handler::BusConnect();
QFontMetrics metrics({});
int width = metrics.boundingRect("-9999.99").width() * m_fieldWidthMultiplier;
m_cameraSpeed->setFixedWidth(width);
m_ui->m_toggleHelpersBtn->setProperty("class", "big");
m_ui->m_toggleDisplayInfoBtn->setProperty("class", "big");
}
//////////////////////////////////////////////////////////////////////////
@@ -177,6 +346,80 @@ void CViewportTitleDlg::OnMaximize()
void CViewportTitleDlg::OnToggleHelpers()
{
Helpers::ToggleHelpers();
m_debugHelpersAction->setChecked(Helpers::IsHelpersShown());
}
void CViewportTitleDlg::SetNoViewportInfo()
{
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast(
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, AZ::AtomBridge::ViewportInfoDisplayState::NoInfo);
}
void CViewportTitleDlg::SetNormalViewportInfo()
{
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast(
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, AZ::AtomBridge::ViewportInfoDisplayState::NormalInfo);
}
void CViewportTitleDlg::SetFullViewportInfo()
{
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast(
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, AZ::AtomBridge::ViewportInfoDisplayState::FullInfo);
}
void CViewportTitleDlg::SetCompactViewportInfo()
{
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast(
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, AZ::AtomBridge::ViewportInfoDisplayState::CompactInfo);
}
//////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::UpdateDisplayInfo()
{
if (m_viewportInformationMenu == nullptr)
{
// Nothing to update, just return;
return;
}
AZ::AtomBridge::ViewportInfoDisplayState state = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult(
state,
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState
);
m_noInformationAction->setChecked(false);
m_normalInformationAction->setChecked(false);
m_fullInformationAction->setChecked(false);
m_compactInformationAction->setChecked(false);
switch (state)
{
case AZ::AtomBridge::ViewportInfoDisplayState::NormalInfo:
{
m_normalInformationAction->setChecked(true);
break;
}
case AZ::AtomBridge::ViewportInfoDisplayState::FullInfo:
{
m_fullInformationAction->setChecked(true);
break;
}
case AZ::AtomBridge::ViewportInfoDisplayState::CompactInfo:
{
m_compactInformationAction->setChecked(true);
break;
}
case AZ::AtomBridge::ViewportInfoDisplayState::NoInfo:
default:
{
m_noInformationAction->setChecked(true);
break;
}
}
m_ui->m_debugInformationMenu->setChecked(state != AZ::AtomBridge::ViewportInfoDisplayState::NoInfo);
}
//////////////////////////////////////////////////////////////////////////
@@ -184,27 +427,12 @@ void CViewportTitleDlg::OnToggleDisplayInfo()
{
AZ::AtomBridge::ViewportInfoDisplayState state = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult(
state,
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState
);
state, &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState);
state = aznumeric_cast<AZ::AtomBridge::ViewportInfoDisplayState>(
(aznumeric_cast<int>(state)+1) % aznumeric_cast<int>(AZ::AtomBridge::ViewportInfoDisplayState::Invalid));
(aznumeric_cast<int>(state) + 1) % aznumeric_cast<int>(AZ::AtomBridge::ViewportInfoDisplayState::Invalid));
// SetDisplayState will fire OnViewportInfoDisplayStateChanged and notify us, no need to call UpdateDisplayInfo.
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast(
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState,
state
);
}
//////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::UpdateDisplayInfo()
{
AZ::AtomBridge::ViewportInfoDisplayState state = AZ::AtomBridge::ViewportInfoDisplayState::NoInfo;
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::BroadcastResult(
state,
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::GetDisplayState
);
m_ui->m_toggleDisplayInfoBtn->setChecked(state != AZ::AtomBridge::ViewportInfoDisplayState::NoInfo);
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, state);
}
//////////////////////////////////////////////////////////////////////////
@@ -277,7 +505,7 @@ void CViewportTitleDlg::CreateFOVMenu()
{
if (!m_fovMenu)
{
m_fovMenu = new QMenu(this);
m_fovMenu = new QMenu("FOV", this);
}
m_fovMenu->clear();
@@ -292,17 +520,6 @@ void CViewportTitleDlg::CreateFOVMenu()
connect(action, &QAction::triggered, this, &CViewportTitleDlg::OnMenuFOVCustom);
}
void CViewportTitleDlg::PopUpFOVMenu()
{
if (m_pViewPane == NULL)
{
return;
}
CreateFOVMenu();
m_fovMenu->exec(QCursor::pos());
}
QMenu* const CViewportTitleDlg::GetFovMenu()
{
CreateFOVMenu();
@@ -379,9 +596,9 @@ void CViewportTitleDlg::OnMenuAspectRatioCustom()
//////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::CreateAspectMenu()
{
if (!m_aspectMenu)
if (m_aspectMenu == nullptr)
{
m_aspectMenu = new QMenu(this);
m_aspectMenu = new QMenu("Aspect Ratio");
}
m_aspectMenu->clear();
@@ -396,23 +613,48 @@ void CViewportTitleDlg::CreateAspectMenu()
connect(customAction, &QAction::triggered, this, &CViewportTitleDlg::OnMenuAspectRatioCustom);
}
void CViewportTitleDlg::PopUpAspectMenu()
{
if (!m_pViewPane)
{
return;
}
CreateAspectMenu();
m_aspectMenu->exec(QCursor::pos());
}
QMenu* const CViewportTitleDlg::GetAspectMenu()
{
CreateAspectMenu();
return m_aspectMenu;
}
QMenu* const CViewportTitleDlg::GetViewportInformationMenu()
{
CreateViewportInformationMenu();
return m_viewportInformationMenu;
}
void CViewportTitleDlg::CreateViewportInformationMenu()
{
if (m_viewportInformationMenu == nullptr)
{
m_viewportInformationMenu = new QMenu("Viewport Information");
m_noInformationAction = new QAction(tr("None"), m_viewportInformationMenu);
m_noInformationAction->setCheckable(true);
connect(m_noInformationAction, &QAction::triggered, this, &CViewportTitleDlg::SetNoViewportInfo);
m_viewportInformationMenu->addAction(m_noInformationAction);
m_normalInformationAction = new QAction(tr("Normal"), m_viewportInformationMenu);
m_normalInformationAction->setCheckable(true);
connect(m_normalInformationAction, &QAction::triggered, this, &CViewportTitleDlg::SetNormalViewportInfo);
m_viewportInformationMenu->addAction(m_normalInformationAction);
m_fullInformationAction = new QAction(tr("Full"), m_viewportInformationMenu);
m_fullInformationAction->setCheckable(true);
connect(m_fullInformationAction, &QAction::triggered, this, &CViewportTitleDlg::SetFullViewportInfo);
m_viewportInformationMenu->addAction(m_fullInformationAction);
m_compactInformationAction = new QAction(tr("Compact"), m_viewportInformationMenu);
m_compactInformationAction->setCheckable(true);
connect(m_compactInformationAction, &QAction::triggered, this, &CViewportTitleDlg::SetCompactViewportInfo);
m_viewportInformationMenu->addAction(m_compactInformationAction);
UpdateDisplayInfo();
}
}
void CViewportTitleDlg::AddResolutionMenus(QMenu* menu, std::function<void(int, int)> callback, const QStringList& customPresets)
{
static const CRenderViewport::SResolution resolutions[] = {
@@ -479,7 +721,7 @@ void CViewportTitleDlg::CreateResolutionMenu()
{
if (!m_resolutionMenu)
{
m_resolutionMenu = new QMenu(this);
m_resolutionMenu = new QMenu("Resolution");
}
m_resolutionMenu->clear();
@@ -494,17 +736,6 @@ void CViewportTitleDlg::CreateResolutionMenu()
connect(action, &QAction::triggered, this, &CViewportTitleDlg::OnMenuResolutionCustom);
}
void CViewportTitleDlg::PopUpResolutionMenu()
{
if (!m_pViewPane)
{
return;
}
CreateResolutionMenu();
m_resolutionMenu->exec(QCursor::pos());
}
QMenu* const CViewportTitleDlg::GetResolutionMenu()
{
CreateResolutionMenu();
@@ -514,14 +745,14 @@ QMenu* const CViewportTitleDlg::GetResolutionMenu()
//////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::OnViewportSizeChanged(int width, int height)
{
m_ui->m_sizeStaticCtrl->setText(QString::fromLatin1("%1 x %2").arg(width).arg(height));
m_resolutionMenu->setTitle(QString::fromLatin1("Resolution: %1 x %2").arg(width).arg(height));
if (width != 0 && height != 0)
{
// Calculate greatest common divider of width & height
int whGCD = gcd(width, height);
m_ui->m_ratioStaticCtrl->setText(QString::fromLatin1("%1:%2").arg(width / whGCD).arg(height / whGCD));
m_aspectMenu->setTitle(QString::fromLatin1("Ratio: %1:%2").arg(width / whGCD).arg(height / whGCD));
}
}
@@ -529,9 +760,9 @@ void CViewportTitleDlg::OnViewportSizeChanged(int width, int height)
void CViewportTitleDlg::OnViewportFOVChanged(float fov)
{
const float degFOV = RAD2DEG(fov);
if (m_ui && m_ui->m_fovStaticCtrl)
if (m_fovMenu)
{
m_ui->m_fovStaticCtrl->setText(QString::fromLatin1("%1%2").arg(qRound(degFOV)).arg(QString(QByteArray::fromPercentEncoding("%C2%B0"))));
m_fovMenu->setTitle(QString::fromLatin1("FOV: %1%2").arg(qRound(degFOV)).arg(QString(QByteArray::fromPercentEncoding("%C2%B0"))));
}
}
@@ -541,7 +772,11 @@ void CViewportTitleDlg::OnEditorNotifyEvent(EEditorNotifyEvent event)
switch (event)
{
case eNotify_OnDisplayRenderUpdate:
m_ui->m_toggleHelpersBtn->setChecked(GetIEditor()->GetDisplaySettings()->IsDisplayHelpers());
m_debugHelpersAction->setChecked(Helpers::IsHelpersShown());
break;
case eNotify_OnBeginGameMode:
case eNotify_OnEndGameMode:
UpdateMuteActionText();
break;
}
}
@@ -615,6 +850,132 @@ bool CViewportTitleDlg::eventFilter(QObject* object, QEvent* event)
return QWidget::eventFilter(object, event) || consumeEvent;
}
void CViewportTitleDlg::OnBnClickedSyncplayer()
{
emit ActionTriggered(ID_GAME_SYNCPLAYER);
bool bSyncPlayer = GetIEditor()->GetGameEngine()->IsSyncPlayerPosition();
m_syncPlayerToCameraAction->setChecked(!bSyncPlayer);
}
void CViewportTitleDlg::OnBnClickedGotoPosition()
{
emit ActionTriggered(ID_DISPLAY_GOTOPOSITION);
}
void CViewportTitleDlg::OnBnClickedMuteAudio()
{
gSettings.bMuteAudio = !gSettings.bMuteAudio;
Audio::AudioSystemRequestBus::Broadcast(
&Audio::AudioSystemRequestBus::Events::PushRequest, gSettings.bMuteAudio ? m_oMuteAudioRequest : m_oUnmuteAudioRequest);
UpdateMuteActionText();
}
void CViewportTitleDlg::UpdateMuteActionText()
{
m_audioMuteAction->setText(gSettings.bMuteAudio ? tr("Un-mute Audio") : tr("Mute Audio"));
}
void CViewportTitleDlg::OnHMDInitialized()
{
m_enableVRAction->setEnabled(true);
}
void CViewportTitleDlg::OnHMDShutdown()
{
m_enableVRAction->setEnabled(false);
}
void CViewportTitleDlg::OnBnClickedEnableVR()
{
gSettings.bEnableGameModeVR = !gSettings.bEnableGameModeVR;
m_enableVRAction->setText(gSettings.bEnableGameModeVR ? tr("Disable VR Preview") : tr("Enable VR Preview"));
}
inline double Round(double fVal, double fStep)
{
if (fStep > 0.f)
{
fVal = int_round(fVal / fStep) * fStep;
}
return fVal;
}
void CViewportTitleDlg::SetSpeedComboBox(double value)
{
value = AZStd::clamp(Round(value, m_speedStep), m_minSpeed, m_maxSpeed);
int index = m_cameraSpeed->findData(value);
if (index != -1)
{
m_cameraSpeed->setCurrentIndex(index);
}
else
{
m_cameraSpeed->lineEdit()->setText(QString().setNum(value, 'f', m_numDecimals));
}
}
void CViewportTitleDlg::OnSpeedComboBoxEnter()
{
m_cameraSpeed->clearFocus();
}
void CViewportTitleDlg::OnUpdateMoveSpeedText(const QString& text)
{
gSettings.cameraMoveSpeed = aznumeric_cast<float>(Round(text.toDouble(), m_speedStep));
}
void CViewportTitleDlg::CheckForCameraSpeedUpdate()
{
if (gSettings.cameraMoveSpeed != m_prevMoveSpeed && !m_cameraSpeed->lineEdit()->hasFocus())
{
m_prevMoveSpeed = gSettings.cameraMoveSpeed;
SetSpeedComboBox(gSettings.cameraMoveSpeed);
}
}
void CViewportTitleDlg::OnGridSnappingToggled()
{
m_gridSizeActionWidget->setEnabled(m_enableGridSnappingAction->isChecked());
MainWindow::instance()->GetActionManager()->GetAction(ID_SNAP_TO_GRID)->trigger();
}
void CViewportTitleDlg::OnAngleSnappingToggled()
{
m_angleSizeActionWidget->setEnabled(m_enableAngleSnappingAction->isChecked());
MainWindow::instance()->GetActionManager()->GetAction(ID_SNAPANGLE)->trigger();
}
void CViewportTitleDlg::OnGridSpinBoxChanged(double value)
{
SandboxEditor::SetGridSnappingSize(value);
}
void CViewportTitleDlg::OnAngleSpinBoxChanged(double value)
{
SandboxEditor::SetAngleSnappingSize(value);
}
void CViewportTitleDlg::UpdateOverFlowMenuState()
{
bool gridSnappingActive = MainWindow::instance()->GetActionManager()->GetAction(ID_SNAP_TO_GRID)->isChecked();
{
QSignalBlocker signalBlocker(m_enableGridSnappingAction);
m_enableGridSnappingAction->setChecked(gridSnappingActive);
}
m_gridSizeActionWidget->setEnabled(gridSnappingActive);
bool angleSnappingActive = MainWindow::instance()->GetActionManager()->GetAction(ID_SNAPANGLE)->isChecked();
{
QSignalBlocker signalBlocker(m_enableAngleSnappingAction);
m_enableAngleSnappingAction->setChecked(angleSnappingActive);
}
m_angleSizeActionWidget->setEnabled(angleSnappingActive);
}
namespace
{
+91 -4
View File
@@ -19,8 +19,16 @@
#include "RenderViewport.h"
#include <AzCore/Component/Component.h>
#include <IAudioSystem.h>
#include <functional>
#include <QSharedPointer>
#include <QWidgetAction>
#include <QComboBox>
#include <AzQtComponents/Components/Widgets/SpinBox.h>
#include <HMDBus.h>
#endif
// CViewportTitleDlg dialog
@@ -42,6 +50,7 @@ class CViewportTitleDlg
: public QWidget
, public IEditorNotifyListener
, public ISystemEventListener
, public AZ::VR::VREventBus::Handler
{
Q_OBJECT
public:
@@ -63,10 +72,15 @@ public:
bool eventFilter(QObject* object, QEvent* event) override;
void SetSpeedComboBox(double value);
QMenu* const GetFovMenu();
QMenu* const GetAspectMenu();
QMenu* const GetResolutionMenu();
Q_SIGNALS:
void ActionTriggered(int command);
protected:
virtual void OnInitDialog();
@@ -75,9 +89,20 @@ protected:
void OnMaximize();
void OnToggleHelpers();
void OnToggleDisplayInfo();
void UpdateDisplayInfo();
//////////////////////////////////////////////////////////////////////////
/// VR Event Bus Implementation
//////////////////////////////////////////////////////////////////////////
void OnHMDInitialized() override;
void OnHMDShutdown() override;
//////////////////////////////////////////////////////////////////////////
void SetupCameraDropdownMenu();
void SetupResolutionDropdownMenu();
void SetupViewportInformationMenu();
void SetupOverflowMenu();
QString m_title;
CLayoutViewPane* m_pViewPane;
@@ -87,22 +112,84 @@ protected:
QStringList m_customFOVPresets;
QStringList m_customAspectRatioPresets;
float m_prevMoveSpeed;
// Speed combobox/lineEdit settings
double m_minSpeed = 0.1;
double m_maxSpeed = 100.0;
double m_speedStep = 0.1;
int m_numDecimals = 1;
// Speed presets
float m_speedPresetValues[3] = { 0.1f, 1.0f, 10.0f };
double m_fieldWidthMultiplier = 1.8;
void OnMenuFOVCustom();
void CreateFOVMenu();
void PopUpFOVMenu();
void OnMenuAspectRatioCustom();
void CreateAspectMenu();
void PopUpAspectMenu();
void OnMenuResolutionCustom();
void CreateResolutionMenu();
void PopUpResolutionMenu();
void CreateViewportInformationMenu();
QMenu* const GetViewportInformationMenu();
void SetNoViewportInfo();
void SetNormalViewportInfo();
void SetFullViewportInfo();
void SetCompactViewportInfo();
void OnBnClickedSyncplayer();
void OnBnClickedGotoPosition();
void OnBnClickedMuteAudio();
void OnBnClickedEnableVR();
void UpdateMuteActionText();
void OnToggleDisplayInfo();
void OnSpeedComboBoxEnter();
void OnUpdateMoveSpeedText(const QString&);
void CheckForCameraSpeedUpdate();
void OnGridSnappingToggled();
void OnAngleSnappingToggled();
void OnGridSpinBoxChanged(double value);
void OnAngleSpinBoxChanged(double value);
void UpdateOverFlowMenuState();
QMenu* m_fovMenu = nullptr;
QMenu* m_aspectMenu = nullptr;
QMenu* m_resolutionMenu = nullptr;
QMenu* m_viewportInformationMenu = nullptr;
QAction* m_noInformationAction = nullptr;
QAction* m_normalInformationAction = nullptr;
QAction* m_fullInformationAction = nullptr;
QAction* m_compactInformationAction = nullptr;
QAction* m_debugHelpersAction = nullptr;
QAction* m_syncPlayerToCameraAction = nullptr;
QAction* m_audioMuteAction = nullptr;
QAction* m_enableVRAction = nullptr;
QAction* m_enableGridSnappingAction = nullptr;
QAction* m_enableAngleSnappingAction = nullptr;
QComboBox* m_cameraSpeed = nullptr;
AzQtComponents::DoubleSpinBox* m_gridSpinBox = nullptr;
AzQtComponents::DoubleSpinBox* m_angleSpinBox = nullptr;
QWidgetAction* m_gridSizeActionWidget = nullptr;
QWidgetAction* m_angleSizeActionWidget = nullptr;
Audio::SAudioRequest m_oMuteAudioRequest;
Audio::SAudioManagerRequestData<Audio::eAMRT_MUTE_ALL> m_oMuteAudioRequestData;
Audio::SAudioRequest m_oUnmuteAudioRequest;
Audio::SAudioManagerRequestData<Audio::eAMRT_UNMUTE_ALL> m_oUnmuteAudioRequestData;
QScopedPointer<Ui::ViewportTitleDlg> m_ui;
};
+39 -115
View File
@@ -61,121 +61,43 @@
</widget>
</item>
<item>
<widget class="QLabel" name="m_fovLabel">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="text">
<string>FOV:</string>
</property>
</widget>
<widget class="QToolButton" name="m_cameraMenu">
<property name="icon">
<iconset>
<normaloff>:/Menu/camera.svg</normaloff>:/Menu/camera.svg
</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_debugInformationMenu">
<property name="icon">
<iconset>
<normaloff>:/Menu/debug.svg</normaloff>:/Menu/debug.svg
</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_resolutionMenu">
<property name="icon">
<iconset>
<normaloff>:/Menu/resolution.svg</normaloff>:/Menu/resolution.svg
</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_fovStaticCtrl">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="text">
<string>120°</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_ratioLabel">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="text">
<string>Ratio:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_ratioStaticCtrl">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="text">
<string>000:000</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_sizeStaticCtrl">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="text">
<string>0000 x 0000</string>
</property>
</widget>
</item>
<item>
<widget class="AzQtComponents::ButtonDivider" name="divider1" native="true"/>
</item>
<item>
<widget class="QToolButton" name="m_toggleDisplayInfoBtn">
<property name="text">
<string>Toggle display info</string>
</property>
<property name="toolTip">
<string>Toggle display info</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/stylesheet/img/UI20/Info.svg</normaloff>:/stylesheet/img/UI20/Info.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_toggleHelpersBtn">
<property name="text">
<string>Toggle display helpers</string>
</property>
<property name="toolTip">
<string>Toggle display helpers</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/stylesheet/img/UI20/Helpers.svg</normaloff>:/stylesheet/img/UI20/Helpers.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
<widget class="QToolButton" name="m_overflowBtn">
<property name="icon">
<iconset>
<normaloff>:/stylesheet/img/UI20/menu-centered.svg</normaloff>:/stylesheet/img/UI20/menu-centered.svg
</iconset>
</property>
</widget>
</item>
</layout>
</widget>
@@ -187,6 +109,8 @@
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
<resources>
<include location="../../Framework/AzQtComponents/AzQtComponents/Images/resources.qrc"/>
</resources>
<connections/>
</ui>
@@ -424,10 +424,6 @@ set(FILES
GotoPositionDlg.cpp
GotoPositionDlg.h
GotoPositionDlg.ui
InfoBar.cpp
InfoBar.qrc
InfoBar.h
InfoBar.ui
LayoutConfigDialog.cpp
LayoutConfigDialog.h
LayoutConfigDialog.ui
@@ -1,12 +0,0 @@
/*
* 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 "ComponentEntityEditorPlugin_precompiled.h"
@@ -670,18 +670,11 @@ void SandboxIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu, con
AzToolsFramework::EditorContextMenuBus::Broadcast(&AzToolsFramework::EditorContextMenuEvents::PopulateEditorGlobalContextMenu, menu);
}
bool prefabWipFeaturesEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
if (!prefabSystemEnabled || (prefabSystemEnabled && prefabWipFeaturesEnabled))
action = menu->addAction(QObject::tr("Duplicate"));
QObject::connect(action, &QAction::triggered, action, [this] { ContextMenu_Duplicate(); });
if (selected.size() == 0)
{
action = menu->addAction(QObject::tr("Duplicate"));
QObject::connect(action, &QAction::triggered, action, [this] { ContextMenu_Duplicate(); });
if (selected.size() == 0)
{
action->setDisabled(true);
}
action->setDisabled(true);
}
if (!prefabSystemEnabled)
@@ -15,7 +15,6 @@ set(FILES
ComponentEntityEditorPlugin.cpp
SandboxIntegration.h
SandboxIntegration.cpp
ComponentEntityEditorPlugin_precompiled.cpp
ComponentEntityEditorPlugin_precompiled.h
UI/ComponentEntityEditorOutlinerWindow.qrc
UI/QComponentEntityEditorMainWindow.h
@@ -1,15 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorAssetImporter_precompiled.h"
@@ -23,7 +23,6 @@ set(FILES
SceneSerializationHandler.h
SceneSerializationHandler.cpp
Main.cpp
EditorAssetImporter_precompiled.cpp
EditorAssetImporter_precompiled.h
AssetImporter.qrc
AssetImporterWindow.ui
@@ -1,13 +0,0 @@
/*
* 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 "FFMPEGPlugin_precompiled.h"
@@ -12,7 +12,6 @@
set(FILES
FFMPEGPlugin.rc
main.cpp
FFMPEGPlugin_precompiled.cpp
FFMPEGPlugin_precompiled.h
FFMPEGPlugin.cpp
FFMPEGPlugin.h
@@ -1,15 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "PerforcePlugin_precompiled.h"
@@ -20,6 +20,5 @@ set(FILES
PerforceSourceControl.cpp
PerforceSourceControl.h
resource.h
PerforcePlugin_precompiled.cpp
PerforcePlugin_precompiled.h
)
@@ -1,12 +0,0 @@
/*
* 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 "ProjectSettingsTool_precompiled.h"
@@ -11,7 +11,6 @@
set(FILES
main.cpp
ProjectSettingsTool_precompiled.cpp
ProjectSettingsTool_precompiled.h
DefaultImageValidator.cpp
DefaultImageValidator.h
@@ -291,6 +291,30 @@ QTabBar::tab:pressed
height:50px;
}
#projectSettingsTab::tab-bar > QPushButton {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #888888, stop: 1.0 #555555);
qproperty-flat: true;
margin-right:30px;
margin-bottom:12px;
margin-top:0px;
min-width:170px;
max-width:170px;
min-height:26px;
max-height:26px;
border-radius: 3px;
text-align:center;
font-size:13px;
}
#projectSettingsTab::tab-bar > QPushButton:hover {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #999999, stop: 1.0 #666666);
}
#projectSettingsTab::tab-bar > QPushButton:pressed {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #555555, stop: 1.0 #777777);
}
#projectSettingsTopFrame {
background-color:#1E252F;
}
@@ -15,10 +15,13 @@
namespace O3DE::ProjectManager
{
ProjectInfo::ProjectInfo(const QString& path, const QString& projectName, const QString& displayName,
const QString& imagePath, const QString& backgroundImagePath, bool needsBuild)
const QString& origin, const QString& summary, const QString& imagePath, const QString& backgroundImagePath,
bool needsBuild)
: m_path(path)
, m_projectName(projectName)
, m_displayName(displayName)
, m_origin(origin)
, m_summary(summary)
, m_imagePath(imagePath)
, m_backgroundImagePath(backgroundImagePath)
, m_needsBuild(needsBuild)
+16 -2
View File
@@ -15,6 +15,7 @@
#if !defined(Q_MOC_RUN)
#include <AzCore/Math/Uuid.h>
#include <QString>
#include <QStringList>
#endif
namespace O3DE::ProjectManager
@@ -23,8 +24,17 @@ namespace O3DE::ProjectManager
{
public:
ProjectInfo() = default;
ProjectInfo(const QString& path, const QString& projectName, const QString& displayName,
const QString& imagePath, const QString& backgroundImagePath, bool needsBuild);
ProjectInfo(
const QString& path,
const QString& projectName,
const QString& displayName,
const QString& origin,
const QString& summary,
const QString& imagePath,
const QString& backgroundImagePath,
bool needsBuild);
bool operator==(const ProjectInfo& rhs);
bool operator!=(const ProjectInfo& rhs);
@@ -36,12 +46,16 @@ namespace O3DE::ProjectManager
// From project.json
QString m_projectName;
QString m_displayName;
QString m_origin;
QString m_summary;
QStringList m_userTags;
// Used on projects home screen
QString m_imagePath;
QString m_backgroundImagePath;
// Used in project creation
bool m_needsBuild = false; //! Does this project need to be built
};
} // namespace O3DE::ProjectManager
@@ -19,6 +19,7 @@
#include <pybind11/functional.h>
#include <pybind11/embed.h>
#include <pybind11/eval.h>
#include <pybind11/stl.h>
#pragma pop_macro("slots")
#include <AzCore/IO/FileIO.h>
@@ -289,6 +290,7 @@ namespace O3DE::ProjectManager
m_engineTemplate = pybind11::module::import("o3de.engine_template");
m_enableGemProject = pybind11::module::import("o3de.enable_gem");
m_disableGemProject = pybind11::module::import("o3de.disable_gem");
m_editProjectProperties = pybind11::module::import("o3de.project_properties");
// make sure the engine is registered
RegisterThisEngine();
@@ -678,6 +680,15 @@ namespace O3DE::ProjectManager
{
projectInfo.m_projectName = Py_To_String(projectData["project_name"]);
projectInfo.m_displayName = Py_To_String_Optional(projectData, "display_name", projectInfo.m_projectName);
projectInfo.m_origin = Py_To_String_Optional(projectData, "origin", projectInfo.m_origin);
projectInfo.m_summary = Py_To_String_Optional(projectData, "summary", projectInfo.m_summary);
if (projectData.contains("user_tags"))
{
for (auto tag : projectData["user_tags"])
{
projectInfo.m_userTags.append(Py_To_String(tag));
}
}
}
catch ([[maybe_unused]] const std::exception& e)
{
@@ -748,9 +759,27 @@ namespace O3DE::ProjectManager
});
}
bool PythonBindings::UpdateProject([[maybe_unused]] const ProjectInfo& projectInfo)
AZ::Outcome<void, AZStd::string> PythonBindings::UpdateProject(const ProjectInfo& projectInfo)
{
return false;
return ExecuteWithLockErrorHandling([&]
{
std::list<std::string> newTags;
for (const auto& i : projectInfo.m_userTags)
{
newTags.push_back(i.toStdString());
}
m_editProjectProperties.attr("edit_project_props")(
pybind11::str(projectInfo.m_path.toStdString()), // proj_path
pybind11::none(), // proj_name not used
pybind11::str(projectInfo.m_origin.toStdString()), // new_origin
pybind11::str(projectInfo.m_displayName.toStdString()), // new_display
pybind11::str(projectInfo.m_summary.toStdString()), // new_summary
pybind11::str(projectInfo.m_imagePath.toStdString()), // new_icon
pybind11::none(), // add_tags not used
pybind11::none(), // remove_tags not used
pybind11::list(pybind11::cast(newTags))); // replace_tags
});
}
ProjectTemplateInfo PythonBindings::ProjectTemplateInfoFromPath(pybind11::handle path)
@@ -50,7 +50,7 @@ namespace O3DE::ProjectManager
AZ::Outcome<QVector<ProjectInfo>> GetProjects() override;
bool AddProject(const QString& path) override;
bool RemoveProject(const QString& path) override;
bool UpdateProject(const ProjectInfo& projectInfo) override;
AZ::Outcome<void, AZStd::string> UpdateProject(const ProjectInfo& projectInfo) override;
AZ::Outcome<void, AZStd::string> AddGemToProject(const QString& gemPath, const QString& projectPath) override;
AZ::Outcome<void, AZStd::string> RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override;
@@ -78,5 +78,6 @@ namespace O3DE::ProjectManager
pybind11::handle m_manifest;
pybind11::handle m_enableGemProject;
pybind11::handle m_disableGemProject;
pybind11::handle m_editProjectProperties;
};
}
@@ -122,7 +122,7 @@ namespace O3DE::ProjectManager
* @param projectInfo the info to use to update the project
* @return true on success, false on failure
*/
virtual bool UpdateProject(const ProjectInfo& projectInfo) = 0;
virtual AZ::Outcome<void, AZStd::string> UpdateProject(const ProjectInfo& projectInfo) = 0;
/**
* Add a gem to a project
@@ -58,7 +58,7 @@ namespace O3DE::ProjectManager
tabWidget->tabBar()->setObjectName("projectSettingsTabBar");
tabWidget->addTab(m_updateSettingsScreen, tr("General"));
QPushButton* gemsButton = new QPushButton(tr("Add More Gems"), this);
QPushButton* gemsButton = new QPushButton(tr("Configure Gems"), this);
topBarHLayout->addWidget(gemsButton);
tabWidget->setCornerWidget(gemsButton);
@@ -136,10 +136,10 @@ namespace O3DE::ProjectManager
// Update project if settings changed
if (m_projectInfo != newProjectSettings)
{
bool result = PythonBindingsInterface::Get()->UpdateProject(newProjectSettings);
if (!result)
auto result = PythonBindingsInterface::Get()->UpdateProject(newProjectSettings);
if (!result.IsSuccess())
{
QMessageBox::critical(this, tr("Project update failed"), tr("Failed to update project."));
QMessageBox::critical(this, tr("Project update failed"), tr(result.GetError().c_str()));
return;
}
}
@@ -189,7 +189,7 @@ namespace O3DE::ProjectManager
{
if (m_stack->currentIndex() == ScreenOrder::Gems)
{
m_header->setSubTitle(QString(tr("Add More Gems to \"%1\"")).arg(m_projectInfo.m_projectName));
m_header->setSubTitle(QString(tr("Configure Gems for \"%1\"")).arg(m_projectInfo.m_projectName));
m_nextButton->setText(tr("Confirm"));
}
else
@@ -1,14 +0,0 @@
/*
* 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 "StandaloneTools_precompiled.h"
@@ -10,7 +10,6 @@
#
set(FILES
StandaloneTools_precompiled.cpp
StandaloneTools_precompiled.h
targetver.h
Source/StandaloneToolsApplication.cpp
@@ -1,12 +0,0 @@
/*
* 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 "AssetMemoryAnalyzer_precompiled.h"
@@ -10,7 +10,6 @@
#
set(FILES
Source/AssetMemoryAnalyzer_precompiled.cpp
Source/AssetMemoryAnalyzer_precompiled.h
Include/AssetMemoryAnalyzer/AssetMemoryAnalyzerBus.h
Source/AssetMemoryAnalyzer.cpp
@@ -1,13 +0,0 @@
/*
* 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 "ImageProcessing_precompiled.h"
@@ -10,7 +10,6 @@
#
set(FILES
Source/ImageProcessing_precompiled.cpp
Source/ImageProcessing_precompiled.h
Source/Compressors/CryTextureSquisher/CryTextureSquisher.cpp
Source/Compressors/CryTextureSquisher/CryTextureSquisher.h
@@ -1,12 +0,0 @@
/*
* 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 <RHI/Atom_RHI_DX12_precompiled.h>
@@ -11,7 +11,6 @@
set(FILES
Source/RHI/Atom_RHI_DX12_precompiled.h
Source/RHI/Atom_RHI_DX12_precompiled.cpp
Source/RHI/Buffer.cpp
Source/RHI/Buffer.h
Source/RHI/BufferPool.cpp
@@ -1,12 +0,0 @@
/*
* 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 "Atom_RHI_Metal_precompiled.h"
@@ -10,6 +10,5 @@
#
set(FILES
Source/Atom_RHI_Metal_precompiled.cpp
Source/Atom_RHI_Metal_precompiled.h
)
@@ -1,12 +0,0 @@
/*
* 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 "Atom_RHI_Null_precompiled.h"
@@ -10,6 +10,5 @@
#
set(FILES
Source/Atom_RHI_Null_precompiled.cpp
Source/Atom_RHI_Null_precompiled.h
)
@@ -1,12 +0,0 @@
/*
* 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 "Atom_RHI_Vulkan_precompiled.h"
@@ -720,7 +720,7 @@ namespace AZ
StringList deviceExtensions = physicalDevice.GetDeviceExtensionNames();
StringList::iterator itRayTracingExtension = AZStd::find(deviceExtensions.begin(), deviceExtensions.end(), VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
m_features.m_rayTracing = (itRayTracingExtension != deviceExtensions.end());
m_features.m_unboundedArrays = true;
m_features.m_unboundedArrays = physicalDevice.GetPhysicalDeviceDescriptorIndexingFeatures().shaderStorageTexelBufferArrayNonUniformIndexing;
const auto& deviceLimits = physicalDevice.GetDeviceLimits();
m_limits.m_maxImageDimension1D = deviceLimits.maxImageDimension1D;
@@ -10,6 +10,5 @@
#
set(FILES
Source/Atom_RHI_Vulkan_precompiled.cpp
Source/Atom_RHI_Vulkan_precompiled.h
)
+1
View File
@@ -150,6 +150,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
PRIVATE
AZ::AtomCore
AZ::AzTest
AZ::AzTestShared
AZ::AzFramework
AZ::AzToolsFramework
Legacy::CryCommon
@@ -81,7 +81,7 @@ namespace AZ
//! Common arguments for free polygon (point, line, Triangle) draws.
struct AuxGeomDynamicDrawArguments
{
const AZ::Vector3* m_verts = nullptr; //!< An array of points, 1 for each vertice.
const AZ::Vector3* m_verts = nullptr; //!< An array of points, 1 for each vertex.
uint32_t m_vertCount = 0; //!< The number of vertices.
const AZ::Color* m_colors; //!< An array of colors, must have either vertCount entries or 1 entry.
uint32_t m_colorCount = 0; //!< The number of colors, must equal 1 or vertCount.
@@ -61,12 +61,13 @@ namespace AZ
//! Important: only to be used in the Editor, it may kick off a job to calculate spatial information.
//! [GFX TODO][ATOM-4343 Bake mesh spatial during AP processing]
//!
//! @param rayStart position where the ray starts
//! @param dir direction where the ray ends (does not have to be unit length)
//! @param distanceFactor if an intersection is detected, this will be set such that distanceFactor * dir.length == distance to intersection
//! @param normal if an intersection is detected, this will be set to the normal at the point of intersection
//! @return true if the ray intersects the mesh
bool LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const;
//! @param rayStart The starting point of the ray.
//! @param rayDir The direction and length of the ray (magnitude is encoded in the direction).
//! @param[out] distanceNormalized If an intersection is found, will be set to the normalized distance of the intersection
//! (in the range 0.0-1.0) - to calculate the actual distance, multiply distanceNormalized by the magnitude of rayDir.
//! @param[out] normal If an intersection is found, will be set to the normal at the point of collision.
//! @return True if the ray intersects the mesh.
bool LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const;
//! Checks a ray for intersection against this model, where the ray is in a different coordinate space.
//! Important: only to be used in the Editor, it may kick off a job to calculate spatial information.
@@ -74,13 +75,19 @@ namespace AZ
//!
//! @param modelTransform a transform that puts the model into the ray's coordinate space
//! @param nonUniformScale Non-uniform scale applied in the model's local frame.
//! @param rayStart position where the ray starts
//! @param dir direction where the ray ends (does not have to be unit length)
//! @param distanceFactor if an intersection is detected, this will be set such that distanceFactor * dir.length == distance to intersection
//! @param normal if an intersection is detected, this will be set to the normal at the point of intersection
//! @return true if the ray intersects the mesh
bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart,
const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const;
//! @param rayStart The starting point of the ray.
//! @param rayDir The direction and length of the ray (magnitude is encoded in the direction).
//! @param[out] distanceNormalized If an intersection is found, will be set to the normalized distance of the intersection
//! (in the range 0.0-1.0) - to calculate the actual distance, multiply distanceNormalized by the magnitude of rayDir.
//! @param[out] normal If an intersection is found, will be set to the normal at the point of collision.
//! @return True if the ray intersects the mesh.
bool RayIntersection(
const AZ::Transform& modelTransform,
const AZ::Vector3& nonUniformScale,
const AZ::Vector3& rayStart,
const AZ::Vector3& rayDir,
float& distanceNormalized,
AZ::Vector3& normal) const;
//! Get available UV names from the model and its lods.
const AZStd::unordered_set<AZ::Name>& GetUvNames() const;
@@ -63,12 +63,14 @@ namespace AZ
//! Important: only to be used in the Editor, it may kick off a job to calculate spatial information.
//! [GFX TODO][ATOM-4343 Bake mesh spatial information during AP processing]
//!
//! @param rayStart position where the ray starts
//! @param dir direction where the ray ends (does not have to be unit length)
//! @param distance if an intersection is detected, this will be set such that distanceFactor * dir.length == distance to intersection
//! @param normal if an intersection is detected, this will be set to the normal at the point of collision
//! @return true if the ray intersects the mesh
virtual bool LocalRayIntersectionAgainstModel(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const;
//! @param rayStart The starting point of the ray.
//! @param rayDir The direction and length of the ray (magnitude is encoded in the direction).
//! @param[out] distanceNormalized If an intersection is found, will be set to the normalized distance of the intersection
//! (in the range 0.0-1.0) - to calculate the actual distance, multiply distanceNormalized by the magnitude of rayDir.
//! @param[out] normal If an intersection is found, will be set to the normal at the point of collision.
//! @return True if the ray intersects the mesh.
virtual bool LocalRayIntersectionAgainstModel(
const AZ::Vector3& rayStart, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const;
private:
void SetReady();
@@ -79,9 +81,15 @@ namespace AZ
// mutable method
void BuildKdTree() const;
bool BruteForceRayIntersect(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const;
bool BruteForceRayIntersect(
const AZ::Vector3& rayStart, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const;
bool LocalRayIntersectionAgainstMesh(const ModelLodAsset::Mesh& mesh, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const;
bool LocalRayIntersectionAgainstMesh(
const ModelLodAsset::Mesh& mesh,
const AZ::Vector3& rayStart,
const AZ::Vector3& rayDir,
float& distanceNormalized,
AZ::Vector3& normal) const;
// Various model information used in raycasting
AZ::Name m_positionName{ "POSITION" };
@@ -137,12 +137,12 @@ namespace AZ
return m_modelAsset;
}
bool Model::LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
bool Model::LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
float start;
float end;
const int result = Intersect::IntersectRayAABB2(rayStart, dir.GetReciprocal(), m_aabb, start, end);
const int result = Intersect::IntersectRayAABB2(rayStart, rayDir.GetReciprocal(), m_aabb, start, end);
if (Intersect::ISECT_RAY_AABB_NONE != result)
{
if (ModelAsset* modelAssetPtr = m_modelAsset.Get())
@@ -151,7 +151,7 @@ namespace AZ
AZ::Debug::Timer timer;
timer.Stamp();
#endif
const bool hit = modelAssetPtr->LocalRayIntersectionAgainstModel(rayStart, dir, distance, normal);
const bool hit = modelAssetPtr->LocalRayIntersectionAgainstModel(rayStart, rayDir, distanceNormalized, normal);
#if defined(AZ_RPI_PROFILE_RAYCASTING_AGAINST_MODELS)
if (hit)
{
@@ -166,8 +166,12 @@ namespace AZ
}
bool Model::RayIntersection(
const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, const AZ::Vector3& dir,
float& distanceFactor, AZ::Vector3& normal) const
const AZ::Transform& modelTransform,
const AZ::Vector3& nonUniformScale,
const AZ::Vector3& rayStart,
const AZ::Vector3& rayDir,
float& distanceNormalized,
AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
const AZ::Vector3 clampedScale = nonUniformScale.GetMax(AZ::Vector3(AZ::MinTransformScale));
@@ -175,12 +179,13 @@ namespace AZ
const AZ::Transform inverseTM = modelTransform.GetInverse();
const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart) / clampedScale;
// Instead of just rotating 'dir' we need it to be scaled too, so that 'distanceFactor' will be in the target units rather than object local units.
const AZ::Vector3 rayDest = rayStart + dir;
// Instead of just rotating 'rayDir' we need it to be scaled too, so that 'distanceNormalized' will be in the target units rather
// than object local units.
const AZ::Vector3 rayDest = rayStart + rayDir;
const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest) / clampedScale;
const AZ::Vector3 rayDirLocal = rayDestLocal - raySrcLocal;
bool result = LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor, normal);
const bool result = LocalRayIntersection(raySrcLocal, rayDirLocal, distanceNormalized, normal);
normal = (normal * clampedScale).GetNormalized();
return result;
}
@@ -15,6 +15,7 @@
#include <AzCore/Debug/EventTrace.h>
#include <AzCore/Jobs/JobFunction.h>
#include <AzCore/Math/IntersectSegment.h>
#include <AzCore/std/limits.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Serialization/SerializeContext.h>
@@ -75,7 +76,8 @@ namespace AZ
m_status = Data::AssetData::AssetStatus::Ready;
}
bool ModelAsset::LocalRayIntersectionAgainstModel(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
bool ModelAsset::LocalRayIntersectionAgainstModel(
const AZ::Vector3& rayStart, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
@@ -85,7 +87,7 @@ namespace AZ
m_modelTriangleCount = CalculateTriangleCount();
}
// check the total vertex count for this model and skip kdtree if the model is simple enough
// check the total vertex count for this model and skip kd-tree if the model is simple enough
if (*m_modelTriangleCount > s_minimumModelTriangleCountToOptimize)
{
if (!m_kdTree)
@@ -97,11 +99,11 @@ namespace AZ
}
else
{
return m_kdTree->RayIntersection(rayStart, dir, distance, normal);
return m_kdTree->RayIntersection(rayStart, rayDir, distanceNormalized, normal);
}
}
return BruteForceRayIntersect(rayStart, dir, distance, normal);
return BruteForceRayIntersect(rayStart, rayDir, distanceNormalized, normal);
}
void ModelAsset::BuildKdTree() const
@@ -136,7 +138,8 @@ namespace AZ
}
}
bool ModelAsset::BruteForceRayIntersect(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
bool ModelAsset::BruteForceRayIntersect(
const AZ::Vector3& rayStart, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const
{
// brute force - check every triangle
if (GetLodAssets().empty() == false)
@@ -144,27 +147,27 @@ namespace AZ
// intersect against the highest level of detail
if (ModelLodAsset* loadAssetPtr = GetLodAssets()[0].Get())
{
float shortestDistance = std::numeric_limits<float>::max();
bool anyHit = false;
AZ::Vector3 intersectionNormal;
float shortestDistanceNormalized = AZStd::numeric_limits<float>::max();
for (const ModelLodAsset::Mesh& mesh : loadAssetPtr->GetMeshes())
{
if (LocalRayIntersectionAgainstMesh(mesh, rayStart, dir, distance, intersectionNormal))
float currentDistanceNormalized;
if (LocalRayIntersectionAgainstMesh(mesh, rayStart, rayDir, currentDistanceNormalized, intersectionNormal))
{
anyHit = true;
if (distance < shortestDistance)
if (currentDistanceNormalized < shortestDistanceNormalized)
{
normal = intersectionNormal;
shortestDistance = distance;
shortestDistanceNormalized = currentDistanceNormalized;
}
}
}
if (anyHit)
{
distance = shortestDistance;
distanceNormalized = shortestDistanceNormalized;
}
return anyHit;
@@ -174,7 +177,12 @@ namespace AZ
return false;
}
bool ModelAsset::LocalRayIntersectionAgainstMesh(const ModelLodAsset::Mesh& mesh, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
bool ModelAsset::LocalRayIntersectionAgainstMesh(
const ModelLodAsset::Mesh& mesh,
const AZ::Vector3& rayStart,
const AZ::Vector3& rayDir,
float& distanceNormalized,
AZ::Vector3& normal) const
{
const BufferAssetView& indexBufferView = mesh.GetIndexBufferAssetView();
const AZStd::array_view<ModelLodAsset::Mesh::StreamBufferInfo>& streamBufferList = mesh.GetStreamBufferInfoList();
@@ -217,14 +225,13 @@ namespace AZ
AZStd::array_view<uint8_t> indexRawBuffer = indexAssetViewPtr->GetBuffer();
RHI::BufferViewDescriptor indexRawDesc = indexAssetViewPtr->GetBufferViewDescriptor();
float closestNormalizedDistance = 1.f;
bool anyHit = false;
const AZ::Vector3 rayEnd = rayStart + dir * distance;
const AZ::Vector3 rayEnd = rayStart + rayDir;
AZ::Vector3 a, b, c;
AZ::Vector3 intersectionNormal;
float normalizedDistance = 1.f;
float shortestDistanceNormalized = AZStd::numeric_limits<float>::max();
const AZ::u32* indexPtr = reinterpret_cast<const AZ::u32*>(indexRawBuffer.data());
for (uint32_t indexIter = 0; indexIter <= indexRawDesc.m_elementCount - 3; indexIter += 3, indexPtr += 3)
{
@@ -247,20 +254,22 @@ namespace AZ
p = reinterpret_cast<const float*>(&positionRawBuffer[index2 * positionElementSize]);
c.Set(const_cast<float*>(p));
if (AZ::Intersect::IntersectSegmentTriangleCCW(rayStart, rayEnd, a, b, c, intersectionNormal, normalizedDistance))
float currentDistanceNormalized;
if (AZ::Intersect::IntersectSegmentTriangleCCW(rayStart, rayEnd, a, b, c, intersectionNormal, currentDistanceNormalized))
{
if (normalizedDistance < closestNormalizedDistance)
anyHit = true;
if (currentDistanceNormalized < shortestDistanceNormalized)
{
normal = intersectionNormal;
closestNormalizedDistance = normalizedDistance;
shortestDistanceNormalized = currentDistanceNormalized;
}
anyHit = true;
}
}
if (anyHit)
{
distance = closestNormalizedDistance * distance;
distanceNormalized = shortestDistanceNormalized;
}
return anyHit;
@@ -208,10 +208,10 @@ namespace AZ
bool ModelKdTree::RayIntersection(
const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const
{
float closestDistanceNormalized = AZStd::numeric_limits<float>::max();
if (RayIntersectionRecursively(m_pRootNode.get(), raySrc, rayDir, closestDistanceNormalized, normal))
float shortestDistanceNormalized = AZStd::numeric_limits<float>::max();
if (RayIntersectionRecursively(m_pRootNode.get(), raySrc, rayDir, shortestDistanceNormalized, normal))
{
distanceNormalized = closestDistanceNormalized;
distanceNormalized = shortestDistanceNormalized;
return true;
}
+196 -90
View File
@@ -22,6 +22,7 @@
#include <AzCore/std/limits.h>
#include <AzCore/Component/Entity.h>
#include <AZTestShared/Math/MathTestHelpers.h>
#include <AzTest/AzTest.h>
#include <Common/RPITestFixture.h>
@@ -568,7 +569,7 @@ namespace UnitTest
ValidateModelAsset(serializedModelAsset.Get(), expectedModel);
}
// Tests that if we try to set the name on a Model
// Tests that if we try to set the name on a Model
// before calling Begin that it will fail.
TEST_F(ModelTests, SetNameNoBegin)
{
@@ -581,7 +582,7 @@ namespace UnitTest
creator.SetName("TestName");
}
// Tests that if we try to add a ModelLod to a Model
// Tests that if we try to add a ModelLod to a Model
// before calling Begin that it will fail.
TEST_F(ModelTests, AddLodNoBegin)
{
@@ -598,7 +599,7 @@ namespace UnitTest
creator.AddLodAsset(AZStd::move(lod));
}
// Tests that if we create a ModelAsset without adding
// Tests that if we create a ModelAsset without adding
// any ModelLodAssets that the creator will properly fail to produce an asset.
TEST_F(ModelTests, CreateModelNoLods)
{
@@ -618,8 +619,8 @@ namespace UnitTest
ASSERT_EQ(asset.Get(), nullptr);
}
// Tests that if we call SetLodIndexBuffer without calling
// Begin first on the ModelLodAssetCreator that it
// Tests that if we call SetLodIndexBuffer without calling
// Begin first on the ModelLodAssetCreator that it
// fails as expected.
TEST_F(ModelTests, SetLodIndexBufferNoBegin)
{
@@ -633,8 +634,8 @@ namespace UnitTest
creator.SetLodIndexBuffer(validIndexBuffer);
}
// Tests that if we call AddLodStreamBuffer without calling
// Begin first on the ModelLodAssetCreator that it
// Tests that if we call AddLodStreamBuffer without calling
// Begin first on the ModelLodAssetCreator that it
// fails as expected.
TEST_F(ModelTests, AddLodStreamBufferNoBegin)
{
@@ -648,8 +649,8 @@ namespace UnitTest
creator.AddLodStreamBuffer(validStreamBuffer);
}
// Tests that if we call BeginMesh without calling
// Begin first on the ModelLodAssetCreator that it
// Tests that if we call BeginMesh without calling
// Begin first on the ModelLodAssetCreator that it
// fails as expected.
TEST_F(ModelTests, BeginMeshNoBegin)
{
@@ -662,13 +663,13 @@ namespace UnitTest
}
// Tests that if we try to set an AABB on a mesh
// without calling Begin or BeginMesh that it fails
// without calling Begin or BeginMesh that it fails
// as expected. Also tests the case that Begin *is*
// called but BeginMesh is not.
TEST_F(ModelTests, SetAabbNoBeginNoBeginMesh)
{
using namespace AZ;
RPI::ModelLodAssetCreator creator;
AZ::Aabb aabb = AZ::Aabb::CreateCenterRadius(AZ::Vector3::CreateZero(), 1.0f);
@@ -691,13 +692,13 @@ namespace UnitTest
}
// Tests that if we try to set the material id on a mesh
// without calling Begin or BeginMesh that it fails
// without calling Begin or BeginMesh that it fails
// as expected. Also tests the case that Begin *is*
// called but BeginMesh is not.
TEST_F(ModelTests, SetMaterialIdNoBeginNoBeginMesh)
{
using namespace AZ;
RPI::ModelLodAssetCreator creator;
{
@@ -715,7 +716,7 @@ namespace UnitTest
}
// Tests that if we try to set the index buffer on a mesh
// without calling Begin or BeginMesh that it fails
// without calling Begin or BeginMesh that it fails
// as expected. Also tests the case that Begin *is*
// called but BeginMesh is not.
TEST_F(ModelTests, SetIndexBufferNoBeginNoBeginMesh)
@@ -751,7 +752,7 @@ namespace UnitTest
}
// Tests that if we try to add a stream buffer on a mesh
// without calling Begin or BeginMesh that it fails
// without calling Begin or BeginMesh that it fails
// as expected. Also tests the case that Begin *is*
// called but BeginMesh is not.
TEST_F(ModelTests, AddStreamBufferNoBeginNoBeginMesh)
@@ -785,7 +786,7 @@ namespace UnitTest
}
}
// Tests that if we try to end the creation of a
// Tests that if we try to end the creation of a
// ModelLodAsset that has no meshes that it fails
// as expected.
TEST_F(ModelTests, CreateLodNoMeshes)
@@ -804,7 +805,7 @@ namespace UnitTest
ASSERT_EQ(asset.Get(), nullptr);
}
// Tests that validation still fails when expected
// Tests that validation still fails when expected
// even after producing a valid mesh due to a missing
// BeginMesh call
TEST_F(ModelTests, SecondMeshFailureNoBeginMesh)
@@ -862,8 +863,8 @@ namespace UnitTest
ASSERT_EQ(asset->GetMeshes().size(), 1);
}
// Tests that validation still fails when expected
// even after producing a valid mesh due to SetMeshX
// Tests that validation still fails when expected
// even after producing a valid mesh due to SetMeshX
// calls coming after End
TEST_F(ModelTests, SecondMeshAfterEnd)
{
@@ -907,7 +908,7 @@ namespace UnitTest
AZ::Aabb aabb = AZ::Aabb::CreateCenterRadius(Vector3::CreateZero(), 1.0f);
ErrorMessageFinder messageFinder("Begin() was not called", 6);
creator.BeginMesh();
creator.SetMeshAabb(AZStd::move(aabb));
creator.SetMeshMaterialAsset(m_materialAsset);
@@ -955,6 +956,20 @@ namespace UnitTest
EXPECT_EQ(uvStreamTangentBitmask.GetFullTangentBitmask(), 0x70000F51);
}
//
// +----+
// / /|
// +----+ |
// | | +
// | |/
// +----+
//
static constexpr AZStd::array CubePositions = { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f };
static constexpr AZStd::array CubeIndices = {
uint32_t{ 0 }, 2, 1, 1, 2, 3, 4, 5, 6, 5, 7, 6, 0, 4, 2, 4, 6, 2, 1, 3, 5, 5, 3, 7, 0, 1, 4, 4, 1, 5, 2, 6, 3, 6, 7, 3,
};
// This class creates a Model with one LOD, whose mesh contains 2 planes. Plane 1 is in the XY plane at Z=-0.5, and
// plane 2 is in the XY plane at Z=0.5. The two planes each have 9 quads which have been triangulated. It only has
// a position and index buffer.
@@ -972,52 +987,75 @@ namespace UnitTest
// *---*---*---*
// \ / \ / \ / \
// *---*---*---*
static constexpr AZStd::array TwoSeparatedPlanesPositions{
-1.0f, -0.333f, -0.5f, -0.333f, -1.0f, -0.5f, -0.333f, -0.333f, -0.5f, 0.333f, -0.333f, -0.5f, 1.0f, -1.0f, -0.5f,
1.0f, -0.333f, -0.5f, 0.333f, -1.0f, -0.5f, 0.333f, 1.0f, -0.5f, 1.0f, 0.333f, -0.5f, 1.0f, 1.0f, -0.5f,
0.333f, 0.333f, -0.5f, -0.333f, 1.0f, -0.5f, -0.333f, 0.333f, -0.5f, -1.0f, 1.0f, -0.5f, -1.0f, 0.333f, -0.5f,
-1.0f, -0.333f, 0.5f, -0.333f, -1.0f, 0.5f, -0.333f, -0.333f, 0.5f, 0.333f, -0.333f, 0.5f, 1.0f, -1.0f, 0.5f,
1.0f, -0.333f, 0.5f, -0.333f, -0.333f, 0.5f, 0.333f, -1.0f, 0.5f, 0.333f, -0.333f, 0.5f, 0.333f, 1.0f, 0.5f,
1.0f, 0.333f, 0.5f, 1.0f, 1.0f, 0.5f, 0.333f, 0.333f, 0.5f, 1.0f, -0.333f, 0.5f, -0.333f, 1.0f, 0.5f,
-0.333f, 0.333f, 0.5f, 0.333f, -0.333f, 0.5f, 0.333f, 0.333f, 0.5f, -1.0f, 1.0f, 0.5f, -0.333f, 0.333f, 0.5f,
-1.0f, 0.333f, 0.5f, -1.0f, -1.0f, -0.5f, -1.0f, -1.0f, 0.5f, 0.333f, -0.333f, 0.5f, 0.333f, -1.0f, 0.5f,
1.0f, -1.0f, 0.5f, 0.333f, -1.0f, 0.5f, 0.333f, 0.333f, 0.5f, 0.333f, -0.333f, 0.5f, 1.0f, -0.333f, 0.5f,
-0.333f, 0.333f, 0.5f, -0.333f, -0.333f, 0.5f, 0.333f, -0.333f, 0.5f,
};
// clang-format off
static constexpr AZStd::array TwoSeparatedPlanesIndices{
uint32_t{ 0 }, 1, 2, 3, 4, 5, 2, 6, 3, 7, 8, 9, 10, 5, 8, 11, 10, 7, 12, 3, 10, 13, 12, 11, 14, 2, 12,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 25, 29, 27, 24, 30, 31, 32, 33, 34, 29, 35, 17, 34,
0, 36, 1, 3, 6, 4, 2, 1, 6, 7, 10, 8, 10, 3, 5, 11, 12, 10, 12, 2, 3, 13, 14, 12, 14, 0, 2,
15, 37, 16, 38, 39, 40, 17, 16, 41, 24, 27, 25, 42, 43, 44, 29, 34, 27, 45, 46, 47, 33, 35, 34, 35, 15, 17,
};
// clang-format on
// Ensure that the index buffer references all the positions in the position buffer
static constexpr inline auto minmaxElement = AZStd::minmax_element(begin(TwoSeparatedPlanesIndices), end(TwoSeparatedPlanesIndices));
static_assert(*minmaxElement.second == (TwoSeparatedPlanesPositions.size() / 3) - 1);
template<class x> class TD;
class TwoSeparatedPlanesMesh
class TestMesh
{
public:
TwoSeparatedPlanesMesh()
TestMesh(const float* positions, size_t positionCount, const uint32_t* indices, size_t indicesCount)
{
using namespace AZ;
RPI::ModelLodAssetCreator lodCreator;
lodCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()));
AZ::RPI::ModelLodAssetCreator lodCreator;
lodCreator.Begin(AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
lodCreator.BeginMesh();
lodCreator.SetMeshAabb(Aabb::CreateFromMinMax({-1.0f, -1.0f, -0.5f}, {1.0f, 1.0f, 0.5f}));
lodCreator.SetMeshAabb(AZ::Aabb::CreateFromMinMax({-1.0f, -1.0f, -0.5f}, {1.0f, 1.0f, 0.5f}));
lodCreator.SetMeshMaterialAsset(
AZ::Data::Asset<AZ::RPI::MaterialAsset>(AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 0),
AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid(), "")
);
{
AZ::Data::Asset<AZ::RPI::BufferAsset> indexBuffer = BuildTestBuffer(s_indexes.size(), sizeof(uint32_t));
AZStd::copy(s_indexes.begin(), s_indexes.end(), reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(indexBuffer->GetBuffer().data())));
AZ::Data::Asset<AZ::RPI::BufferAsset> indexBuffer = BuildTestBuffer(indicesCount, sizeof(uint32_t));
AZStd::copy(indices, indices + indicesCount, reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(indexBuffer->GetBuffer().data())));
lodCreator.SetMeshIndexBuffer({
indexBuffer,
RHI::BufferViewDescriptor::CreateStructured(0, s_indexes.size(), sizeof(uint32_t))
AZ::RHI::BufferViewDescriptor::CreateStructured(0, indicesCount, sizeof(uint32_t))
});
}
{
AZ::Data::Asset<AZ::RPI::BufferAsset> positionBuffer = BuildTestBuffer(s_positions.size() / 3, sizeof(float) * 3);
AZStd::copy(s_positions.begin(), s_positions.end(), reinterpret_cast<float*>(const_cast<uint8_t*>(positionBuffer->GetBuffer().data())));
AZ::Data::Asset<AZ::RPI::BufferAsset> positionBuffer = BuildTestBuffer(positionCount / 3, sizeof(float) * 3);
AZStd::copy(positions, positions + positionCount, reinterpret_cast<float*>(const_cast<uint8_t*>(positionBuffer->GetBuffer().data())));
lodCreator.AddMeshStreamBuffer(
AZ::RHI::ShaderSemantic(AZ::Name("POSITION")),
AZ::Name(),
{
positionBuffer,
RHI::BufferViewDescriptor::CreateStructured(0, s_positions.size() / 3, sizeof(float) * 3)
AZ::RHI::BufferViewDescriptor::CreateStructured(0, positionCount / 3, sizeof(float) * 3)
}
);
}
lodCreator.EndMesh();
Data::Asset<RPI::ModelLodAsset> lodAsset;
AZ::Data::Asset<AZ::RPI::ModelLodAsset> lodAsset;
lodCreator.End(lodAsset);
RPI::ModelAssetCreator modelCreator;
modelCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()));
AZ::RPI::ModelAssetCreator modelCreator;
modelCreator.Begin(AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
modelCreator.SetName("TestModel");
modelCreator.AddLodAsset(AZStd::move(lodAsset));
modelCreator.End(m_modelAsset);
@@ -1030,40 +1068,20 @@ namespace UnitTest
private:
AZ::Data::Asset<AZ::RPI::ModelAsset> m_modelAsset;
static constexpr AZStd::array s_positions{
-1.0f, -0.333f, -0.5f, -0.333f, -1.0f, -0.5f, -0.333f, -0.333f, -0.5f, 0.333f, -0.333f, -0.5f, 1.0f, -1.0f, -0.5f,
1.0f, -0.333f, -0.5f, 0.333f, -1.0f, -0.5f, 0.333f, 1.0f, -0.5f, 1.0f, 0.333f, -0.5f, 1.0f, 1.0f, -0.5f,
0.333f, 0.333f, -0.5f, -0.333f, 1.0f, -0.5f, -0.333f, 0.333f, -0.5f, -1.0f, 1.0f, -0.5f, -1.0f, 0.333f, -0.5f,
-1.0f, -0.333f, 0.5f, -0.333f, -1.0f, 0.5f, -0.333f, -0.333f, 0.5f, 0.333f, -0.333f, 0.5f, 1.0f, -1.0f, 0.5f,
1.0f, -0.333f, 0.5f, -0.333f, -0.333f, 0.5f, 0.333f, -1.0f, 0.5f, 0.333f, -0.333f, 0.5f, 0.333f, 1.0f, 0.5f,
1.0f, 0.333f, 0.5f, 1.0f, 1.0f, 0.5f, 0.333f, 0.333f, 0.5f, 1.0f, -0.333f, 0.5f, -0.333f, 1.0f, 0.5f,
-0.333f, 0.333f, 0.5f, 0.333f, -0.333f, 0.5f, 0.333f, 0.333f, 0.5f, -1.0f, 1.0f, 0.5f, -0.333f, 0.333f, 0.5f,
-1.0f, 0.333f, 0.5f, -1.0f, -1.0f, -0.5f, -1.0f, -1.0f, 0.5f, 0.333f, -0.333f, 0.5f, 0.333f, -1.0f, 0.5f,
1.0f, -1.0f, 0.5f, 0.333f, -1.0f, 0.5f, 0.333f, 0.333f, 0.5f, 0.333f, -0.333f, 0.5f, 1.0f, -0.333f, 0.5f,
-0.333f, 0.333f, 0.5f, -0.333f, -0.333f, 0.5f, 0.333f, -0.333f, 0.5f,
};
static constexpr AZStd::array s_indexes{
uint32_t{0}, 1, 2, 3, 4, 5, 2, 6, 3, 7, 8, 9, 10, 5, 8, 11, 10, 7, 12, 3, 10, 13, 12, 11, 14, 2, 12,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 25, 29, 27, 24, 30, 31, 32, 33, 34, 29, 35, 17, 34,
0, 36, 1, 3, 6, 4, 2, 1, 6, 7, 10, 8, 10, 3, 5, 11, 12, 10, 12, 2, 3, 13, 14, 12, 14, 0, 2,
15, 37, 16, 38, 39, 40, 17, 16, 41, 24, 27, 25, 42, 43, 44, 29, 34, 27, 45, 46, 47, 33, 35, 34, 35, 15, 17,
};
// Ensure that the index buffer references all the positions in the position buffer
static constexpr inline auto minmaxElement = AZStd::minmax_element(begin(s_indexes), end(s_indexes));
static_assert(*minmaxElement.second == (s_positions.size() / 3) - 1);
};
struct KdTreeIntersectParams
struct IntersectParams
{
float xpos;
float ypos;
float zpos;
float xdir;
float ydir;
float zdir;
float expectedDistance;
bool expectedShouldIntersect;
friend std::ostream& operator<<(std::ostream& os, const KdTreeIntersectParams& param)
friend std::ostream& operator<<(std::ostream& os, const IntersectParams& param)
{
return os
<< "xpos:" << param.xpos
@@ -1076,13 +1094,15 @@ namespace UnitTest
class KdTreeIntersectsParameterizedFixture
: public ModelTests
, public ::testing::WithParamInterface<KdTreeIntersectParams>
, public ::testing::WithParamInterface<IntersectParams>
{
};
TEST_P(KdTreeIntersectsParameterizedFixture, KdTreeIntersects)
{
TwoSeparatedPlanesMesh mesh;
TestMesh mesh(
TwoSeparatedPlanesPositions.data(), TwoSeparatedPlanesPositions.size(), TwoSeparatedPlanesIndices.data(),
TwoSeparatedPlanesIndices.size());
AZ::RPI::ModelKdTree kdTree;
ASSERT_TRUE(kdTree.Build(mesh.GetModel().Get()));
@@ -1092,38 +1112,40 @@ namespace UnitTest
EXPECT_THAT(
kdTree.RayIntersection(
AZ::Vector3(GetParam().xpos, GetParam().ypos, GetParam().zpos), AZ::Vector3::CreateAxisZ(-1.0f), distance, normal),
AZ::Vector3(GetParam().xpos, GetParam().ypos, GetParam().zpos),
AZ::Vector3(GetParam().xdir, GetParam().ydir, GetParam().zdir), distance, normal),
testing::Eq(GetParam().expectedShouldIntersect));
EXPECT_THAT(distance, testing::FloatEq(GetParam().expectedDistance));
}
static constexpr inline AZStd::array<KdTreeIntersectParams, 21> intersectTestData{
KdTreeIntersectParams{ -0.1f, 0.0f, 1.0f, 0.5f, true },
KdTreeIntersectParams{ 0.0f, 0.0f, 1.0f, 0.5f, true },
KdTreeIntersectParams{ 0.1f, 0.0f, 1.0f, 0.5f, true },
static constexpr AZStd::array KdTreeIntersectTestData{
IntersectParams{ -0.1f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.1f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
// Test the center of each triangle
KdTreeIntersectParams{-0.111f, -0.111f, 1.0f, 0.5f, true},
KdTreeIntersectParams{-0.111f, -0.778f, 1.0f, 0.5f, true},
KdTreeIntersectParams{-0.111f, 0.555f, 1.0f, 0.5f, true}, // Should intersect triangle with indices {29, 34, 27} and {11, 12, 10}
KdTreeIntersectParams{-0.555f, -0.555f, 1.0f, 0.5f, true},
KdTreeIntersectParams{-0.555f, 0.111f, 1.0f, 0.5f, true},
KdTreeIntersectParams{-0.555f, 0.778f, 1.0f, 0.5f, true},
KdTreeIntersectParams{-0.778f, -0.111f, 1.0f, 0.5f, true},
KdTreeIntersectParams{-0.778f, -0.778f, 1.0f, 0.5f, true},
KdTreeIntersectParams{-0.778f, 0.555f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.111f, -0.555f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.111f, 0.111f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.111f, 0.778f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.555f, -0.111f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.555f, -0.778f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.555f, 0.555f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.778f, -0.555f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.778f, 0.111f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.778f, 0.778f, 1.0f, 0.5f, true},
IntersectParams{ -0.111f, -0.111f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ -0.111f, -0.778f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ -0.111f, 0.555f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f,
true }, // Should intersect triangle with indices {29, 34, 27} and {11, 12, 10}
IntersectParams{ -0.555f, -0.555f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ -0.555f, 0.111f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ -0.555f, 0.778f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ -0.778f, -0.111f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ -0.778f, -0.778f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ -0.778f, 0.555f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.111f, -0.555f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.111f, 0.111f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.111f, 0.778f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.555f, -0.111f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.555f, -0.778f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.555f, 0.555f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.778f, -0.555f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.778f, 0.111f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 0.778f, 0.778f, 1.0f, 0.0f, 0.0f, -1.0f, 0.5f, true },
};
INSTANTIATE_TEST_CASE_P(KdTreeIntersectsPlane, KdTreeIntersectsParameterizedFixture, ::testing::ValuesIn(intersectTestData));
INSTANTIATE_TEST_CASE_P(KdTreeIntersectsPlane, KdTreeIntersectsParameterizedFixture, ::testing::ValuesIn(KdTreeIntersectTestData));
class KdTreeIntersectsFixture
: public ModelTests
@@ -1133,7 +1155,10 @@ namespace UnitTest
{
ModelTests::SetUp();
m_mesh = AZStd::make_unique<TwoSeparatedPlanesMesh>();
m_mesh = AZStd::make_unique<TestMesh>(
TwoSeparatedPlanesPositions.data(), TwoSeparatedPlanesPositions.size(), TwoSeparatedPlanesIndices.data(),
TwoSeparatedPlanesIndices.size());
m_kdTree = AZStd::make_unique<AZ::RPI::ModelKdTree>();
ASSERT_TRUE(m_kdTree->Build(m_mesh->GetModel().Get()));
}
@@ -1146,7 +1171,7 @@ namespace UnitTest
ModelTests::TearDown();
}
AZStd::unique_ptr<TwoSeparatedPlanesMesh> m_mesh;
AZStd::unique_ptr<TestMesh> m_mesh;
AZStd::unique_ptr<AZ::RPI::ModelKdTree> m_kdTree;
};
@@ -1154,7 +1179,7 @@ namespace UnitTest
{
float t = AZStd::numeric_limits<float>::max();
AZ::Vector3 normal;
constexpr float rayLength = 100.0f;
EXPECT_THAT(
m_kdTree->RayIntersection(
@@ -1181,4 +1206,85 @@ namespace UnitTest
EXPECT_THAT(
m_kdTree->RayIntersection(AZ::Vector3::CreateAxisZ(5.0f), -AZ::Vector3::CreateAxisZ(), t, normal), testing::Eq(false));
}
class BruteForceIntersectsParameterizedFixture
: public ModelTests
, public ::testing::WithParamInterface<IntersectParams>
{
};
TEST_P(BruteForceIntersectsParameterizedFixture, BruteForceIntersectsCube)
{
TestMesh mesh(CubePositions.data(), CubePositions.size(), CubeIndices.data(), CubeIndices.size());
float distance = AZStd::numeric_limits<float>::max();
AZ::Vector3 normal;
EXPECT_THAT(
mesh.GetModel()->LocalRayIntersectionAgainstModel(
AZ::Vector3(GetParam().xpos, GetParam().ypos, GetParam().zpos),
AZ::Vector3(GetParam().xdir, GetParam().ydir, GetParam().zdir), distance, normal),
testing::Eq(GetParam().expectedShouldIntersect));
EXPECT_THAT(distance, testing::FloatEq(GetParam().expectedDistance));
}
static constexpr AZStd::array BruteForceIntersectTestData{
IntersectParams{ 5.0f, 0.0f, 5.0f, 0.0f, 0.0f, -1.0f, AZStd::numeric_limits<float>::max(), false },
IntersectParams{ 0.0f, 0.0f, 1.5f, 0.0f, 0.0f, -1.0f, 0.5f, true },
IntersectParams{ 5.0f, 0.0f, 0.0f, -10.0f, 0.0f, 0.0f, 0.4f, true },
IntersectParams{ -5.0f, 0.0f, 0.0f, 20.0f, 0.0f, 0.0f, 0.2f, true },
IntersectParams{ 0.0f, -10.0f, 0.0f, 0.0f, 20.0f, 0.0f, 0.45f, true },
IntersectParams{ 0.0f, 20.0f, 0.0f, 0.0f, -40.0f, 0.0f, 0.475f, true },
IntersectParams{ 0.0f, 20.0f, 0.0f, 0.0f, -19.0f, 0.0f, 1.0f, true },
};
INSTANTIATE_TEST_CASE_P(
BruteForceIntersects, BruteForceIntersectsParameterizedFixture, ::testing::ValuesIn(BruteForceIntersectTestData));
class BruteForceModelIntersectsFixture
: public ModelTests
{
public:
void SetUp() override
{
ModelTests::SetUp();
m_mesh = AZStd::make_unique<TestMesh>(CubePositions.data(), CubePositions.size(), CubeIndices.data(), CubeIndices.size());
}
void TearDown() override
{
m_mesh.reset();
ModelTests::TearDown();
}
AZStd::unique_ptr<TestMesh> m_mesh;
};
TEST_F(BruteForceModelIntersectsFixture, BruteForceIntersectionDetectedWithCube)
{
float t = 0.0f;
AZ::Vector3 normal;
// firing down the negative z axis, positioned 5 units from cube (cube is 2x2x2 so intersection
// happens at 1 in z)
EXPECT_THAT(
m_mesh->GetModel()->LocalRayIntersectionAgainstModel(
AZ::Vector3::CreateAxisZ(5.0f), -AZ::Vector3::CreateAxisZ(10.0f), t, normal),
testing::Eq(true));
EXPECT_THAT(t, testing::FloatEq(0.4f));
}
TEST_F(BruteForceModelIntersectsFixture, BruteForceIntersectionDetectedAndNormalSetAtEndOfRay)
{
float t = 0.0f;
AZ::Vector3 normal = AZ::Vector3::CreateOne(); // invalid starting normal
// ensure the intersection happens right at the end of the ray
EXPECT_THAT(
m_mesh->GetModel()->LocalRayIntersectionAgainstModel(
AZ::Vector3::CreateAxisY(10.0f), -AZ::Vector3::CreateAxisY(9.0f), t, normal),
testing::Eq(true));
EXPECT_THAT(t, testing::FloatEq(1.0f));
EXPECT_THAT(normal, IsClose(AZ::Vector3::CreateAxisY()));
}
} // namespace UnitTest
@@ -11,8 +11,8 @@
*/
/* Style for visualizing property values overridden from their prefab values */
AzToolsFramework--PropertyRowWidget[IsOverridden=true] QLabel
AzToolsFramework--PropertyRowWidget[IsOverridden="true"] QLabel
{
font-weight: bold;
color: #F5A623;
color: #1E70EB;
}
@@ -37,9 +37,6 @@
"factor": 0.4343433976173401,
"textureMap": "Materials/Bricks038_8K/Bricks038_8K_Roughness.png",
"useTexture": false
},
"subsurfaceScattering": {
"useThicknessMap": false
}
}
}
@@ -18,15 +18,6 @@
},
"opacity": {
"factor": 1.0
},
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
"quality": 1.0,
"scatterDistance": 2.626262664794922,
"subsurfaceScatterFactor": 1.0,
"thickness": 0.1414141058921814,
"transmissionMode": "ThinObject",
"transmissionScale": 1.8181817531585694
}
}
}
@@ -31,18 +31,6 @@
},
"roughness": {
"factor": 0.0
},
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
"quality": 1.0,
"scatterColor": [
0.045288778841495517,
0.24347294867038728,
0.2060578316450119,
1.0
],
"scatterDistance": 4.040403842926025,
"subsurfaceScatterFactor": 0.5
}
}
}
@@ -20,11 +20,6 @@
},
"roughness": {
"factor": 0.20202019810676576
},
"subsurfaceScattering": {
"quality": 0.329292893409729,
"scatterDistance": 6.666666507720947,
"subsurfaceScatterFactor": 0.9595959782600403
}
}
}
@@ -28,17 +28,6 @@
},
"specularF0": {
"factor": 1.0
},
"subsurfaceScattering": {
"quality": 0.9838383793830872,
"scatterColor": [
0.143602654337883,
0.012634470127522946,
0.0005798428319394589,
1.0
],
"scatterDistance": 18.383838653564454,
"subsurfaceScatterFactor": 0.1414141058921814
}
}
}
@@ -25,17 +25,6 @@
},
"specularF0": {
"factor": 1.0
},
"subsurfaceScattering": {
"quality": 0.9838383793830872,
"scatterColor": [
0.143602654337883,
0.012634470127522946,
0.0005798428319394589,
1.0
],
"scatterDistance": 18.383838653564454,
"subsurfaceScatterFactor": 0.1414141058921814
}
}
}
@@ -4,20 +4,15 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"occlusion": {
"diffuseTextureMap": "Textures/ceiling_1k_ao.png"
},
"baseColor": {
"textureBlendMode": "Lerp",
"color": [
0.800000011920929,
0.800000011920929,
0.800000011920929,
1.0
],
"textureMap": "Textures/ceiling_1k_basecolor.png"
},
"clearCoat": {
"enable": true,
"factor": 0.5,
"influenceMap": "Textures/ceiling_1k_ao.png",
"normalMap": "Textures/ceiling_1k_normal.png",
"roughness": 0.30000001192092898
},
"emissive": {
"color": [
0.0,
@@ -26,33 +21,8 @@
1.0
]
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"color": [
1.0,
0.7591058015823364,
0.43776607513427737,
1.0
]
},
"normal": {
"textureMap": "Textures/ceiling_1k_normal.png"
},
"opacity": {
"factor": 1.0
},
"parallax": {
"algorithm": "ContactRefinement",
"factor": 0.019999999552965165,
"pdo": true,
"quality": "Medium",
"textureMap": "Textures/ceiling_1k_height.png",
"useTexture": false
},
"roughness": {
"textureMap": "Textures/ceiling_1k_roughness.png"
}
}
}
}
@@ -13,31 +13,16 @@
],
"textureMap": "Textures/chain_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"emissive": {
"color": [
0.4891279339790344,
0.7931944727897644,
1.0,
0.0,
0.0,
0.0,
1.0
]
},
"metallic": {
"textureMap": "Textures/chain_alpha.png"
},
"normal": {
"textureMap": "Textures/chain_normal.jpg"
},
"opacity": {
"alphaSource": "Split",
"factor": 0.30000001192092898,
"mode": "Cutout",
"textureMap": "Textures/chain_alpha.png"
},
"roughness": {
"factor": 0.4000000059604645
"factor": 1.0
}
}
}
}
@@ -47,25 +47,6 @@
},
"roughness": {
"textureMap": "Textures/thorn_roughness.png"
},
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
"quality": 1.0,
"scatterColor": [
0.28143739700317385,
1.0,
0.13000686466693879,
1.0
],
"scatterDistance": 1.0,
"thickness": 0.10000000149011612,
"transmissionMode": "ThinObject",
"transmissionTint": [
0.07225146889686585,
0.16981765627861024,
0.04444953054189682,
1.0
]
}
}
}
@@ -4,9 +4,6 @@
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"occlusion": {
"diffuseTextureMap": "Textures/lion_1k_ao.png"
},
"baseColor": {
"color": [
0.800000011920929,
@@ -16,38 +13,16 @@
],
"textureMap": "Textures/lion_1k_basecolor.png"
},
"general": {
"applySpecularAA": true
},
"irradiance": {
"emissive": {
"color": [
1.0,
0.7364919781684876,
0.3672388792037964,
0.0,
0.0,
0.0,
1.0
]
},
"metallic": {
"textureMap": "Textures/lion_1k_metallic.png"
},
"normal": {
"textureMap": "Textures/lion_1k_normal.jpg"
},
"opacity": {
"factor": 1.0
},
"parallax": {
"algorithm": "ContactRefinement",
"factor": 0.009999999776482582,
"pdo": true,
"quality": "Ultra",
"textureMap": "Textures/lion_1k_height.png"
},
"roughness": {
"textureMap": "Textures/lion_1k_roughness.png"
},
"specularF0": {
"enableMultiScatterCompensation": true
}
}
}
}
@@ -28,24 +28,6 @@
"doubleSided": true,
"factor": 0.28999999165534975,
"mode": "Cutout"
},
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
"quality": 1.0,
"scatterColor": [
0.07421988248825073,
0.10223544389009476,
0.0,
1.0
],
"subsurfaceScatterFactor": 0.0,
"transmissionMode": "ThinObject",
"transmissionTint": [
0.33716335892677309,
0.4620737135410309,
0.0,
1.0
]
}
}
}
@@ -1,14 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include <AtomLyIntegration/AtomFont/AtomFont_precompiled.h>
@@ -33,5 +33,4 @@ set(FILES
Include/AtomLyIntegration/AtomFont/AtomNullFont.h
Include/AtomLyIntegration/AtomFont/resource.h
Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
Source/AtomFont_precompiled.cpp
)
@@ -18,6 +18,7 @@
#include <Integration/System/SystemCommon.h>
#include <Integration/System/SystemComponent.h>
#include <EMotionFX/Source/ActorInstance.h>
#include <EMotionFX/Source/DebugDraw.h>
#include <EMotionFX/Source/MorphSetup.h>
#include <EMotionFX/Source/MorphSetupInstance.h>
#include <EMotionFX/Source/MorphTargetStandard.h>
@@ -27,6 +28,8 @@
#include <EMotionFX/Source/Node.h>
#include <MCore/Source/AzCoreConversions.h>
#include <Atom/RPI.Public/AuxGeom/AuxGeomDraw.h>
#include <Atom/RPI.Public/AuxGeom/AuxGeomFeatureProcessorInterface.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/Image/StreamingImage.h>
@@ -57,6 +60,8 @@ namespace AZ
Activate();
AzFramework::BoundsRequestBus::Handler::BusConnect(m_entityId);
}
m_auxGeomFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity<RPI::AuxGeomFeatureProcessorInterface>(m_entityId);
}
AtomActorInstance::~AtomActorInstance()
@@ -88,7 +93,119 @@ namespace AZ
AZ::Interface<AzFramework::IEntityBoundsUnion>::Get()->RefreshEntityLocalBoundsUnion(m_entityId);
}
AZ::Aabb AtomActorInstance:: GetWorldBounds()
void AtomActorInstance::DebugDraw(const DebugOptions& debugOptions)
{
if (m_auxGeomFeatureProcessor)
{
if (RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue())
{
if (debugOptions.m_drawAABB)
{
const MCore::AABB emfxAabb = m_actorInstance->GetAABB();
const AZ::Aabb azAabb = AZ::Aabb::CreateFromMinMax(emfxAabb.GetMin(), emfxAabb.GetMax());
auxGeom->DrawAabb(azAabb, AZ::Color(0.0f, 1.0f, 1.0f, 1.0f), RPI::AuxGeomDraw::DrawStyle::Line);
}
if (debugOptions.m_drawSkeleton)
{
RenderSkeleton(auxGeom.get());
}
if (debugOptions.m_emfxDebugDraw)
{
RenderEMFXDebugDraw(auxGeom.get());
}
}
}
}
void AtomActorInstance::RenderSkeleton(RPI::AuxGeomDraw* auxGeom)
{
AZ_Assert(m_actorInstance, "Valid actor instance required.");
const EMotionFX::TransformData* transformData = m_actorInstance->GetTransformData();
const EMotionFX::Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton();
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
const AZ::u32 transformCount = transformData->GetNumTransforms();
const AZ::u32 lodLevel = m_actorInstance->GetLODLevel();
const AZ::u32 numJoints = skeleton->GetNumNodes();
m_auxVertices.clear();
m_auxVertices.reserve(numJoints * 2);
for (AZ::u32 jointIndex = 0; jointIndex < numJoints; ++jointIndex)
{
const EMotionFX::Node* joint = skeleton->GetNode(jointIndex);
if (!joint->GetSkeletalLODStatus(lodLevel))
{
continue;
}
const AZ::u32 parentIndex = joint->GetParentIndex();
if (parentIndex == InvalidIndex32)
{
continue;
}
const AZ::Vector3 parentPos = pose->GetWorldSpaceTransform(parentIndex).mPosition;
m_auxVertices.emplace_back(parentPos);
const AZ::Vector3 bonePos = pose->GetWorldSpaceTransform(jointIndex).mPosition;
m_auxVertices.emplace_back(bonePos);
}
const AZ::Color skeletonColor(0.604f, 0.804f, 0.196f, 1.0f);
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
lineArgs.m_verts = m_auxVertices.data();
lineArgs.m_vertCount = m_auxVertices.size();
lineArgs.m_colors = &skeletonColor;
lineArgs.m_colorCount = 1;
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
auxGeom->DrawLines(lineArgs);
}
void AtomActorInstance::RenderEMFXDebugDraw(RPI::AuxGeomDraw* auxGeom)
{
EMotionFX::DebugDraw& debugDraw = EMotionFX::GetDebugDraw();
debugDraw.Lock();
EMotionFX::DebugDraw::ActorInstanceData* actorInstanceData = debugDraw.GetActorInstanceData(m_actorInstance);
actorInstanceData->Lock();
const AZStd::vector<EMotionFX::DebugDraw::Line>& lines = actorInstanceData->GetLines();
if (lines.empty())
{
actorInstanceData->Unlock();
debugDraw.Unlock();
return;
}
m_auxVertices.clear();
m_auxVertices.reserve(lines.size() * 2);
m_auxColors.clear();
m_auxColors.reserve(m_auxVertices.size());
for (const EMotionFX::DebugDraw::Line& line : actorInstanceData->GetLines())
{
m_auxVertices.emplace_back(line.m_start);
m_auxColors.emplace_back(line.m_startColor);
m_auxVertices.emplace_back(line.m_end);
m_auxColors.emplace_back(line.m_endColor);
}
AZ_Assert(m_auxVertices.size() == m_auxColors.size(),
"Number of vertices and number of colors need to match.");
actorInstanceData->Unlock();
debugDraw.Unlock();
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
lineArgs.m_verts = m_auxVertices.data();
lineArgs.m_vertCount = m_auxVertices.size();
lineArgs.m_colors = m_auxColors.data();
lineArgs.m_colorCount = m_auxColors.size();
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
auxGeom->DrawLines(lineArgs);
}
AZ::Aabb AtomActorInstance::GetWorldBounds()
{
return m_worldAABB;
}
@@ -42,6 +42,8 @@ namespace EMotionFX
}
namespace AZ::RPI
{
class AuxGeomDraw;
class AuxGeomFeatureProcessorInterface;
class Model;
class Buffer;
class StreamingImage;
@@ -89,7 +91,7 @@ namespace AZ
// RenderActorInstance overrides ...
void OnTick(float timeDelta) override;
void UpdateBounds() override;
void DebugDraw(const DebugOptions& debugOptions) override { AZ_UNUSED(debugOptions) };
void DebugDraw(const DebugOptions& debugOptions) override;
void SetMaterials(const EMotionFX::Integration::ActorAsset::MaterialList& materialPerLOD) override { AZ_UNUSED(materialPerLOD); };
void SetSkinningMethod(EMotionFX::Integration::SkinningMethod emfxSkinningMethod);
SkinningMethod GetAtomSkinningMethod() const;
@@ -177,6 +179,13 @@ namespace AZ
void InitWrinkleMasks();
void UpdateWrinkleMasks();
// Helper and debug geometry rendering
void RenderSkeleton(RPI::AuxGeomDraw* auxGeom);
void RenderEMFXDebugDraw(RPI::AuxGeomDraw* auxGeom);
RPI::AuxGeomFeatureProcessorInterface* m_auxGeomFeatureProcessor = nullptr;
AZStd::vector<AZ::Vector3> m_auxVertices;
AZStd::vector<AZ::Color> m_auxColors;
AZStd::intrusive_ptr<AZ::Render::SkinnedMeshInputBuffers> m_skinnedMeshInputBuffers = nullptr;
AZStd::intrusive_ptr<SkinnedMeshInstance> m_skinnedMeshInstance;
AZ::Data::Instance<AZ::RPI::Buffer> m_boneTransforms = nullptr;

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