Merge branch 'stabilization/2106' into cpack/jenkins-main

main
scottr 5 years ago
commit 36929f59ae

@ -14679,6 +14679,25 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
<translation></translation>
</message>
</context>
<context>
<name>Method: NetBindComponent</name>
<message id="NETBINDCOMPONENT_ISNETENTITYROLEAUTHORITY_TOOLTIP">
<source>NETBINDCOMPONENT_ISNETENTITYROLEAUTHORITY_TOOLTIP</source>
<translation>Returns true if this network entity is an authoritative proxy on a server (full authority); otherwise false.</translation>
</message>
<message id="NETBINDCOMPONENT_ISNETENTITYROLEAUTONOMOUS_TOOLTIP">
<source>NETBINDCOMPONENT_ISNETENTITYROLEAUTONOMOUS_TOOLTIP</source>
<translation>Returns true if this network entity is an autonomous proxy on a client (can execute local prediction) or if this network entity is an authoritative proxy on a server but has autonomous privileges (ie: a host who is also a player); otherwise false.</translation>
</message>
<message id="NETBINDCOMPONENT_ISNETENTITYROLECLIENT_TOOLTIP">
<source>NETBINDCOMPONENT_ISNETENTITYROLECLIENT_TOOLTIP</source>
<translation>Returns true if this network entity is a simulated proxy on a client; otherwise false.</translation>
</message>
<message id="NETBINDCOMPONENT_ISNETENTITYROLESERVER_TOOLTIP">
<source>NETBINDCOMPONENT_ISNETENTITYROLESERVER_TOOLTIP</source>
<translation>Returns true if this network entity is a simulated proxy on a server (ie: a different server may own this entity, but the entity has been replicated to this server; otherwise false.</translation>
</message>
</context>
<context>
<name>Method: Math</name>
<message id="MATH_NAME">

@ -79,8 +79,6 @@ class TestBasicEditorWorkflows(EditorTestHelper):
grp_box = new_level_dlg.findChild(QtWidgets.QGroupBox, "STATIC_GROUP1")
level_name = grp_box.findChild(QtWidgets.QLineEdit, "LEVEL")
level_name.setText(self.args["level"])
level_folders = grp_box.findChild(QtWidgets.QComboBox, "LEVEL_FOLDERS")
level_folders.setCurrentText("Levels/")
button_box = new_level_dlg.findChild(QtWidgets.QDialogButtonBox, "buttonBox")
button_box.button(QtWidgets.QDialogButtonBox.Ok).click()

@ -57,7 +57,13 @@ namespace AZ
//! Determines if a component can be created from the asset type
//! This will be called before attempting to create a component from an asset (drag&drop, etc)
//! You can use this to filter by subIds or do your own validation here if needed
virtual bool CanCreateComponent(const AZ::Data::AssetId& /*assetId*/) const { return true; }
virtual bool CanCreateComponent([[maybe_unused]] const AZ::Data::AssetId& assetId) const { return true; }
//! Determines if other products conflict with the given one when multiple are generated from a source asset.
//! This will be called before attempting to create a component from an asset (drag&drop, etc)
//! You can use this to filter by conflicting product types or in case you want to skip for UX reasons.
//! @param[in] productAssetTypes Asset types of all generated products, including the one for our given type in this bus.
virtual bool HasConflictingProducts([[maybe_unused]] const AZStd::vector<AZ::Data::AssetType>& productAssetTypes) const { return false; }
};
using AssetTypeInfoBus = AZ::EBus<AssetTypeInfo>;

@ -1206,7 +1206,7 @@ namespace JsonSerializationTests
if (this->m_features.m_enableInitializationTest)
{
auto instance = this->m_description.CreateDefaultInstance();
typename TypeParam::Type compare = typename TypeParam::Type{};
AZStd::remove_cvref_t<typename TypeParam::Type> compare;
if (!this->m_description.AreEqual(*instance, compare))
{
auto serializer = this->m_description.CreateSerializer();

@ -75,6 +75,8 @@ namespace AzFramework
// Add a fullscreen button in the upper right of the title bar.
[m_nativeWindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
m_nativeWindow.tabbingMode = NSWindowTabbingModeDisallowed;
// Make the window active
[m_nativeWindow makeKeyAndOrderFront:nil];
m_nativeWindow.title = m_windowTitle;

@ -493,7 +493,30 @@ namespace AzQtComponents
}
}
break;
}
case CE_MenuItem:
{
const QMenu* menu = qobject_cast<const QMenu*>(widget);
QAction* action = menu->activeAction();
if (action)
{
QMenu* subMenu = action->menu();
if (subMenu)
{
QVariant noHover = subMenu->property("noHover");
if (noHover.isValid() && noHover.toBool())
{
// First draw as standard to get the correct hover background for the complete control.
QProxyStyle::drawControl(element, option, painter, widget);
// Now draw the icon as non-hovered so control behaves as designed.
QStyleOptionMenuItem myOpt = *qstyleoption_cast<const QStyleOptionMenuItem*>(option);
myOpt.state &= ~QStyle::State_Selected;
return QProxyStyle::drawControl(element, &myOpt, painter, widget);
}
}
}
}
break;
}
return QProxyStyle::drawControl(element, option, painter, widget);
}

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Helpers Icon</title>
<defs>
<circle id="path-1" cx="8" cy="8" r="8"></circle>
<path d="M8.59736328,10.1821289 L8.59736328,9.79394531 C8.59736328,9.07617188 8.86835937,8.71728516 9.84248047,8.15332031 C10.8751953,7.54541016 11.4098633,6.77636719 11.4098633,5.67041016 C11.4098633,4.00048828 10.0255859,2.8359375 7.93085937,2.8359375 C5.68232422,2.8359375 4.40791016,4.09570312 4.37128906,5.89746094 L6.35615234,5.89746094 C6.40009766,5.06982422 6.95673828,4.53515625 7.79902344,4.53515625 C8.63398437,4.53515625 9.190625,5.04052734 9.190625,5.73632812 C9.190625,6.43212891 8.90498047,6.79101562 7.96015625,7.35498047 C6.94941406,7.94824219 6.54658203,8.60742188 6.64179687,9.75732422 L6.65644531,10.1821289 L8.59736328,10.1821289 Z M7.70380859,13.7124023 C8.52412109,13.7124023 9.02949219,13.2436523 9.02949219,12.4892578 C9.02949219,11.7275391 8.52412109,11.2587891 7.70380859,11.2587891 C6.88349609,11.2587891 6.37080078,11.7275391 6.37080078,12.4892578 C6.37080078,13.2436523 6.88349609,13.7124023 7.70380859,13.7124023 Z" id="path-3"></path>
</defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="2nd-ToolBar-v2-(Perspective)-3" transform="translate(-1161.000000, -7.000000)">
<g id="2nd-ToolBar-buttons-on-right" transform="translate(1076.000000, 5.000000)">
<g id="Helpers-Icon" transform="translate(85.000000, 2.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Oval" fill="#FFFFFF" xlink:href="#path-1"></use>
<g id="?" fill-rule="nonzero" mask="url(#mask-2)">
<use fill="#909090" xlink:href="#path-3"></use>
<use fill="#3F3F3F" xlink:href="#path-3"></use>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Buttons / Dropdown button with Icon / no arrow</title>
<g id="Buttons-/-Dropdown-button-with-Icon-/-no-arrow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons-/-System-/-Menu" fill="#FFFFFF">
<rect id="Rectangle-11" x="1.33333333" y="2.66666667" width="13.3333333" height="1.33333333"></rect>
<rect id="Rectangle-11" x="1.33333333" y="7.33333333" width="13.3333333" height="1.33333333"></rect>
<rect id="Rectangle-11" x="1.33333333" y="12" width="13.3333333" height="1.33333333"></rect>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 786 B

@ -1,4 +1,4 @@
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.0708 0.87087L11.0708 0.87074C10.4286 0.371024 9.61107 0.13517 8.79265 0.213464C7.97422 0.291757 7.21961 0.678004 6.6897 1.28985L5.76756 2.36366C5.63378 2.51944 5.56909 2.72055 5.58771 2.92273C5.60634 3.12492 5.70675 3.31163 5.86686 3.44178C6.02698 3.57194 6.23368 3.63488 6.44149 3.61676C6.6493 3.59864 6.8412 3.50094 6.97498 3.34516L7.89716 2.27122C8.03184 2.11488 8.19736 1.98639 8.38395 1.89334C8.57053 1.8003 8.7744 1.74459 8.98349 1.7295C9.19258 1.71442 9.40266 1.74027 9.60131 1.80552C9.79996 1.87078 9.98315 1.97411 10.1401 2.10942C10.4422 2.38256 10.6244 2.75851 10.6488 3.15904C10.6732 3.55957 10.5379 3.95383 10.2711 4.25978L8.35381 6.49309L8.33616 6.51209C8.23375 6.62767 8.11374 6.72729 7.98031 6.80749C7.67189 6.99364 7.30661 7.06983 6.94686 7.02305C6.58711 6.97626 6.25522 6.8094 6.00789 6.55097C5.86556 6.40288 5.66865 6.31578 5.46039 6.30879C5.25213 6.30179 5.04952 6.37546 4.89703 6.51365C4.74453 6.65183 4.65462 6.84323 4.64701 7.04584C4.6394 7.24845 4.71472 7.44572 4.85645 7.59436C5.21222 7.96578 5.65746 8.24515 6.15198 8.40726C6.6465 8.56937 7.17473 8.60911 7.68898 8.52289C7.84983 8.49539 8.00828 8.45599 8.16298 8.40505C8.70939 8.22568 9.19408 7.90261 9.56335 7.47165L11.4758 5.24457C11.7478 4.92529 11.9523 4.55683 12.0773 4.16038C12.2024 3.76394 12.2457 3.34735 12.2046 2.93457C12.1671 2.53429 12.0475 2.1454 11.8527 1.79092C11.658 1.43644 11.3921 1.12358 11.0708 0.87087Z" fill="white"/>
<path d="M5.40958 9.14055L4.58546 10.1003C4.32342 10.4101 3.94867 10.6097 3.53919 10.6576C3.12972 10.7054 2.71706 10.5977 2.3871 10.357C2.22234 10.2309 2.08525 10.0738 1.98392 9.89526C1.8826 9.71668 1.81911 9.52014 1.79719 9.31727C1.77528 9.1144 1.79539 8.90932 1.85634 8.71414C1.91729 8.51896 2.01784 8.33765 2.15204 8.18093L4.10231 5.90975L4.11666 5.89415C4.21908 5.77861 4.3391 5.67903 4.47254 5.59887C4.75216 5.42921 5.07976 5.34988 5.4085 5.37222C5.73725 5.39457 6.05033 5.51745 6.30299 5.72329C6.3635 5.77246 6.42015 5.82595 6.47246 5.88333C6.54738 5.9658 6.63971 6.03156 6.74316 6.07611C6.84661 6.12066 6.95872 6.14295 7.07184 6.14146C7.18361 6.13992 7.29372 6.11492 7.39465 6.06817C7.49558 6.02143 7.58495 5.95403 7.65666 5.8706L7.66607 5.85958C7.78641 5.72083 7.85132 5.54454 7.8489 5.36301C7.84647 5.18148 7.77687 5.00689 7.65286 4.87124C7.35341 4.54132 6.98422 4.27825 6.57057 4.10003C6.15692 3.92182 5.70858 3.83266 5.25623 3.83866C4.80388 3.84467 4.35821 3.94569 3.94971 4.13482C3.54122 4.32395 3.17954 4.59672 2.88945 4.93446L0.944626 7.19943C0.420065 7.81564 0.163643 8.60683 0.230025 9.40433C0.296406 10.2018 0.68034 10.9426 1.29998 11.4686C1.61272 11.7312 1.97644 11.9301 2.3696 12.0535C2.76277 12.1769 3.17738 12.2223 3.5889 12.187C3.687 12.1793 3.78434 12.1672 3.88093 12.1507C4.62877 12.0232 5.30663 11.6437 5.79562 11.0786L6.617 10.1221C6.75077 9.96628 6.81547 9.76517 6.79684 9.56299C6.77822 9.3608 6.6778 9.17409 6.51769 9.04394C6.35758 8.91378 6.15088 8.85084 5.94306 8.86896C5.73525 8.88708 5.54335 8.98477 5.40957 9.14055H5.40958Z" fill="white"/>
<path d="M11.0708 0.87087L11.0708 0.87074C10.4286 0.371024 9.61107 0.13517 8.79265 0.213464C7.97422 0.291757 7.21961 0.678004 6.6897 1.28985L5.76756 2.36366C5.63378 2.51944 5.56909 2.72055 5.58771 2.92273C5.60634 3.12492 5.70675 3.31163 5.86686 3.44178C6.02698 3.57194 6.23368 3.63488 6.44149 3.61676C6.6493 3.59864 6.8412 3.50094 6.97498 3.34516L7.89716 2.27122C8.03184 2.11488 8.19736 1.98639 8.38395 1.89334C8.57053 1.8003 8.7744 1.74459 8.98349 1.7295C9.19258 1.71442 9.40266 1.74027 9.60131 1.80552C9.79996 1.87078 9.98315 1.97411 10.1401 2.10942C10.4422 2.38256 10.6244 2.75851 10.6488 3.15904C10.6732 3.55957 10.5379 3.95383 10.2711 4.25978L8.35381 6.49309L8.33616 6.51209C8.23375 6.62767 8.11374 6.72729 7.98031 6.80749C7.67189 6.99364 7.30661 7.06983 6.94686 7.02305C6.58711 6.97626 6.25522 6.8094 6.00789 6.55097C5.86556 6.40288 5.66865 6.31578 5.46039 6.30879C5.25213 6.30179 5.04952 6.37546 4.89703 6.51365C4.74453 6.65183 4.65462 6.84323 4.64701 7.04584C4.6394 7.24845 4.71472 7.44572 4.85645 7.59436C5.21222 7.96578 5.65746 8.24515 6.15198 8.40726C6.6465 8.56937 7.17473 8.60911 7.68898 8.52289C7.84983 8.49539 8.00828 8.45599 8.16298 8.40505C8.70939 8.22568 9.19408 7.90261 9.56335 7.47165L11.4758 5.24457C11.7478 4.92529 11.9523 4.55683 12.0773 4.16038C12.2024 3.76394 12.2457 3.34735 12.2046 2.93457C12.1671 2.53429 12.0475 2.1454 11.8527 1.79092C11.658 1.43644 11.3921 1.12358 11.0708 0.87087Z" fill="#3F3F3F"/>
<path d="M5.40958 9.14055L4.58546 10.1003C4.32342 10.4101 3.94867 10.6097 3.53919 10.6576C3.12972 10.7054 2.71706 10.5977 2.3871 10.357C2.22234 10.2309 2.08525 10.0738 1.98392 9.89526C1.8826 9.71668 1.81911 9.52014 1.79719 9.31727C1.77528 9.1144 1.79539 8.90932 1.85634 8.71414C1.91729 8.51896 2.01784 8.33765 2.15204 8.18093L4.10231 5.90975L4.11666 5.89415C4.21908 5.77861 4.3391 5.67903 4.47254 5.59887C4.75216 5.42921 5.07976 5.34988 5.4085 5.37222C5.73725 5.39457 6.05033 5.51745 6.30299 5.72329C6.3635 5.77246 6.42015 5.82595 6.47246 5.88333C6.54738 5.9658 6.63971 6.03156 6.74316 6.07611C6.84661 6.12066 6.95872 6.14295 7.07184 6.14146C7.18361 6.13992 7.29372 6.11492 7.39465 6.06817C7.49558 6.02143 7.58495 5.95403 7.65666 5.8706L7.66607 5.85958C7.78641 5.72083 7.85132 5.54454 7.8489 5.36301C7.84647 5.18148 7.77687 5.00689 7.65286 4.87124C7.35341 4.54132 6.98422 4.27825 6.57057 4.10003C6.15692 3.92182 5.70858 3.83266 5.25623 3.83866C4.80388 3.84467 4.35821 3.94569 3.94971 4.13482C3.54122 4.32395 3.17954 4.59672 2.88945 4.93446L0.944626 7.19943C0.420065 7.81564 0.163643 8.60683 0.230025 9.40433C0.296406 10.2018 0.68034 10.9426 1.29998 11.4686C1.61272 11.7312 1.97644 11.9301 2.3696 12.0535C2.76277 12.1769 3.17738 12.2223 3.5889 12.187C3.687 12.1793 3.78434 12.1672 3.88093 12.1507C4.62877 12.0232 5.30663 11.6437 5.79562 11.0786L6.617 10.1221C6.75077 9.96628 6.81547 9.76517 6.79684 9.56299C6.77822 9.3608 6.6778 9.17409 6.51769 9.04394C6.35758 8.91378 6.15088 8.85084 5.94306 8.86896C5.73525 8.88708 5.54335 8.98477 5.40957 9.14055H5.40958Z" fill="#3F3F3F"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -28,5 +28,7 @@
<file alias="script_canvas_editor.svg">Menu/script_canvas_editor.svg</file>
<file alias="trackview_editor.svg">Menu/trackview_editor.svg</file>
<file alias="ui_editor.svg">Menu/ui_editor.svg</file>
<file alias="menu.svg">Menu/menu.svg</file>
<file alias="helpers.svg">Menu/helpers.svg</file>
</qresource>
</RCC>

@ -524,8 +524,6 @@ namespace AzToolsFramework
rootSpawnableIndex = m_playInEditorData.m_assets.size();
}
LoadReferencedAssets(product.GetReferencedAssets());
AZ::Data::AssetInfo info;
info.m_assetId = product.GetAsset().GetId();
info.m_assetType = product.GetAssetType();
@ -534,6 +532,19 @@ namespace AzToolsFramework
AZ::Data::AssetCatalogRequestBus::Broadcast(
&AZ::Data::AssetCatalogRequestBus::Events::RegisterAsset, info.m_assetId, info);
m_playInEditorData.m_assets.emplace_back(product.ReleaseAsset().release(), AZ::Data::AssetLoadBehavior::Default);
// Ensure the product asset is registered with the AssetManager
// Hold on to the returned asset to keep ref count alive until we assign it the latest data
AZ::Data::Asset<AZ::Data::AssetData> asset =
AZ::Data::AssetManager::Instance().FindOrCreateAsset(info.m_assetId, info.m_assetType, AZ::Data::AssetLoadBehavior::Default);
// Update the asset registered in the AssetManager with the data of our product from the Prefab Processor
AZ::Data::AssetManager::Instance().AssignAssetData(m_playInEditorData.m_assets.back());
}
for (auto& product : context.GetProcessedObjects())
{
LoadReferencedAssets(product.GetReferencedAssets());
}
// make sure that PRE_NOTIFY assets get their notify before we activate, so that we can preserve the order of

@ -922,8 +922,8 @@ namespace AzToolsFramework
return AZ::Failure(AZStd::string("Failed to duplicate : Couldn't get a valid owning instance for the common root entity of the entities provided."));
}
// If the first entity id is a container entity id, then we need to mark its parent as the common owning instance because you
// cannot duplicate an instance from itself.
// If the first entity id is a container entity id, then we need to mark its parent as the common owning instance
// This is because containers, despite representing the nested instance in the parent, are owned by the child.
if (commonOwningInstance->get().GetContainerEntityId() == firstEntityIdToDuplicate)
{
commonOwningInstance = commonOwningInstance->get().GetParentInstance();
@ -967,17 +967,18 @@ namespace AzToolsFramework
// Duplicate any nested entities and instances as requested
AZStd::unordered_map<InstanceAlias, Instance*> newInstanceAliasToOldInstanceMap;
AZStd::unordered_map<EntityAlias, EntityAlias> duplicateEntityAliasMap;
DuplicateNestedEntitiesInInstance(commonOwningInstance->get(),
entities, instanceDomAfter, duplicatedEntityAndInstanceIds);
DuplicateNestedInstancesInInstance(commonOwningInstance->get(),
instances, instanceDomAfter, duplicatedEntityAndInstanceIds,
newInstanceAliasToOldInstanceMap);
entities, instanceDomAfter, duplicatedEntityAndInstanceIds, duplicateEntityAliasMap);
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity/Instance duplication");
command->SetParent(undoBatch.GetUndoBatch());
command->Capture(instanceDomBefore, instanceDomAfter, commonOwningInstance->get().GetTemplateId());
command->Redo();
DuplicateNestedInstancesInInstance(commonOwningInstance->get(),
instances, instanceDomAfter, duplicatedEntityAndInstanceIds, newInstanceAliasToOldInstanceMap);
// Create links for our duplicated instances (if any were duplicated)
for (auto [newInstanceAlias, oldInstance] : newInstanceAliasToOldInstanceMap)
{
@ -995,8 +996,35 @@ namespace AzToolsFramework
PrefabDom linkPatchesCopy;
linkPatchesCopy.CopyFrom(linkPatches->get(), linkPatchesCopy.GetAllocator());
m_prefabSystemComponentInterface->CreateLink(
commonOwningInstance->get().GetTemplateId(), oldInstance->GetTemplateId(), newInstanceAlias, linkPatchesCopy);
// If the instance was duplicated as part of an ancestor's nested hierarchy, the container's parent patch
// will need to be refreshed to point to the new duplicated parent entity
auto oldInstanceContainerEntityId = oldInstance->GetContainerEntityId();
AZ_Assert(oldInstanceContainerEntityId.IsValid(), "Instance returned invalid Container Entity Id");
AZ::EntityId previousParentEntityId;
AZ::TransformBus::EventResult(previousParentEntityId, oldInstanceContainerEntityId, &AZ::TransformBus::Events::GetParentId);
if (previousParentEntityId.IsValid() && AZStd::find(duplicatedEntityAndInstanceIds.begin(), duplicatedEntityAndInstanceIds.end(), previousParentEntityId))
{
auto oldParentAlias = commonOwningInstance->get().GetEntityAlias(previousParentEntityId);
if (oldParentAlias.has_value() && duplicateEntityAliasMap.contains(oldParentAlias->get()))
{
// Get the dom into a QString for search/replace purposes
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
linkPatchesCopy.Accept(writer);
QString linkPatchesString(buffer.GetString());
ReplaceOldAliases(linkPatchesString, oldParentAlias->get(), duplicateEntityAliasMap[oldParentAlias->get()]);
linkPatchesCopy.Parse(linkPatchesString.toUtf8().constData());
}
}
PrefabUndoHelpers::CreateLink(
oldInstance->GetTemplateId(), commonOwningInstance->get().GetTemplateId(),
AZStd::move(linkPatchesCopy), newInstanceAlias, undoBatch.GetUndoBatch());
}
// Select the duplicated entities/instances
@ -1507,14 +1535,13 @@ namespace AzToolsFramework
void PrefabPublicHandler::DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
EntityIdList& duplicatedEntityIds)
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<EntityAlias, EntityAlias>& oldAliasToNewAliasMap)
{
if (entities.empty())
{
return;
}
AZStd::unordered_map<EntityAlias, EntityAlias> oldAliasToNewAliasMap;
AZStd::unordered_map<EntityAlias, QString> aliasToEntityDomMap;
for (AZ::Entity* entity : entities)

@ -87,7 +87,7 @@ namespace AzToolsFramework
*/
void DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
EntityIdList& duplicatedEntityIds);
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<EntityAlias, EntityAlias>& oldAliasToNewAliasMap);
/**
* Duplicate a list of instances owned by a common owning instance by directly
* copying/modifying their entries in the instance DOM

@ -13,6 +13,7 @@
#include <AzCore/Math/ToString.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzFramework/Components/NonUniformScaleComponent.h>
#include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h>
@ -57,6 +58,13 @@ namespace AzToolsFramework
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly);
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->ConstantProperty("EditorNonUniformScaleComponentTypeId", BehaviorConstant(EditorNonUniformScaleComponent::RTTI_Type()))
->Attribute(AZ::Script::Attributes::Module, "editor")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation);
}
}
void EditorNonUniformScaleComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)

@ -210,6 +210,19 @@ namespace AzToolsFramework
//! Type to inherit to implement ViewportInteractionRequests.
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
//! An interface to notify when changes to viewport settings have happened.
class ViewportSettingNotifications
{
public:
virtual void OnGridSnappingChanged([[maybe_unused]] bool enabled) {}
virtual void OnDrawHelpersChanged([[maybe_unused]] bool enabled) {}
protected:
ViewportSettingNotifications() = default;
};
using ViewportSettingsNotificationBus = AZ::EBus<ViewportSettingNotifications, ViewportEBusTraits>;
//! Requests to freeze the Viewport Input
//! Added to prevent a bug with the legacy CryEngine Viewport code that would
//! keep doing raycast tests even when no level is loaded, causing a crash.

@ -56,7 +56,8 @@ namespace AzAssetBrowserRequestHandlerPrivate
using namespace AzToolsFramework;
using namespace AzToolsFramework::AssetBrowser;
// return true ONLY if we can handle the drop request in the viewport.
bool CanSpawnEntityForProduct(const ProductAssetBrowserEntry* product)
bool CanSpawnEntityForProduct(const ProductAssetBrowserEntry* product,
AZStd::optional<const AZStd::vector<AZ::Data::AssetType>> optionalProductAssetTypes = AZStd::nullopt)
{
if (!product)
{
@ -70,7 +71,6 @@ namespace AzAssetBrowserRequestHandlerPrivate
bool canCreateComponent = false;
AZ::AssetTypeInfoBus::EventResult(canCreateComponent, product->GetAssetType(), &AZ::AssetTypeInfo::CanCreateComponent, product->GetAssetId());
if (!canCreateComponent)
{
return false;
@ -78,16 +78,25 @@ namespace AzAssetBrowserRequestHandlerPrivate
AZ::Uuid componentTypeId = AZ::Uuid::CreateNull();
AZ::AssetTypeInfoBus::EventResult(componentTypeId, product->GetAssetType(), &AZ::AssetTypeInfo::GetComponentTypeId);
if (!componentTypeId.IsNull())
if (componentTypeId.IsNull())
{
// we have a component type that handles this asset.
return true;
return false;
}
if (optionalProductAssetTypes.has_value())
{
bool hasConflictingProducts = false;
AZ::AssetTypeInfoBus::EventResult(hasConflictingProducts, product->GetAssetType(), &AZ::AssetTypeInfo::HasConflictingProducts, optionalProductAssetTypes.value());
if (hasConflictingProducts)
{
return false;
}
}
// additional operations can be added here.
return false;
return true;
}
void SpawnEntityAtPoint(const ProductAssetBrowserEntry* product, AzQtComponents::ViewportDragContext* viewportDragContext, EntityIdList& spawnList, AzFramework::SliceInstantiationTicket& spawnTicket)
@ -511,9 +520,16 @@ void AzAssetBrowserRequestHandler::Drop(QDropEvent* event, AzQtComponents::DragA
}
// Handle products
AZStd::vector<AZ::Data::AssetType> productAssetTypes;
productAssetTypes.reserve(products.size());
for (const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry* entry : products)
{
productAssetTypes.emplace_back(entry->GetAssetType());
}
for (const ProductAssetBrowserEntry* product : products)
{
if (CanSpawnEntityForProduct(product))
if (CanSpawnEntityForProduct(product, productAssetTypes))
{
SpawnEntityAtPoint(product, viewportDragContext, spawnedEntities, spawnTicket);
}

@ -128,6 +128,7 @@ ly_add_target(
Legacy::EditorCore
RUNTIME_DEPENDENCIES
Gem::AtomViewportDisplayInfo
Legacy::EditorCommon
)
ly_add_source_properties(
SOURCES CryEdit.cpp

@ -208,22 +208,9 @@ WelcomeScreenDialog QLabel
margin: 0;
}
WelcomeScreenDialog QLabel#titleLabel
WelcomeScreenDialog QLabel#currentProjectLabel
{
font-size: 22px;
line-height: 32px;
}
WelcomeScreenDialog QLabel#bodyLabel
{
font-size: 14px;
line-height: 20px;
}
WelcomeScreenDialog QLabel[fontStyle="sectionTitle"], QLabel#titleLabel[fontStyle="sectionTitle"], QLabel#documentationLink
{
font-size: 16px;
line-height: 24px;
margin-top: 10px;
}
WelcomeScreenDialog QPushButton
@ -232,36 +219,20 @@ WelcomeScreenDialog QPushButton
line-height: 16px;
}
WelcomeScreenDialog QFrame#viewContainer
{
background-color: transparent;
}
WelcomeScreenDialog QFrame#viewContainer[articleStyle="pinned"]
{
background: rgba(180,139,255,5%);
border: 1px solid #B48BFF;
box-shadow: 0 0 4px 0 rgba(0,0,0,50%);
}
WelcomeScreenDialog QWidget#articleViewContainerRoot
{
background: #111111;
background: #444444;
}
WelcomeScreenDialog QScrollArea#previewArea
WelcomeScreenDialog QWidget#levelViewFTUEContainer
{
background-color: transparent;
background: #282828;
}
WelcomeScreenDialog QWidget#articleViewContents
{
background-color: transparent;
}
WelcomeScreenDialog QFrame#imageFrame
{
background-color: transparent;
QTableWidget#recentLevelTable::item {
background-color: rgb(64,64,64);
margin-bottom: 4px;
margin-top: 4px;
}
/* Particle Editor */

@ -45,6 +45,7 @@
#include <AzCore/std/algorithm.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include "ui_ViewportTitleDlg.h"
@ -57,13 +58,16 @@ inline namespace Helpers
{
void ToggleHelpers()
{
GetIEditor()->GetDisplaySettings()->DisplayHelpers(!GetIEditor()->GetDisplaySettings()->IsDisplayHelpers());
const bool newValue = !GetIEditor()->GetDisplaySettings()->IsDisplayHelpers();
GetIEditor()->GetDisplaySettings()->DisplayHelpers(newValue);
GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate);
if (GetIEditor()->GetDisplaySettings()->IsDisplayHelpers() == false)
if (newValue == false)
{
GetIEditor()->GetObjectManager()->SendEvent(EVENT_HIDE_HELPER);
}
AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Broadcast(
&AzToolsFramework::ViewportInteraction::ViewportSettingNotifications::OnDrawHelpersChanged, newValue);
}
bool IsHelpersShown()
@ -126,6 +130,7 @@ CViewportTitleDlg::CViewportTitleDlg(QWidget* pParent)
SetupCameraDropdownMenu();
SetupResolutionDropdownMenu();
SetupViewportInformationMenu();
SetupHelpersButton();
SetupOverflowMenu();
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, gSettings.bMuteAudio ? m_oMuteAudioRequest : m_oUnmuteAudioRequest);
@ -207,15 +212,16 @@ void CViewportTitleDlg::SetupViewportInformationMenu()
}
void CViewportTitleDlg::SetupHelpersButton()
{
connect(m_ui->m_helpers, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleHelpers);
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown());
}
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);
@ -329,7 +335,7 @@ void CViewportTitleDlg::OnMaximize()
void CViewportTitleDlg::OnToggleHelpers()
{
Helpers::ToggleHelpers();
m_debugHelpersAction->setChecked(Helpers::IsHelpersShown());
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown());
}
void CViewportTitleDlg::SetNoViewportInfo()
@ -755,7 +761,7 @@ void CViewportTitleDlg::OnEditorNotifyEvent(EEditorNotifyEvent event)
switch (event)
{
case eNotify_OnDisplayRenderUpdate:
m_debugHelpersAction->setChecked(Helpers::IsHelpersShown());
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown());
break;
case eNotify_OnBeginGameMode:
case eNotify_OnEndGameMode:

@ -102,6 +102,7 @@ protected:
void SetupResolutionDropdownMenu();
void SetupViewportInformationMenu();
void SetupOverflowMenu();
void SetupHelpersButton();
QString m_title;
@ -172,7 +173,6 @@ protected:
QAction* m_normalInformationAction = nullptr;
QAction* m_fullInformationAction = nullptr;
QAction* m_compactInformationAction = nullptr;
QAction* m_debugHelpersAction = nullptr;
QAction* m_audioMuteAction = nullptr;
QAction* m_enableVRAction = nullptr;
QAction* m_enableGridSnappingAction = nullptr;

@ -81,6 +81,18 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_helpers">
<property name="icon">
<iconset>
<normaloff>:/Menu/helpers.svg</normaloff>:/Menu/helpers.svg
</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="m_resolutionMenu">
<property name="icon">
@ -94,7 +106,7 @@
<widget class="QToolButton" name="m_overflowBtn">
<property name="icon">
<iconset>
<normaloff>:/stylesheet/img/UI20/menu-centered.svg</normaloff>:/stylesheet/img/UI20/menu-centered.svg
<normaloff>:/Menu/menu.svg</normaloff>:/Menu/menu.svg
</iconset>
</property>
</widget>

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:263e95489560dac6e5944ef3caba13e598f83ddead324b943ad7735ba015e1a9
size 70727

@ -15,7 +15,8 @@
#include "WelcomeScreenDialog.h"
// Qt
#include <QStringListModel>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QToolTip>
#include <QMenu>
#include <QDesktopServices>
@ -24,6 +25,7 @@
#include <QScreen>
#include <QDesktopWidget>
#include <QTimer>
#include <QDateTime>
#include <AzCore/Utils/Utils.h>
@ -74,65 +76,39 @@ static int GetSmallestScreenHeight()
WelcomeScreenDialog::WelcomeScreenDialog(QWidget* pParent)
: QDialog(new WindowDecorationWrapper(WindowDecorationWrapper::OptionAutoAttach | WindowDecorationWrapper::OptionAutoTitleBarButtons, pParent), Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::WindowTitleHint)
, ui(new Ui::WelcomeScreenDialog)
, m_pRecentListModel(new QStringListModel(this))
, m_pRecentList(nullptr)
{
ui->setupUi(this);
// Make our welcome screen checkboxes appear as toggle switches
AzQtComponents::CheckBox::applyToggleSwitchStyle(ui->autoLoadLevel);
AzQtComponents::CheckBox::applyToggleSwitchStyle(ui->showOnStartup);
ui->recentLevelTable->setColumnCount(3);
ui->recentLevelTable->setMouseTracking(true);
ui->recentLevelTable->setContextMenuPolicy(Qt::CustomContextMenu);
ui->recentLevelTable->horizontalHeader()->hide();
ui->recentLevelTable->verticalHeader()->hide();
ui->recentLevelTable->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->recentLevelTable->setSelectionMode(QAbstractItemView::SingleSelection);
ui->recentLevelTable->setIconSize(QSize(20, 20));
installEventFilter(this);
ui->autoLoadLevel->setChecked(gSettings.bAutoloadLastLevelAtStartup);
ui->showOnStartup->setChecked(!gSettings.bShowDashboardAtStartup);
ui->recentLevelList->setModel(m_pRecentListModel);
ui->recentLevelList->setMouseTracking(true);
ui->recentLevelList->setContextMenuPolicy(Qt::CustomContextMenu);
auto currentProjectButtonMenu = new QMenu();
ui->currentProjectButton->setMenu(currentProjectButtonMenu);
auto projectName = AZ::Utils::GetProjectName();
ui->currentProjectButton->setText(projectName.c_str());
ui->currentProjectButton->adjustSize();
ui->currentProjectButton->setMinimumWidth(ui->currentProjectButton->width() + 40);
ui->currentProjectName->setText(projectName.c_str());
ui->documentationLink->setCursor(Qt::PointingHandCursor);
ui->documentationLink->installEventFilter(this);
ui->newLevelButton->setDefault(true);
connect(ui->recentLevelList, &QWidget::customContextMenuRequested, this, &WelcomeScreenDialog::OnShowContextMenu);
// Hide these buttons until the new functionality is added
ui->gridButton->hide();
ui->objectListButton->hide();
ui->switchProjectButton->hide();
connect(ui->recentLevelList, &QListView::entered, this, &WelcomeScreenDialog::OnShowToolTip);
connect(ui->recentLevelList, &QListView::clicked, this, &WelcomeScreenDialog::OnRecentLevelListItemClicked);
connect(ui->recentLevelTable, &QWidget::customContextMenuRequested, this, &WelcomeScreenDialog::OnShowContextMenu);
connect(ui->recentLevelTable, &QTableWidget::entered, this, &WelcomeScreenDialog::OnShowToolTip);
connect(ui->recentLevelTable, &QTableWidget::clicked, this, &WelcomeScreenDialog::OnRecentLevelTableItemClicked);
connect(ui->newLevelButton, &QPushButton::clicked, this, &WelcomeScreenDialog::OnNewLevelBtnClicked);
connect(ui->levelFileLabel, &QLabel::linkActivated, this, &WelcomeScreenDialog::OnNewLevelLabelClicked);
connect(ui->openLevelButton, &QPushButton::clicked, this, &WelcomeScreenDialog::OnOpenLevelBtnClicked);
connect(ui->newSliceButton, &QPushButton::clicked, this, &WelcomeScreenDialog::OnNewSliceBtnClicked);
connect(ui->openSliceButton, &QPushButton::clicked, this, &WelcomeScreenDialog::OnOpenSliceBtnClicked);
connect(ui->documentationButton, &QPushButton::clicked, this, &WelcomeScreenDialog::OnDocumentationBtnClicked);
connect(ui->showOnStartup, &QCheckBox::clicked, this, &WelcomeScreenDialog::OnShowOnStartupBtnClicked);
connect(ui->autoLoadLevel, &QCheckBox::clicked, this, &WelcomeScreenDialog::OnAutoLoadLevelBtnClicked);
m_manifest = new News::ResourceManifest(
std::bind(&WelcomeScreenDialog::SyncSuccess, this),
std::bind(&WelcomeScreenDialog::SyncFail, this, std::placeholders::_1),
std::bind(&WelcomeScreenDialog::SyncUpdate, this, std::placeholders::_1, std::placeholders::_2));
m_articleViewContainer = new News::ArticleViewContainer(this, *m_manifest);
connect(m_articleViewContainer, &News::ArticleViewContainer::scrolled,
this, &WelcomeScreenDialog::previewAreaScrolled);
ui->articleViewContainerRoot->layout()->addWidget(m_articleViewContainer);
m_manifest->Sync();
#ifndef ENABLE_SLICE_EDITOR
ui->newSliceButton->hide();
ui->openSliceButton->hide();
#endif
// Adjust the height, if need be
// Do it in the constructor so that the WindowDecoratorWrapper handles it correctly
int smallestHeight = GetSmallestScreenHeight();
@ -153,16 +129,10 @@ WelcomeScreenDialog::WelcomeScreenDialog(QWidget* pParent)
WelcomeScreenDialog::~WelcomeScreenDialog()
{
delete ui;
delete m_manifest;
}
void WelcomeScreenDialog::done(int result)
{
if (m_waitingOnAsync)
{
m_manifest->Abort();
}
QDialog::done(result);
}
@ -173,13 +143,11 @@ const QString& WelcomeScreenDialog::GetLevelPath()
bool WelcomeScreenDialog::eventFilter(QObject *watched, QEvent *event)
{
if (watched == ui->documentationLink)
if (event->type() == QEvent::Show)
{
if (event->type() == QEvent::MouseButtonRelease)
{
OnDocumentationBtnClicked(false);
return true;
}
ui->recentLevelTable->horizontalHeader()->resizeSection(0, ui->nameLabel->width());
ui->recentLevelTable->horizontalHeader()->resizeSection(1, ui->modifiedLabel->width());
ui->recentLevelTable->horizontalHeader()->resizeSection(2, ui->typeLabel->width());
}
return QDialog::eventFilter(watched, event);
@ -207,7 +175,9 @@ void WelcomeScreenDialog::SetRecentFileList(RecentFileList* pList)
int nCurDir = sCurDir.length();
int recentListSize = pList->GetSize();
for (int i = 0; i < recentListSize; ++i)
int currentRow = 0;
ui->recentLevelTable->setRowCount(recentListSize);
for (int i = 0; i < recentListSize; ++i)
{
const QString& recentFile = pList->m_arrNames[i];
if (recentFile.endsWith(m_levelExtension))
@ -218,7 +188,7 @@ void WelcomeScreenDialog::SetRecentFileList(RecentFileList* pList)
if (sCurEntryDir.compare(sCurDir, Qt::CaseInsensitive) == 0)
{
QString fullPath = recentFile;
QString name = Path::GetFileName(fullPath);
const QString name = Path::GetFile(fullPath);
Path::ConvertSlashToBackSlash(fullPath);
fullPath = Path::ToUnixPath(fullPath.toLower());
@ -226,18 +196,34 @@ void WelcomeScreenDialog::SetRecentFileList(RecentFileList* pList)
if (fullPath.contains(gamePath))
{
m_pRecentListModel->setStringList(m_pRecentListModel->stringList() << QString(name));
if (gSettings.prefabSystem)
{
QIcon icon;
icon.addFile(QString::fromUtf8(":/Level/level.svg"), QSize(), QIcon::Normal, QIcon::Off);
ui->recentLevelTable->setItem(currentRow, 0, new QTableWidgetItem(icon, name));
}
else
{
ui->recentLevelTable->setItem(currentRow, 0, new QTableWidgetItem(name));
}
QFileInfo file(recentFile);
QDateTime dateTime = file.lastModified();
QString date = QLocale::system().toString(dateTime.date(), QLocale::ShortFormat) + " " +
QLocale::system().toString(dateTime.time(), QLocale::LongFormat);
ui->recentLevelTable->setItem(currentRow, 1, new QTableWidgetItem(date));
ui->recentLevelTable->setItem(currentRow++, 2, new QTableWidgetItem(tr("Level")));
m_levels.push_back(std::make_pair(name, recentFile));
}
}
}
}
}
ui->recentLevelTable->setRowCount(currentRow);
ui->recentLevelTable->setMinimumHeight(currentRow * ui->recentLevelTable->verticalHeader()->defaultSectionSize());
ui->recentLevelTable->setMaximumHeight(currentRow * ui->recentLevelTable->verticalHeader()->defaultSectionSize());
ui->levelFileLabel->setVisible(currentRow ? false : true);
ui->recentLevelList->setCurrentIndex(QModelIndex());
int rowSize = ui->recentLevelList->sizeHintForRow(0) + ui->recentLevelList->spacing() * 2;
ui->recentLevelList->setMinimumHeight(m_pRecentListModel->rowCount() * rowSize);
ui->recentLevelList->setMaximumHeight(m_pRecentListModel->rowCount() * rowSize);
ui->recentLevelTable->setCurrentIndex(QModelIndex());
}
@ -245,7 +231,7 @@ void WelcomeScreenDialog::RemoveLevelEntry(int index)
{
TNamePathPair levelPath = m_levels[index];
m_pRecentListModel->removeRow(index);
ui->recentLevelTable->removeRow(index);
m_levels.erase(m_levels.begin() + index);
@ -284,21 +270,18 @@ void WelcomeScreenDialog::OnShowToolTip(const QModelIndex& index)
{
const QString& fullPath = m_levels[index.row()].second;
//TEMPORARY:Begin This can be put back once the main window is in Qt
//QRect itemRect = ui->recentLevelList->visualRect(index);
QToolTip::showText(QCursor::pos(), QString("Open level: %1").arg(fullPath) /*, ui->recentLevelList, itemRect*/);
//TEMPORARY:END
QToolTip::showText(QCursor::pos(), QString("Open level: %1").arg(fullPath));
}
void WelcomeScreenDialog::OnShowContextMenu(const QPoint& pos)
{
QModelIndex index = ui->recentLevelList->indexAt(pos);
QModelIndex index = ui->recentLevelTable->indexAt(pos);
if (index.isValid())
{
QString level = m_pRecentListModel->data(index, 0).toString();
QString level = ui->recentLevelTable->itemAt(pos)->text();
QPoint globalPos = ui->recentLevelList->viewport()->mapToGlobal(pos);
QPoint globalPos = ui->recentLevelTable->viewport()->mapToGlobal(pos);
QMenu contextMenu;
contextMenu.addAction(QString("Remove " + level + " from recent list"));
@ -310,13 +293,16 @@ void WelcomeScreenDialog::OnShowContextMenu(const QPoint& pos)
}
}
void WelcomeScreenDialog::OnNewLevelBtnClicked([[maybe_unused]] bool checked)
{
m_levelPath = "new";
accept();
}
void WelcomeScreenDialog::OnNewLevelLabelClicked([[maybe_unused]] const QString& path)
{
OnNewLevelBtnClicked(true);
}
void WelcomeScreenDialog::OnOpenLevelBtnClicked([[maybe_unused]] bool checked)
{
@ -329,27 +315,7 @@ void WelcomeScreenDialog::OnOpenLevelBtnClicked([[maybe_unused]] bool checked)
}
}
void WelcomeScreenDialog::OnNewSliceBtnClicked([[maybe_unused]] bool checked)
{
m_levelPath = "new slice";
accept();
}
void WelcomeScreenDialog::OnOpenSliceBtnClicked(bool)
{
QString fileName = QFileDialog::getOpenFileName(MainWindow::instance(),
tr("Open Slice"),
Path::GetEditingGameDataFolder().c_str(),
tr("Slice (*.slice)"));
if (!fileName.isEmpty())
{
m_levelPath = fileName;
accept();
}
}
void WelcomeScreenDialog::OnRecentLevelListItemClicked(const QModelIndex& modelIndex)
void WelcomeScreenDialog::OnRecentLevelTableItemClicked(const QModelIndex& modelIndex)
{
int index = modelIndex.row();
@ -365,45 +331,6 @@ void WelcomeScreenDialog::OnCloseBtnClicked([[maybe_unused]] bool checked)
accept();
}
void WelcomeScreenDialog::OnAutoLoadLevelBtnClicked(bool checked)
{
gSettings.bAutoloadLastLevelAtStartup = checked;
gSettings.Save();
}
void WelcomeScreenDialog::OnShowOnStartupBtnClicked(bool checked)
{
gSettings.bShowDashboardAtStartup = !checked;
gSettings.Save();
if (gSettings.bShowDashboardAtStartup == false)
{
QMessageBox msgBox(AzToolsFramework::GetActiveWindow());
msgBox.setWindowTitle(QObject::tr("Skip the Welcome dialog on startup"));
msgBox.setText(QObject::tr("You may re-enable the Welcome dialog at any time by going to Edit > Editor Settings > Global Preferences in the menu bar."));
msgBox.exec();
}
}
void WelcomeScreenDialog::OnDocumentationBtnClicked([[maybe_unused]] bool checked)
{
QString webLink = tr("https://aws.amazon.com/lumberyard/support/");
QDesktopServices::openUrl(QUrl(webLink));
}
void WelcomeScreenDialog::SyncFail([[maybe_unused]] News::ErrorCode error)
{
m_articleViewContainer->AddErrorMessage();
m_waitingOnAsync = false;
}
void WelcomeScreenDialog::SyncSuccess()
{
m_articleViewContainer->PopulateArticles();
m_waitingOnAsync = false;
}
void WelcomeScreenDialog::previewAreaScrolled()
{
//this should only be reported once per session

@ -52,13 +52,9 @@ private:
Ui::WelcomeScreenDialog* ui;
QString m_levelPath;
QStringListModel* m_pRecentListModel;
TNameFullPathArray m_levels;
RecentFileList* m_pRecentList;
News::ResourceManifest* m_manifest = nullptr;
News::ArticleViewContainer* m_articleViewContainer = nullptr;
const char* m_levelExtension = nullptr;
bool m_waitingOnAsync = true;
bool m_messageScrollReported = false;
void RemoveLevelEntry(int index);
@ -66,19 +62,11 @@ private:
void OnShowToolTip(const QModelIndex& index);
void OnShowContextMenu(const QPoint& point);
void OnNewLevelBtnClicked(bool checked);
void OnNewLevelLabelClicked(const QString& checked);
void OnOpenLevelBtnClicked(bool checked);
void OnNewSliceBtnClicked(bool checked);
void OnOpenSliceBtnClicked(bool checked);
void OnRecentLevelListItemClicked(const QModelIndex& index);
void OnGettingStartedBtnClicked(bool checked);
void OnTutorialsBtnClicked(bool checked);
void OnDocumentationBtnClicked(bool checked);
void OnForumsBtnClicked(bool checked);
void OnAutoLoadLevelBtnClicked(bool checked);
void OnShowOnStartupBtnClicked(bool checked);
void OnRecentLevelTableItemClicked(const QModelIndex& index);
void OnCloseBtnClicked(bool checked);
void SyncUpdate(const QString& /* message */, News::LogType /* logType */) {}
void SyncFail(News::ErrorCode error);
void SyncSuccess();

@ -1,5 +1,5 @@
<RCC>
<qresource prefix="WelcomeScreenDialog">
<file>WelcomeScreenDialogHeader.png</file>
<file>DefaultActiveProject.png</file>
</qresource>
</RCC>

@ -2,12 +2,15 @@
<ui version="4.0">
<class>WelcomeScreenDialog</class>
<widget class="QWidget" name="WelcomeScreenDialog">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
<width>945</width>
<height>639</height>
</rect>
</property>
<property name="sizePolicy">
@ -18,21 +21,21 @@
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
<width>945</width>
<height>639</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>800</width>
<height>16777215</height>
<width>945</width>
<height>639</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="windowTitle">
<string>Welcome to Open 3D Engine</string>
<string>Welcome to O3DE</string>
</property>
<property name="styleSheet">
<string notr="true"/>
@ -53,100 +56,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="projectViewContainer" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>36</height>
</size>
</property>
<layout class="QHBoxLayout" name="projectViewContainer_layout" stretch="0,0,1,0,0">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="currentProjectLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Current project:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="currentProjectButton">
<property name="text">
<string>Current Project Name</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">color: &quot;black&quot;</string>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="bodyContainer">
<property name="spacing">
@ -165,20 +74,26 @@
<number>0</number>
</property>
<item>
<widget class="QWidget" name="levelViewFTUEContainer" native="true">
<widget class="QWidget" name="articleViewContainerRoot" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<width>183</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<width>183</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
<layout class="QVBoxLayout" name="newsContainerLayout">
<property name="spacing">
<number>0</number>
</property>
@ -191,6 +106,143 @@
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>15</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="currentProjectLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Active project</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="activeProjectIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>126</width>
<height>167</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>126</width>
<height>167</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="WelcomeScreenDialog.qrc">:/WelcomeScreenDialog/DefaultActiveProject.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="currentProjectName">
<property name="text">
<string>MyGame</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>15</number>
</property>
<property name="rightMargin">
<number>15</number>
</property>
<item>
<widget class="QPushButton" name="switchProjectButton">
<property name="text">
<string>Switch project...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="levelViewFTUEContainer" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>762</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>762</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>20</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
@ -227,7 +279,7 @@
</size>
</property>
<property name="text">
<string>Open or create a level</string>
<string>Recent Files</string>
</property>
<property name="indent">
<number>-1</number>
@ -255,16 +307,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListView" name="recentLevelList">
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="spacing">
<number>4</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -310,8 +352,26 @@
</property>
<item>
<widget class="QPushButton" name="newLevelButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>156</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>156</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>New level...</string>
<string>Create new...</string>
</property>
</widget>
</item>
@ -333,8 +393,67 @@
</item>
<item>
<widget class="QPushButton" name="openLevelButton">
<property name="minimumSize">
<size>
<width>156</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>156</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Open...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="objectListButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../Framework/AzQtComponents/AzQtComponents/Components/resources.qrc">
<normaloff>:/stylesheet/img/UI20/toolbar/Object_list.svg</normaloff>:/stylesheet/img/UI20/toolbar/Object_list.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="gridButton">
<property name="text">
<string>Open level...</string>
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../Framework/AzQtComponents/AzQtComponents/Components/resources.qrc">
<normaloff>:/stylesheet/img/UI20/toolbar/Grid.svg</normaloff>:/stylesheet/img/UI20/toolbar/Grid.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
@ -358,65 +477,130 @@
</spacer>
</item>
<item>
<widget class="QWidget" name="horizontalWidget_2" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="2,2,1">
<property name="leftMargin">
<number>6</number>
</property>
<layout class="QHBoxLayout" name="sliceControlContainer">
<property name="spacing">
<number>0</number>
</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="QPushButton" name="newSliceButton">
<property name="text">
<string>New slice...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>24</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="openSliceButton">
<property name="text">
<string>Open slice...</string>
</property>
</widget>
</item>
</layout>
</widget>
<item>
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="modifiedLabel">
<property name="text">
<string>Last modified</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="typeLabel">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7" stretch="0,0,0">
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>16</number>
</property>
<property name="rightMargin">
<number>16</number>
</property>
<item>
<widget class="QLabel" name="levelFileLabel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>No level file created yet for this project. &lt;a href=&quot;#&quot;&gt;Create one&lt;/a&gt; now.</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QTableWidget" name="recentLevelTable">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="columnCount">
<number>3</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>1</number>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>48</number>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<column/>
<column/>
<column/>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_4">
<property name="maximumSize">
@ -439,205 +623,16 @@
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QWidget" name="documentationLinkContainer" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>48</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>48</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>10</number>
</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="QToolButton" name="documentationButton">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string>info</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/stylesheet/img/UI20/Info.svg</normaloff>:/stylesheet/img/UI20/Info.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="documentationLink">
<property name="text">
<string>Documentation and tutorials</string>
</property>
<property name="class" stdset="0">
<string>link</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="maximumSize">
<size>
<width>1</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">color: &quot;black&quot;</string>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="articleViewContainerRoot" native="true">
<property name="minimumSize">
<size>
<width>480</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="newsContainerLayout">
<property name="spacing">
<number>0</number>
</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>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">color: &quot;black&quot;</string>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<widget class="QWidget" name="optionsViewContainer" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>36</height>
</size>
</property>
<layout class="QHBoxLayout" name="optionsViewContainer_layout">
<property name="spacing">
<number>30</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>16</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="autoLoadLevel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Auto-load last opened level on startup</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showOnStartup">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Skip this dialog on startup</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="WelcomeScreenDialog.qrc"/>
<include location="../../../Framework/AzQtComponents/AzQtComponents/Components/resources.qrc"/>
</resources>
<connections/>
</ui>

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:53b846352880d940621b14b1ea9514e0a4c95aa6ead4d00234a98684c061c04f
size 29505

@ -255,7 +255,6 @@ namespace AZ
{
return AZStd::make_pair(animation, anim);
}
Events::ProcessingResult AssImpAnimationImporter::ImportAnimation(AssImpSceneNodeAppendedContext& context)
{
AZ_TraceContext("Importer", "Animation");
@ -447,7 +446,22 @@ namespace AZ
return combinedAnimationResult.GetResult();
}
decltype(boneAnimations) parentFillerAnimations;
AZStd::unordered_set<AZStd::string> boneList;
for (int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
{
aiMesh* mesh = scene->mMeshes[meshIndex];
for (int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
{
aiBone* bone = mesh->mBones[boneIndex];
boneList.insert(bone->mName.C_Str());
}
}
decltype(boneAnimations) fillerAnimations;
// Go through all the animations and make sure we create animations for bones who's parents don't have an animation
for (auto&& anim : boneAnimations)
@ -459,8 +473,8 @@ namespace AZ
{
if (!IsPivotNode(parent->mName))
{
if (boneAnimations.find(parent->mName.C_Str()) == boneAnimations.end() &&
parentFillerAnimations.find(parent->mName.C_Str()) == parentFillerAnimations.end())
if (!boneAnimations.contains(parent->mName.C_Str()) &&
!fillerAnimations.contains(parent->mName.C_Str()))
{
// Create 1 key for each type that just copies the current transform
ConsolidatedNodeAnim emptyAnimation;
@ -472,7 +486,7 @@ namespace AZ
globalTransform.Decompose(scale, rotation, position);
emptyAnimation.mNumRotationKeys = emptyAnimation.mNumPositionKeys = emptyAnimation.mNumScalingKeys = 1;
emptyAnimation.m_ownedPositionKeys.emplace_back(0, position);
emptyAnimation.mPositionKeys = emptyAnimation.m_ownedPositionKeys.data();
@ -481,9 +495,9 @@ namespace AZ
emptyAnimation.m_ownedScalingKeys.emplace_back(0, scale);
emptyAnimation.mScalingKeys = emptyAnimation.m_ownedScalingKeys.data();
parentFillerAnimations.insert(
AZStd::make_pair(parent->mName.C_Str(), AZStd::make_pair(anim.second.first, AZStd::move(emptyAnimation))));
fillerAnimations.insert(AZStd::make_pair(
parent->mName.C_Str(), AZStd::make_pair(anim.second.first, AZStd::move(emptyAnimation))));
}
}
@ -491,7 +505,7 @@ namespace AZ
}
}
boneAnimations.insert(AZStd::make_move_iterator(parentFillerAnimations.begin()), AZStd::make_move_iterator(parentFillerAnimations.end()));
boneAnimations.insert(AZStd::make_move_iterator(fillerAnimations.begin()), AZStd::make_move_iterator(fillerAnimations.end()));
auto animItr = boneAnimations.equal_range(currentNode->mName.C_Str());

@ -98,6 +98,20 @@ namespace AZ
}
}
aiMatrix4x4 CalculateWorldTransform(const aiNode* currentNode)
{
aiMatrix4x4 transform = {};
const aiNode* iteratingNode = currentNode;
while (iteratingNode)
{
transform = iteratingNode->mTransformation * transform;
iteratingNode = iteratingNode->mParent;
}
return transform;
}
Events::ProcessingResult AssImpBoneImporter::ImportBone(AssImpNodeEncounteredContext& context)
{
AZ_TraceContext("Importer", "Bone");
@ -111,12 +125,7 @@ namespace AZ
}
bool isBone = false;
if (NodeParentIsOfType(context.m_scene.GetGraph(), context.m_currentGraphPosition, DataTypes::IBoneData::TYPEINFO_Uuid()))
{
isBone = true;
}
else
{
AZStd::unordered_map<AZStd::string, const aiNode*> mainBoneList;
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
@ -170,15 +179,8 @@ namespace AZ
{
createdBoneData = AZStd::make_shared<SceneData::GraphData::RootBoneData>();
}
aiMatrix4x4 transform = currentNode->mTransformation;
const aiNode* parent = currentNode->mParent;
while (parent)
{
transform = parent->mTransformation * transform;
parent = parent->mParent;
}
aiMatrix4x4 transform = CalculateWorldTransform(currentNode);
SceneAPI::DataTypes::MatrixType globalTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(transform);

@ -31,7 +31,7 @@ namespace AZ
~AssImpBoneImporter() override = default;
static void Reflect(ReflectContext* context);
Events::ProcessingResult ImportBone(AssImpNodeEncounteredContext& context);
};
} // namespace FbxSceneBuilder

@ -46,8 +46,9 @@ namespace AZ
serializeContext->Class<AssImpTransformImporter, SceneCore::LoadingComponent>()->Version(1);
}
}
void GetAllBones(const aiScene* scene, AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
void GetAllBones(
const aiScene* scene, AZStd::unordered_multimap<AZStd::string, const aiBone*>& boneLookup)
{
for (unsigned meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
{
@ -57,7 +58,7 @@ namespace AZ
{
const aiBone* bone = mesh->mBones[boneIndex];
boneLookup[bone->mName.C_Str()] = bone;
boneLookup.emplace(bone->mName.C_Str(), bone);
}
}
}
@ -73,41 +74,53 @@ namespace AZ
return Events::ProcessingResult::Ignored;
}
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
AZStd::unordered_multimap<AZStd::string, const aiBone*> boneLookup;
GetAllBones(scene, boneLookup);
auto boneIterator = boneLookup.find(currentNode->mName.C_Str());
const bool isBone = boneIterator != boneLookup.end();
aiMatrix4x4 combinedTransform;
DataTypes::MatrixType localTransform;
if (isBone)
{
auto parentNode = currentNode->mParent;
aiMatrix4x4 offsetMatrix = boneIterator->second->mOffsetMatrix;
aiMatrix4x4 parentOffset {};
AZStd::vector<DataTypes::MatrixType> offsets, inverseOffsets;
auto iteratingNode = currentNode;
auto parentBoneIterator = boneLookup.find(parentNode->mName.C_Str());
if (parentNode && parentBoneIterator != boneLookup.end())
while (iteratingNode && boneLookup.count(iteratingNode->mName.C_Str()))
{
const auto& parentBone = parentBoneIterator->second;
AZStd::string name = iteratingNode->mName.C_Str();
parentOffset = parentBone->mOffsetMatrix;
}
auto range = boneLookup.equal_range(name);
auto inverseOffset = offsetMatrix;
inverseOffset.Inverse();
if (range.first != range.second)
{
// There can be multiple offsetMatrices for a given bone, we're only interested in grabbing the first one
auto boneFirstOffsetMatrix = range.first->second->mOffsetMatrix;
auto azMat = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(boneFirstOffsetMatrix);
offsets.push_back(azMat);
inverseOffsets.push_back(azMat.GetInverseFull());
}
combinedTransform = parentOffset * inverseOffset;
iteratingNode = iteratingNode->mParent;
}
localTransform =
offsets.at(AZ::GetMin(offsets.size()-1, static_cast<decltype(offsets.size())>(1))) // parent bone offset, or if there is no parent, then current node offset
* inverseOffsets.at(inverseOffsets.size() - 1) // Inverse of root bone offset
* offsets.at(offsets.size() - 1) // Root bone offset
* inverseOffsets.at(0); // Inverse of current node offset
}
else
{
combinedTransform = GetConcatenatedLocalTransform(currentNode);
localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(GetConcatenatedLocalTransform(currentNode));
}
DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(combinedTransform);
// Don't bother adding a node with the identity matrix
if (localTransform == DataTypes::MatrixType::Identity())
{
return Events::ProcessingResult::Ignored;
}
context.m_sourceSceneSystem.SwapTransformForUpAxis(localTransform);
context.m_sourceSceneSystem.ConvertUnit(localTransform);

@ -1765,16 +1765,8 @@ namespace LUAEditor
return false;
}
//name has the full path in it, we need to convert it to an asset name
AZStd::string projectRoot, databaseRoot, databasePath, databaseFile, fileExtension;
if (!AzFramework::StringFunc::AssetDatabasePath::Split(name.toUtf8().data(), &projectRoot, &databaseRoot, &databasePath, &databaseFile, &fileExtension))
{
AZ_Warning("LUAEditorMainWindow", false, AZStd::string::format("<span severity=\"err\">Path is invalid: '%s'</span>", name.toUtf8().data()).c_str());
return false;
}
AzFramework::StringFunc::Path::Split(name.toUtf8().data(), nullptr, &m_lastOpenFilePath);
AzFramework::StringFunc::AssetDatabasePath::Join(databasePath.c_str(), databaseFile.c_str(), newAssetName);
newAssetName = name.toUtf8().data();
return true;
}

@ -46,6 +46,7 @@ namespace AWSCore
void InitializeAWSDocActions();
void InitializeAWSGlobalDocsSubMenu();
void InitializeAWSFeatureGemActions();
void AddSpaceForIcon(QMenu* menu);
// AWSCoreEditorRequestBus interface implementation
void SetAWSClientAuthEnabled() override;

@ -35,6 +35,8 @@
namespace AWSCore
{
static constexpr int IconSize = 16;
AWSCoreEditorMenu::AWSCoreEditorMenu(const QString& text)
: QMenu(text)
, m_resourceMappingToolWatcher(nullptr)
@ -43,6 +45,7 @@ namespace AWSCore
InitializeResourceMappingToolAction();
this->addSeparator();
InitializeAWSFeatureGemActions();
AddSpaceForIcon(this);
AWSCoreEditorRequestBus::Handler::BusConnect();
}
@ -136,6 +139,8 @@ namespace AWSCore
globalDocsMenu->addAction(AddExternalLinkAction(AWSAndScriptCanvasActionText, AWSAndScriptCanvasUrl, ":/Notifications/link.svg"));
globalDocsMenu->addAction(AddExternalLinkAction(AWSAndComponentsActionText, AWSAndComponentsUrl, ":/Notifications/link.svg"));
globalDocsMenu->addAction(AddExternalLinkAction(CallAWSResourcesActionText, CallAWSResourcesUrl, ":/Notifications/link.svg"));
AddSpaceForIcon(globalDocsMenu);
}
void AWSCoreEditorMenu::InitializeAWSFeatureGemActions()
@ -170,6 +175,8 @@ namespace AWSCore
AWSClientAuthPlatformSpecificActionText, AWSClientAuthPlatformSpecificUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSClientAuthAPIReferenceActionText, AWSClientAuthAPIReferenceUrl, ":/Notifications/link.svg"));
AddSpaceForIcon(subMenu);
}
void AWSCoreEditorMenu::SetAWSMetricsEnabled()
@ -198,6 +205,7 @@ namespace AWSCore
QDesktopServices::openUrl(QUrl::fromLocalFile(configFilePath.c_str()));
});
subMenu->addAction(settingsAction);
AddSpaceForIcon(subMenu);
}
QMenu* AWSCoreEditorMenu::SetAWSFeatureSubMenu(const AZStd::string& menuText)
@ -209,6 +217,7 @@ namespace AWSCore
{
QMenu* subMenu = new QMenu(QObject::tr(menuText.c_str()));
subMenu->setIcon(QIcon(QString(":/Notifications/checkmark.svg")));
subMenu->setProperty("noHover", true);
this->insertMenu(*itr, subMenu);
this->removeAction(*itr);
return subMenu;
@ -216,4 +225,11 @@ namespace AWSCore
}
return nullptr;
}
void AWSCoreEditorMenu::AddSpaceForIcon(QMenu* menu)
{
QSize size = menu->sizeHint();
size.setWidth(size.width() + IconSize);
menu->setFixedSize(size);
}
} // namespace AWSCore

@ -1015,7 +1015,7 @@
{
"id": "pdo",
"displayName": "Pixel Depth Offset",
"description": "Whether to enable the pixel depth offset feature.",
"description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.",
"type": "Bool",
"defaultValue": false,
"connection": {

@ -417,7 +417,7 @@
{
"id": "pdo",
"displayName": "Pixel Depth Offset",
"description": "Whether to enable the pixel depth offset feature.",
"description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.",
"type": "Bool",
"defaultValue": false,
"connection": {

@ -956,7 +956,7 @@
{
"id": "pdo",
"displayName": "Pixel Depth Offset",
"description": "Whether to enable the pixel depth offset feature.",
"description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.",
"type": "Bool",
"defaultValue": false,
"connection": {

@ -21,7 +21,7 @@
"SlotType": "Output",
"ScopeAttachmentUsage": "RenderTarget",
"LoadStoreAction": {
"LoadAction": "Load"
"LoadAction": "DontCare"
}
}
],

@ -173,7 +173,7 @@ namespace AZ
{
if (inputPropertyValue.IsObject() && inputPropertyValue.HasMember("Value") && inputPropertyValue.HasMember("$type"))
{
// Requiring explicit type info to differentiate be=tween colors versus vectors and numeric types
// Requiring explicit type info to differentiate between colors versus vectors and numeric types
const AZ::Uuid baseTypeId = azrtti_typeid<T>();
AZ::Uuid typeId = AZ::Uuid::CreateNull();
result.Combine(LoadTypeId(typeId, inputPropertyValue, context, &baseTypeId));
@ -198,7 +198,7 @@ namespace AZ
{
outputPropertyValue.SetObject();
// Storing explicit type info to differentiate be=tween colors versus vectors and numeric types
// Storing explicit type info to differentiate between colors versus vectors and numeric types
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, azrtti_typeid<T>(), context));
outputPropertyValue.AddMember("$type", typeValue, context.GetJsonAllocator());

@ -35,7 +35,6 @@ namespace AZ
{
m_device = device;
m_srgLayout = srgLayout;
m_srgPool = srgPool;
m_constantBufferSize = srgLayout->GetConstantDataSize();
if (m_constantBufferSize)
@ -93,9 +92,6 @@ namespace AZ
//Attach the constant buffer
AttachConstantBuffer();
m_samplerCache = [[NSCache alloc]init];
[m_samplerCache setName:@"SamplerCache"];
}
}
}
@ -211,8 +207,8 @@ namespace AZ
}
else
{
RHI::Ptr<Memory> nullMtlBufferMemPtr = m_device->GetNullDescriptorManager().GetNullImage(shaderInputImage.m_type).GetMemory();
mtlTextures[imageArrayLen] = nullMtlBufferMemPtr->GetGpuAddress<id<MTLTexture>>();
RHI::Ptr<Memory> nullMtlImagePtr = m_device->GetNullDescriptorManager().GetNullImage(shaderInputImage.m_type).GetMemory();
mtlTextures[imageArrayLen] = nullMtlImagePtr->GetGpuAddress<id<MTLTexture>>();
}
imageArrayLen++;
}
@ -345,15 +341,20 @@ namespace AZ
m_device->GetArgumentBufferAllocator().DeAllocate(m_argumentBuffer);
}
#endif
m_argumentBuffer = {};
m_constantBuffer = {};
[m_samplerCache removeAllObjects];
[m_samplerCache release];
m_samplerCache = nil;
if(m_argumentBuffer.IsValid())
{
m_device->QueueForRelease(m_argumentBuffer);
}
if(m_constantBuffer.IsValid())
{
m_device->QueueForRelease(m_constantBuffer);
}
[m_argumentEncoder release];
m_argumentEncoder = nil;
Base::Shutdown();
}
@ -374,23 +375,22 @@ namespace AZ
id<MTLSamplerState> ArgumentBuffer::GetMtlSampler(MTLSamplerDescriptor* samplerDesc)
{
id<MTLSamplerState> mtlSamplerState = [m_samplerCache objectForKey:samplerDesc];
const NSCache* samplerCache = m_device->GetSamplerCache();
id<MTLSamplerState> mtlSamplerState = [samplerCache objectForKey:samplerDesc];
if(mtlSamplerState == nil)
{
mtlSamplerState = [m_device->GetMtlDevice() newSamplerStateWithDescriptor:samplerDesc];
[m_samplerCache setObject:mtlSamplerState forKey:samplerDesc];
[samplerCache setObject:mtlSamplerState forKey:samplerDesc];
}
return mtlSamplerState;
}
void ArgumentBuffer::AddUntrackedResourcesToEncoder(id<MTLCommandEncoder> commandEncoder, const ShaderResourceGroupVisibility& srgResourcesVisInfo) const
void ArgumentBuffer::CollectUntrackedResources(id<MTLCommandEncoder> commandEncoder,
const ShaderResourceGroupVisibility& srgResourcesVisInfo,
ComputeResourcesToMakeResidentMap& resourcesToMakeResidentCompute,
GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentGraphics) const
{
//Map to cache all the resources based on the usage as we can batch all the resources for a given usage
ComputeResourcesToMakeResidentMap resourcesToMakeResidentCompute;
//Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage
GraphicsResourcesToMakeResidentMap resourcesToMakeResidentGraphics;
//Cache the constant buffer associated with a srg
if (m_constantBufferSize)
{
@ -434,25 +434,6 @@ namespace AZ
}
}
}
//Call UseResource on all resources for Compute stage
for (const auto& key : resourcesToMakeResidentCompute)
{
AZStd::vector<id <MTLResource>> resourcesToProcessVec(key.second.begin(), key.second.end());
[static_cast<id<MTLComputeCommandEncoder>>(commandEncoder) useResources: &resourcesToProcessVec[0]
count: resourcesToProcessVec.size()
usage: key.first];
}
//Call UseResource on all resources for Vertex and Fragment stages
for (const auto& key : resourcesToMakeResidentGraphics)
{
AZStd::vector<id <MTLResource>> resourcesToProcessVec(key.second.begin(), key.second.end());
[static_cast<id<MTLRenderCommandEncoder>>(commandEncoder) useResources: &resourcesToProcessVec[0]
count: resourcesToProcessVec.size()
usage: key.first.first
stages: key.first.second];
}
}
void ArgumentBuffer::CollectResourcesForCompute(id<MTLCommandEncoder> encoder,

@ -97,7 +97,15 @@ namespace AZ
id<MTLBuffer> GetArgEncoderBuffer() const;
size_t GetOffset() const;
void AddUntrackedResourcesToEncoder(id<MTLCommandEncoder> commandEncoder, const ShaderResourceGroupVisibility& srgResourcesVisInfo) const;
//Map to cache all the resources based on the usage as we can batch all the resources for a given usage.
using ComputeResourcesToMakeResidentMap = AZStd::unordered_map<MTLResourceUsage, AZStd::unordered_set<id <MTLResource>>>;
//Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage.
using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map<AZStd::pair<MTLResourceUsage,MTLRenderStages>, AZStd::unordered_set<id <MTLResource>>>;
void CollectUntrackedResources(id<MTLCommandEncoder> commandEncoder,
const ShaderResourceGroupVisibility& srgResourcesVisInfo,
ComputeResourcesToMakeResidentMap& resourcesToMakeResidentCompute,
GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentGraphics) const;
void ClearResourceTracking();
@ -120,11 +128,7 @@ namespace AZ
ResourceBindingsMap m_resourceBindings;
static const int MaxEntriesInArgTable = 31;
//Map to cache all the resources based on the usage as we can batch all the resources for a given usage.
using ComputeResourcesToMakeResidentMap = AZStd::unordered_map<MTLResourceUsage, AZStd::unordered_set<id <MTLResource>>>;
//Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage.
using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map<AZStd::pair<MTLResourceUsage,MTLRenderStages>, AZStd::unordered_set<id <MTLResource>>>;
void CollectResourcesForCompute(id<MTLCommandEncoder> encoder,
const ResourceBindingsSet& resourceBindingData,
ComputeResourcesToMakeResidentMap& resourcesToMakeResidentMap) const;
@ -153,9 +157,6 @@ namespace AZ
MemoryView m_argumentBuffer;
MemoryView m_constantBuffer;
#endif
ShaderResourceGroupPool* m_srgPool = nullptr;
NSCache* m_samplerCache;
};
}
}

@ -40,7 +40,7 @@ namespace AZ
buffer->m_pendingResolves++;
uploadRequest.m_attachmentBuffer = buffer;
uploadRequest.m_byteOffset = buffer->GetMemoryView().GetOffset() + request.m_byteOffset;
uploadRequest.m_byteOffset = request.m_byteOffset;
uploadRequest.m_stagingBuffer = stagingBuffer;
return stagingBuffer->GetMemoryView().GetCpuAddress();
@ -51,6 +51,12 @@ namespace AZ
void BufferPoolResolver::Compile()
{
for (BufferUploadPacket& packet : m_uploadPackets)
{
Buffer* stagingBuffer = packet.m_stagingBuffer.get();
//Inform the GPU that the CPU has modified the staging buffer.
Platform::SynchronizeBufferOnCPU(stagingBuffer->GetMemoryView().GetGpuAddress<id<MTLBuffer>>(), stagingBuffer->GetMemoryView().GetOffset(), stagingBuffer->GetMemoryView().GetSize());
}
}
void BufferPoolResolver::Resolve(CommandList& commandList) const
@ -62,15 +68,12 @@ namespace AZ
Buffer* destBuffer = packet.m_attachmentBuffer;
AZ_Assert(stagingBuffer, "Staging Buffer is null.");
AZ_Assert(destBuffer, "Attachment Buffer is null.");
//Inform the GPU that the CPU has modified the staging buffer.
Platform::SynchronizeBufferOnCPU(stagingBuffer->GetMemoryView().GetGpuAddress<id<MTLBuffer>>(), stagingBuffer->GetMemoryView().GetOffset(), stagingBuffer->GetMemoryView().GetSize());
RHI::CopyBufferDescriptor copyDescriptor;
copyDescriptor.m_sourceBuffer = stagingBuffer;
copyDescriptor.m_sourceOffset = stagingBuffer->GetMemoryView().GetOffset();
copyDescriptor.m_destinationBuffer = destBuffer;
copyDescriptor.m_destinationOffset = static_cast<uint32_t>(packet.m_byteOffset);
copyDescriptor.m_destinationOffset = destBuffer->GetMemoryView().GetOffset() + static_cast<uint32_t>(packet.m_byteOffset);
copyDescriptor.m_size = stagingBuffer->GetMemoryView().GetSize();
commandList.Submit(RHI::CopyItem(copyDescriptor));

@ -85,6 +85,7 @@ namespace AZ
destinationOffset:descriptor.m_destinationOffset
size:descriptor.m_size];
Platform::SynchronizeBufferOnGPU(blitEncoder, destinationBuffer->GetMemoryView().GetGpuAddress<id<MTLBuffer>>());
break;
}
case RHI::CopyItemType::Image:
@ -114,6 +115,8 @@ namespace AZ
destinationSlice: descriptor.m_destinationSubresource.m_arraySlice
destinationLevel: descriptor.m_destinationSubresource.m_mipSlice
destinationOrigin: destinationOrigin];
Platform::SynchronizeTextureOnGPU(blitEncoder, destinationImage->GetMemoryView().GetGpuAddress<id<MTLTexture>>());
break;
}
case RHI::CopyItemType::BufferToImage:
@ -266,6 +269,11 @@ namespace AZ
mtlVertexArgBufferOffsets.fill(0);
mtlFragmentOrComputeArgBufferOffsets.fill(0);
//Map to cache all the resources based on the usage as we can batch all the resources for a given usage
ArgumentBuffer::ComputeResourcesToMakeResidentMap resourcesToMakeResidentCompute;
//Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage
ArgumentBuffer::GraphicsResourcesToMakeResidentMap resourcesToMakeResidentGraphics;
for (uint32_t slot = 0; slot < RHI::Limits::Pipeline::ShaderResourceGroupCountMax; ++slot)
{
const ShaderResourceGroup* shaderResourceGroup = bindings.m_srgsBySlot[slot];
@ -291,7 +299,6 @@ namespace AZ
//For graphics and compute shader stages, cache all the argument buffers, offsets and track the min/max indices
if(m_commandEncoderType == CommandEncoderType::Render)
{
id<MTLRenderCommandEncoder> renderEncoder = GetEncoder<id<MTLRenderCommandEncoder>>();
uint8_t numBitsSet = RHI::CountBitsSet(static_cast<uint64_t>(srgVisInfo));
if( numBitsSet > 1 || srgVisInfo == RHI::ShaderStageMask::Vertex)
{
@ -334,11 +341,11 @@ namespace AZ
//format compatible with the appropriate metal function.
if(m_commandEncoderType == CommandEncoderType::Render)
{
shaderResourceGroup->AddUntrackedResourcesToEncoder(m_encoder, srgResourcesVisInfo);
shaderResourceGroup->CollectUntrackedResources(m_encoder, srgResourcesVisInfo, resourcesToMakeResidentCompute, resourcesToMakeResidentGraphics);
}
else if(m_commandEncoderType == CommandEncoderType::Compute)
{
shaderResourceGroup->AddUntrackedResourcesToEncoder(m_encoder, srgResourcesVisInfo);
shaderResourceGroup->CollectUntrackedResources(m_encoder, srgResourcesVisInfo, resourcesToMakeResidentCompute, resourcesToMakeResidentGraphics);
}
}
}
@ -368,6 +375,32 @@ namespace AZ
mtlFragmentOrComputeArgBufferOffsets);
}
id<MTLRenderCommandEncoder> renderEncoder = GetEncoder<id<MTLRenderCommandEncoder>>();
id<MTLComputeCommandEncoder> computeEncoder = GetEncoder<id<MTLComputeCommandEncoder>>();
//Call UseResource on all resources for Compute stage
for (const auto& key : resourcesToMakeResidentCompute)
{
AZStd::vector<id <MTLResource>> resourcesToProcessVec(key.second.begin(), key.second.end());
[computeEncoder useResources: &resourcesToProcessVec[0]
count: resourcesToProcessVec.size()
usage: key.first];
}
//Call UseResource on all resources for Vertex and Fragment stages
for (const auto& key : resourcesToMakeResidentGraphics)
{
AZStd::vector<id <MTLResource>> resourcesToProcessVec(key.second.begin(), key.second.end());
[renderEncoder useResources: &resourcesToProcessVec[0]
count: resourcesToProcessVec.size()
usage: key.first.first
stages: key.first.second];
}
return true;
}

@ -83,7 +83,7 @@ namespace AZ
for (id<MTLHeap> residentHeap : *m_residentHeaps)
{
[renderEncoder useHeap : residentHeap
stages : MTLRenderStageFragment];
stages : MTLRenderStageVertex | MTLRenderStageFragment];
}
break;
}

@ -80,6 +80,9 @@ namespace AZ
m_nullDescriptorManager.Init(*this);
m_samplerCache = [[NSCache alloc]init];
[m_samplerCache setName:@"SamplerCache"];
return RHI::ResultCode::Success;
}
@ -101,6 +104,10 @@ namespace AZ
m_releaseQueue.Shutdown();
m_pipelineLayoutCache.Shutdown();
[m_samplerCache removeAllObjects];
[m_samplerCache release];
m_samplerCache = nil;
for (AZ::u32 i = 0; i < CommandEncoderTypeCount; ++i)
{
m_commandListPools[i].Shutdown();

@ -144,6 +144,11 @@ namespace AZ
return m_asyncUploadQueue;
}
const NSCache* GetSamplerCache() const
{
return m_samplerCache;
}
BufferMemoryAllocator& GetArgBufferConstantBufferAllocator() { return m_argumentBufferConstantsAllocator;}
BufferMemoryAllocator& GetArgumentBufferAllocator() { return m_argumentBufferAllocator;}
@ -194,6 +199,7 @@ namespace AZ
RHI::HeapMemoryUsage m_argumentBufferAllocatorMemoryUsage;
NullDescriptorManager m_nullDescriptorManager;
NSCache* m_samplerCache;
};
}
}

@ -11,6 +11,7 @@
*/
#include "Atom_RHI_Metal_precompiled.h"
#include <RHI/ArgumentBuffer.h>
#include <RHI/ImageView.h>
#include <RHI/ShaderResourceGroup.h>
@ -33,10 +34,12 @@ namespace AZ
return *m_compiledArgBuffers[m_compiledDataIndex];
}
void ShaderResourceGroup::AddUntrackedResourcesToEncoder(id<MTLCommandEncoder> commandEncoder,
const ShaderResourceGroupVisibility& srgResourcesVisInfo) const
void ShaderResourceGroup::CollectUntrackedResources(id<MTLCommandEncoder> commandEncoder,
const ShaderResourceGroupVisibility& srgResourcesVisInfo,
ArgumentBuffer::ComputeResourcesToMakeResidentMap& resourcesToMakeResidentCompute,
ArgumentBuffer::GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentGraphics) const
{
GetCompiledArgumentBuffer().AddUntrackedResourcesToEncoder(commandEncoder, srgResourcesVisInfo);
GetCompiledArgumentBuffer().CollectUntrackedResources(commandEncoder, srgResourcesVisInfo, resourcesToMakeResidentCompute, resourcesToMakeResidentGraphics);
}
}
}

@ -47,7 +47,10 @@ namespace AZ
const ImageView* GetImageView(const int index) const;
void UpdateCompiledDataIndex();
const ArgumentBuffer& GetCompiledArgumentBuffer() const;
void AddUntrackedResourcesToEncoder(id<MTLCommandEncoder> commandEncoder, const ShaderResourceGroupVisibility& srgResourcesVisInfo) const;
void CollectUntrackedResources(id<MTLCommandEncoder> commandEncoder,
const ShaderResourceGroupVisibility& srgResourcesVisInfo,
ArgumentBuffer::ComputeResourcesToMakeResidentMap& resourcesToMakeResidentCompute,
ArgumentBuffer::GraphicsResourcesToMakeResidentMap& resourcesToMakeResidentGraphics) const;
private:
ShaderResourceGroup() = default;

@ -30,6 +30,7 @@ namespace AZ
//! It does this by recursively creating Compute Passes to write to each mip using the Compute Shader.
class DownsampleMipChainPass
: public ParentPass
, private ShaderReloadNotificationBus::Handler
{
AZ_RPI_PASS(DownsampleMipChainPass);
@ -39,6 +40,7 @@ namespace AZ
//! Creates a new pass without a PassTemplate
static Ptr<DownsampleMipChainPass> Create(const PassDescriptor& descriptor);
virtual ~DownsampleMipChainPass();
protected:
explicit DownsampleMipChainPass(const PassDescriptor& descriptor);
@ -49,6 +51,11 @@ namespace AZ
void BuildInternal() override;
void FrameBeginInternal(FramePrepareParams params) override;
// ShaderReloadNotificationBus::Handler overrides...
void OnShaderReinitialized(const Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
private:
// Gets target height, width and mip levels from the input/output image attachment

@ -103,10 +103,14 @@ namespace AZ
AZStd::size_t CalculateTriangleCount() const;
};
class ModelAssetHandler : public AssetHandler<ModelAsset>
class ModelAssetHandler
: public AssetHandler<ModelAsset>
{
public:
AZ_RTTI(ModelAssetHandler, "{993B8CE3-1BBF-4712-84A0-285DB9AE808F}", AssetHandler<ModelAsset>);
// AZ::AssetTypeInfoBus::Handler overrides
bool HasConflictingProducts(const AZStd::vector<AZ::Data::AssetType>& productAssetTypes) const override;
};
} //namespace RPI
} // namespace AZ

@ -54,8 +54,14 @@ namespace AZ
}
m_passData = *passData;
ShaderReloadNotificationBus::Handler::BusConnect(passData->m_shaderReference.m_assetId);
}
DownsampleMipChainPass::~DownsampleMipChainPass()
{
ShaderReloadNotificationBus::Handler::BusDisconnect();
}
void DownsampleMipChainPass::ResetInternal()
{
RemoveChildren();
@ -206,5 +212,19 @@ namespace AZ
ParentPass::FrameBeginInternal(params);
}
void DownsampleMipChainPass::OnShaderReinitialized([[maybe_unused]] const Shader& shader)
{
m_needToUpdateChildren = true;
}
void DownsampleMipChainPass::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<ShaderAsset>& shaderAsset)
{
m_needToUpdateChildren = true;
}
void DownsampleMipChainPass::OnShaderVariantReinitialized([[maybe_unused]] const ShaderVariant& shaderVariant)
{
m_needToUpdateChildren = true;
}
} // namespace RPI
} // namespace AZ

@ -315,5 +315,26 @@ namespace AZ
return modelTriangleCount;
}
} //namespace RPI
bool ModelAssetHandler::HasConflictingProducts(const AZStd::vector<AZ::Data::AssetType>& productAssetTypes) const
{
size_t modelAssetCount = 0;
size_t actorAssetCount = 0;
for (const AZ::Data::AssetType& assetType : productAssetTypes)
{
if (assetType == azrtti_typeid<ModelAsset>())
{
modelAssetCount++;
}
else if (assetType == AZ::Data::AssetType("{F67CC648-EA51-464C-9F5D-4A9CE41A7F86}")) // ActorAsset
{
actorAssetCount++;
}
}
// When dropping a well-defined character, consisting of a mesh and a skeleton/actor,
// do not create an entity with a mesh component.
return modelAssetCount == 1 && actorAssetCount == 1;
}
} // namespace RPI
} // namespace AZ

@ -10,6 +10,9 @@
*
*/
#include <QApplication>
#include <QWidget>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/Matrix4x4.h>
@ -223,7 +226,12 @@ namespace MaterialEditor
}
else if (inputChannelId == InputDeviceKeyboard::Key::AlphanumericZ && (m_keys & Ctrl) == None)
{
Reset();
// only reset camera if no other widget besides viewport is in focus
const auto focus = QApplication::focusWidget();
if (!focus || focus->objectName() == "Viewport")
{
Reset();
}
}
break;
case InputChannel::State::Updated:

@ -17,6 +17,7 @@
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/std/string/conversions.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Utils/Utils.h>
#include <ACETypes.h>
#include <AudioSystemControl_wwise.h>
@ -540,11 +541,10 @@ namespace AudioControls
}
//-------------------------------------------------------------------------------------------//
AZStd::string CAudioSystemEditor_wwise::GetDataPath() const
AZ::IO::FixedMaxPath CAudioSystemEditor_wwise::GetDataPath() const
{
AZStd::string path(Path::GetEditingGameDataFolder());
AZ::StringFunc::Path::Join(path.c_str(), "sounds/wwise_project/", path);
return path;
auto projectPath = AZ::IO::FixedMaxPath{ AZ::Utils::GetProjectPath() };
return (projectPath / "sounds" / "wwise_project");
}
} // namespace AudioControls

@ -86,7 +86,7 @@ namespace AudioControls
const AZStd::string_view GetTypeIcon(TImplControlType type) const override;
const AZStd::string_view GetTypeIconSelected(TImplControlType type) const override;
AZStd::string GetName() const override;
AZStd::string GetDataPath() const;
AZ::IO::FixedMaxPath GetDataPath() const override;
void DataSaved() override {}
void ConnectionRemoved(IAudioSystemControl* control) override;
//////////////////////////////////////////////////////////

@ -54,12 +54,12 @@ namespace AudioControls
void CAudioWwiseLoader::Load(CAudioSystemEditor_wwise* audioSystemImpl)
{
m_audioSystemImpl = audioSystemImpl;
const AZStd::string wwiseProjectFullPath(m_audioSystemImpl->GetDataPath());
LoadControlsInFolder(wwiseProjectFullPath + WwiseStrings::GameParametersFolder);
LoadControlsInFolder(wwiseProjectFullPath + WwiseStrings::GameStatesFolder);
LoadControlsInFolder(wwiseProjectFullPath + WwiseStrings::SwitchesFolder);
LoadControlsInFolder(wwiseProjectFullPath + WwiseStrings::EventsFolder);
LoadControlsInFolder(wwiseProjectFullPath + WwiseStrings::EnvironmentsFolder);
const AZ::IO::FixedMaxPath wwiseProjectFullPath{ m_audioSystemImpl->GetDataPath() };
LoadControlsInFolder(AZ::IO::FixedMaxPath{ wwiseProjectFullPath / WwiseStrings::GameParametersFolder }.Native());
LoadControlsInFolder(AZ::IO::FixedMaxPath{ wwiseProjectFullPath / WwiseStrings::GameStatesFolder }.Native());
LoadControlsInFolder(AZ::IO::FixedMaxPath{ wwiseProjectFullPath / WwiseStrings::SwitchesFolder }.Native());
LoadControlsInFolder(AZ::IO::FixedMaxPath{ wwiseProjectFullPath / WwiseStrings::EventsFolder }.Native());
LoadControlsInFolder(AZ::IO::FixedMaxPath{ wwiseProjectFullPath / WwiseStrings::EnvironmentsFolder }.Native());
LoadSoundBanks(Audio::Wwise::GetBanksRootPath(), "", false);
}

@ -14,6 +14,7 @@
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/string/string_view.h>
#include <ACETypes.h>
@ -151,7 +152,7 @@ namespace AudioControls
//! Gets the folder where the implementation specific controls data are stored.
//! This is used by the ACE to update if controls are changed while the editor is open.
//! @return String with the path to the folder where the implementation specific controls are stored.
virtual AZStd::string GetDataPath() const = 0;
virtual AZ::IO::FixedMaxPath GetDataPath() const = 0;
//! Informs the plugin that the ACE has saved the data in case it needs to do any clean up.
virtual void DataSaved() = 0;

@ -218,7 +218,7 @@ namespace AudioControls
IAudioSystemEditor* pAudioSystemImpl = CAudioControlsEditorPlugin::GetAudioSystemEditorImpl();
if (pAudioSystemImpl)
{
StartWatchingFolder(pAudioSystemImpl->GetDataPath());
StartWatchingFolder(pAudioSystemImpl->GetDataPath().LexicallyNormal().Native());
m_pMiddlewareDockWidget->setWindowTitle(QString(pAudioSystemImpl->GetName().c_str()) + " Controls");
}
}

@ -14,6 +14,7 @@
// AZ
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/containers/map.h>
// Graph Model

@ -14,10 +14,10 @@
// AZ
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/any.h>
#include <AzCore/std/smart_ptr/enable_shared_from_this.h>
// Graph Model
#include <GraphModel/Integration/GraphCanvasMetadata.h>
#include <GraphModel/Model/Common.h>
#include <GraphModel/Model/GraphElement.h>
@ -136,9 +136,9 @@ namespace GraphModel
//! Set/gets a bundle of generic metadata that is provided by the node graph UI
//! system. This may include node positions, comment blocks, node groupings, and
//! bookmarks, for example.
void SetUiMetadata(const AZStd::any& uiMetadata);
const AZStd::any& GetUiMetadata() const;
AZStd::any& GetUiMetadata();
void SetUiMetadata(const GraphModelIntegration::GraphCanvasMetadata& uiMetadata);
const GraphModelIntegration::GraphCanvasMetadata& GetUiMetadata() const;
GraphModelIntegration::GraphCanvasMetadata& GetUiMetadata();
AZStd::shared_ptr<Slot> FindSlot(const Endpoint& endpoint);
@ -157,7 +157,7 @@ namespace GraphModel
ConnectionList m_connections;
//! Used to store and serialize metadata from the graph UI, like node positions, comments, group boxes, etc.
AZStd::any m_uiMetadata;
GraphModelIntegration::GraphCanvasMetadata m_uiMetadata;
//! Used to store all of our node <-> wrapper node mappings
NodeWrappingMap m_nodeWrappings;

@ -12,6 +12,7 @@
#pragma once
// AZ
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/std/any.h>
#include <AzCore/std/hash.h>
#include <AzCore/std/containers/list.h>
@ -165,6 +166,32 @@ namespace GraphModel
ExtendableSlotConfiguration m_extendableSlotConfiguration;
};
//! Custom JSON serializer for Slot because we use an AZStd::any for m_value
class JsonSlotSerializer
: public AZ::BaseJsonSerializer
{
public:
AZ_RTTI(JsonSlotSerializer, "{8AC96D70-7BCD-4D68-8813-269938982D51}", AZ::BaseJsonSerializer);
AZ_CLASS_ALLOCATOR(JsonSlotSerializer, AZ::SystemAllocator, 0);
AZ::JsonSerializationResult::Result Load(
void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
AZ::JsonDeserializerContext& context) override;
AZ::JsonSerializationResult::Result Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const AZ::Uuid& valueTypeId,
AZ::JsonSerializerContext& context) override;
private:
template<typename T>
bool LoadAny(
AZStd::any& propertyValue, const rapidjson::Value& inputPropertyValue, AZ::JsonDeserializerContext& context,
AZ::JsonSerializationResult::ResultCode& result);
template<typename T>
bool StoreAny(
const AZStd::any& propertyValue, rapidjson::Value& outputPropertyValue, AZ::JsonSerializerContext& context,
AZ::JsonSerializationResult::ResultCode& result);
};
//!!! Start in Graph.h for high level GraphModel documentation !!!
@ -180,6 +207,7 @@ namespace GraphModel
class Slot : public GraphElement, public AZStd::enable_shared_from_this<Slot>
{
friend class Graph; // So the Graph can update the Slot's cache of Connection pointers
friend class JsonSlotSerializer; // So we can set the m_value and m_subId directly from the serializer
public:
AZ_CLASS_ALLOCATOR(Slot, AZ::SystemAllocator, 0);

@ -1338,11 +1338,7 @@ namespace GraphModelIntegration
GraphCanvasMetadata* GraphController::GetGraphMetadata()
{
if (!m_graph->GetUiMetadata().is<GraphCanvasMetadata>())
{
m_graph->SetUiMetadata(AZStd::any(GraphCanvasMetadata()));
}
GraphCanvasMetadata* graphCanvasMetadata = AZStd::any_cast<GraphCanvasMetadata>(&m_graph->GetUiMetadata());
GraphCanvasMetadata* graphCanvasMetadata = &m_graph->GetUiMetadata();
AZ_Assert(graphCanvasMetadata, "GraphCanvasMetadata not initialized");
return graphCanvasMetadata;
}

@ -37,7 +37,7 @@ namespace GraphModel
if (serializeContext)
{
serializeContext->Class<Graph>()
->Version(1)
->Version(2)
->Field("m_nodes", &Graph::m_nodes)
->Field("m_connections", &Graph::m_connections)
->Field("m_uiMetadata", &Graph::m_uiMetadata)
@ -312,19 +312,19 @@ namespace GraphModel
}
void Graph::SetUiMetadata(const AZStd::any& uiMetadata)
void Graph::SetUiMetadata(const GraphModelIntegration::GraphCanvasMetadata& uiMetadata)
{
m_uiMetadata = uiMetadata;
}
const AZStd::any& Graph::GetUiMetadata() const
const GraphModelIntegration::GraphCanvasMetadata& Graph::GetUiMetadata() const
{
return m_uiMetadata;
}
AZStd::any& Graph::GetUiMetadata()
GraphModelIntegration::GraphCanvasMetadata& Graph::GetUiMetadata()
{
return m_uiMetadata;
}

@ -11,9 +11,14 @@
*/
// AZ
#include <AzCore/Math/Color.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Vector4.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzCore/Serialization/SerializeContext.h>
// Graph Model
@ -294,13 +299,164 @@ namespace GraphModel
/////////////////////////////////////////////////////////
// Slot
AZ::JsonSerializationResult::Result JsonSlotSerializer::Load(
void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
AZ::JsonDeserializerContext& context)
{
namespace JSR = AZ::JsonSerializationResult;
AZ_Assert(
azrtti_typeid<Slot>() == outputValueTypeId,
"Unable to deserialize Slot from json because the provided type is %s.",
outputValueTypeId.ToString<AZStd::string>().c_str());
Slot* slot = reinterpret_cast<Slot*>(outputValue);
AZ_Assert(slot, "Output value for JsonSlotSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::ReadField);
auto serializedSlotValue = inputValue.FindMember("m_value");
if (serializedSlotValue != inputValue.MemberEnd())
{
AZStd::any slotValue;
if (LoadAny<bool>(slotValue, serializedSlotValue->value, context, result) ||
LoadAny<int>(slotValue, serializedSlotValue->value, context, result) ||
LoadAny<float>(slotValue, serializedSlotValue->value, context, result) ||
LoadAny<AZStd::string>(slotValue, serializedSlotValue->value, context, result) ||
LoadAny<AZ::Vector2>(slotValue, serializedSlotValue->value, context, result) ||
LoadAny<AZ::Vector3>(slotValue, serializedSlotValue->value, context, result) ||
LoadAny<AZ::Vector4>(slotValue, serializedSlotValue->value, context, result) ||
LoadAny<AZ::EntityId>(slotValue, serializedSlotValue->value, context, result))
{
slot->m_value = slotValue;
}
}
// Load m_subId normally because it's just an int
{
SlotSubId slotSubId = 0;
result.Combine(ContinueLoadingFromJsonObjectField(
&slotSubId, azrtti_typeid<SlotSubId>(), inputValue,
"m_subId", context));
slot->m_subId = slotSubId;
}
return context.Report(
result,
result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded Slot information."
: "Failed to load Slot information.");
}
AZ::JsonSerializationResult::Result JsonSlotSerializer::Store(
rapidjson::Value& outputValue, const void* inputValue, [[maybe_unused]] const void* defaultValue, const AZ::Uuid& valueTypeId,
AZ::JsonSerializerContext& context)
{
namespace JSR = AZ::JsonSerializationResult;
AZ_Assert(
azrtti_typeid<Slot>() == valueTypeId,
"Unable to Serialize Slot because the provided type is %s.", valueTypeId.ToString<AZStd::string>().c_str());
const Slot* slot = reinterpret_cast<const Slot*>(inputValue);
AZ_Assert(slot, "Input value for JsonSlotSerializer can't be null.");
outputValue.SetObject();
JSR::ResultCode result(JSR::Tasks::WriteValue);
{
AZ::ScopedContextPath subPathPropertyOverrides(context, "m_value");
if (!slot->m_value.empty())
{
rapidjson::Value outputPropertyValue;
if (StoreAny<bool>(slot->m_value, outputPropertyValue, context, result) ||
StoreAny<int>(slot->m_value, outputPropertyValue, context, result) ||
StoreAny<float>(slot->m_value, outputPropertyValue, context, result) ||
StoreAny<AZStd::string>(slot->m_value, outputPropertyValue, context, result) ||
StoreAny<AZ::Vector2>(slot->m_value, outputPropertyValue, context, result) ||
StoreAny<AZ::Vector3>(slot->m_value, outputPropertyValue, context, result) ||
StoreAny<AZ::Vector4>(slot->m_value, outputPropertyValue, context, result) ||
StoreAny<AZ::EntityId>(slot->m_value, outputPropertyValue, context, result))
{
outputValue.AddMember("m_value", outputPropertyValue, context.GetJsonAllocator());
}
}
}
{
AZ::ScopedContextPath subSlotId(context, "m_subId");
SlotSubId defaultSubId = 0;
result.Combine(ContinueStoringToJsonObjectField(
outputValue, "m_subId", &slot->m_subId, &defaultSubId,
azrtti_typeid<SlotSubId>(), context));
}
return context.Report(
result,
result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored MaterialAssignment information."
: "Failed to store MaterialAssignment information.");
}
template<typename T>
bool JsonSlotSerializer::LoadAny(
AZStd::any& propertyValue, const rapidjson::Value& inputPropertyValue, AZ::JsonDeserializerContext& context,
AZ::JsonSerializationResult::ResultCode& result)
{
auto valueItr = inputPropertyValue.FindMember("Value");
auto typeItr = inputPropertyValue.FindMember("$type");
if ((valueItr != inputPropertyValue.MemberEnd()) && (typeItr != inputPropertyValue.MemberEnd()))
{
// Requiring explicit type info to differentiate between colors versus vectors and numeric types
const AZ::Uuid baseTypeId = azrtti_typeid<T>();
AZ::Uuid typeId = AZ::Uuid::CreateNull();
result.Combine(LoadTypeId(typeId, inputPropertyValue, context, &baseTypeId));
if (typeId == azrtti_typeid<T>())
{
T value;
result.Combine(ContinueLoadingFromJsonObjectField(&value, azrtti_typeid<T>(), inputPropertyValue, "Value", context));
propertyValue = value;
return true;
}
}
return false;
}
template<typename T>
bool JsonSlotSerializer::StoreAny(
const AZStd::any& propertyValue, rapidjson::Value& outputPropertyValue, AZ::JsonSerializerContext& context,
AZ::JsonSerializationResult::ResultCode& result)
{
if (propertyValue.is<T>())
{
outputPropertyValue.SetObject();
// Storing explicit type info to differentiate between colors versus vectors and numeric types
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, azrtti_typeid<T>(), context));
outputPropertyValue.AddMember("$type", typeValue, context.GetJsonAllocator());
T value = AZStd::any_cast<T>(propertyValue);
result.Combine(
ContinueStoringToJsonObjectField(outputPropertyValue, "Value", &value, nullptr, azrtti_typeid<T>(), context));
return true;
}
return false;
}
void Slot::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
if (auto jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
{
jsonContext->Serializer<JsonSlotSerializer>()->HandlesType<Slot>();
}
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<Slot>()
->Version(0)
->Version(1)
->Field("m_value", &Slot::m_value)
->Field("m_subId", &Slot::m_subId)
// m_slotDescription is not reflected because that data is populated procedurally by each node

@ -460,10 +460,10 @@ namespace LandscapeCanvasEditor
GraphCanvas::StyleManagerRequestBus::Event(editorId, &GraphCanvas::StyleManagerRequests::RegisterDataPaletteStyle, LandscapeCanvas::AreaTypeId, "VegetationAreaDataColorPalette");
LandscapeCanvas::LandscapeCanvasRequestBus::Handler::BusConnect();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
AzToolsFramework::EditorPickModeNotificationBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
AzToolsFramework::EntityCompositionNotificationBus::Handler::BusConnect();
AzToolsFramework::ToolsApplicationNotificationBus::Handler::BusConnect();
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
CrySystemEventBus::Handler::BusConnect();
AZ::EntitySystemBus::Handler::BusConnect();
@ -480,6 +480,7 @@ namespace LandscapeCanvasEditor
{
AZ::EntitySystemBus::Handler::BusDisconnect();
CrySystemEventBus::Handler::BusDisconnect();
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect();
AzToolsFramework::ToolsApplicationNotificationBus::Handler::BusDisconnect();
AzToolsFramework::EditorPickModeNotificationBus::Handler::BusDisconnect();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
@ -883,6 +884,10 @@ namespace LandscapeCanvasEditor
if (landscapeCanvasComponent)
{
landscapeCanvasComponent->m_graph = *m_serializeContext->CloneObject(graph.get());
// Mark the Landscape Canvas entity as dirty so the changes to the graph will be picked up on the next save
AzToolsFramework::ScopedUndoBatch undo("Update Landscape Canvas Graph");
AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, rootEntityId);
}
}
}
@ -1572,7 +1577,7 @@ namespace LandscapeCanvasEditor
void MainWindow::HandleEditorEntityCreated(const AZ::EntityId& entityId, GraphCanvas::GraphId graphId)
{
if (m_ignoreGraphUpdates)
if (m_ignoreGraphUpdates || m_prefabPropagationInProgress)
{
return;
}
@ -1622,6 +1627,11 @@ namespace LandscapeCanvasEditor
void MainWindow::OnEditorEntityDeleted(const AZ::EntityId& entityId)
{
if (m_prefabPropagationInProgress)
{
return;
}
m_queuedEntityDeletes.push_back(entityId);
QTimer::singleShot(0, [this, entityId]() {
@ -2456,6 +2466,11 @@ namespace LandscapeCanvasEditor
void MainWindow::EntityParentChanged(AZ::EntityId entityId, AZ::EntityId newParentId, AZ::EntityId oldParentId)
{
if (m_prefabPropagationInProgress)
{
return;
}
GraphCanvas::GraphId oldGraphId = FindGraphContainingEntity(oldParentId);
GraphCanvas::GraphId newGraphId = FindGraphContainingEntity(newParentId);
@ -2482,6 +2497,20 @@ namespace LandscapeCanvasEditor
}
}
void MainWindow::OnPrefabInstancePropagationBegin()
{
// Ignore graph updates during prefab propagation because the entities will be
// deleted and re-created, which would inadvertantly trigger our logic to close
// the graph when the corresponding entity is deleted.
m_prefabPropagationInProgress = true;
}
void MainWindow::OnPrefabInstancePropagationEnd()
{
// See comment above in OnPrefabInstancePropagationBegin
m_prefabPropagationInProgress = false;
}
void MainWindow::OnCryEditorEndCreate()
{
UpdateGraphEnabled();
@ -2490,6 +2519,15 @@ namespace LandscapeCanvasEditor
void MainWindow::OnCryEditorEndLoad()
{
UpdateGraphEnabled();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
}
void MainWindow::OnCryEditorCloseScene()
{
UpdateGraphEnabled();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
}
void MainWindow::OnCryEditorSceneClosed()

@ -24,6 +24,7 @@
#include <AzToolsFramework/API/EntityCompositionNotificationBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
#include <AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
@ -84,6 +85,7 @@ namespace LandscapeCanvasEditor
, private AzToolsFramework::EntityCompositionNotificationBus::Handler
, private AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler
, private AzToolsFramework::ToolsApplicationNotificationBus::Handler
, private AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
, private CrySystemEventBus::Handler
{
Q_OBJECT
@ -183,10 +185,15 @@ namespace LandscapeCanvasEditor
void EntityParentChanged(AZ::EntityId entityId, AZ::EntityId newParentId, AZ::EntityId oldParentId) override;
////////////////////////////////////////////////////////////////////////
//! PrefabPublicNotificationBus overrides
void OnPrefabInstancePropagationBegin() override;
void OnPrefabInstancePropagationEnd() override;
////////////////////////////////////////////////////////////////////////
// CrySystemEventBus overrides
void OnCryEditorEndCreate() override;
void OnCryEditorEndLoad() override;
void OnCryEditorCloseScene() override;
void OnCryEditorSceneClosed() override;
////////////////////////////////////////////////////////////////////////
@ -246,6 +253,7 @@ namespace LandscapeCanvasEditor
AZ::SerializeContext* m_serializeContext = nullptr;
bool m_ignoreGraphUpdates = false;
bool m_prefabPropagationInProgress = false;
bool m_inObjectPickMode = false;
using DeletedNodePositionsMap = AZStd::unordered_map<AZ::EntityComponentIdPair, AZ::Vector2>;

@ -8,12 +8,3 @@
# 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.
#
add_custom_command(TARGET LmbrCentral.Editor POST_BUILD
COMMAND "${CMAKE_COMMAND}" -P "${LY_ROOT_FOLDER}/cmake/Platform/Mac/RPathChange.cmake"
"$<TARGET_FILE_DIR:LmbrCentral.Editor>/lrelease"
@loader_path/../lib
"${QT_PATH}/lib"
COMMENT "Patching lrelease..."
VERBATIM
)

@ -8,19 +8,3 @@
# 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.
#
add_custom_command(TARGET LmbrCentral.Editor POST_BUILD
COMMAND "${CMAKE_COMMAND}"
-DLY_TIMESTAMP_REFERENCE=$<TARGET_FILE_DIR:LmbrCentral.Editor>/lrelease.exe
-DLY_LOCK_FILE=$<TARGET_FILE_DIR:LmbrCentral.Editor>/qtdeploy.lock
-P ${LY_ROOT_FOLDER}/cmake/CommandExecution.cmake
EXEC_COMMAND "${CMAKE_COMMAND}" -E
env PATH="${QT_PATH}/bin"
${WINDEPLOYQT_EXECUTABLE}
$<$<CONFIG:Debug>:--pdb>
--verbose 0
--no-compiler-runtime
$<TARGET_FILE_DIR:LmbrCentral.Editor>/lrelease.exe
COMMENT "Patching lrelease..."
VERBATIM
)

@ -63,10 +63,10 @@ namespace Multiplayer
//! @}
NetEntityId GetNetEntityId() const;
bool IsAuthority() const;
bool IsAutonomous() const;
bool IsServer() const;
bool IsClient() const;
bool IsNetEntityRoleAuthority() const;
bool IsNetEntityRoleAutonomous() const;
bool IsNetEntityRoleServer() const;
bool IsNetEntityRoleClient() const;
ConstNetworkEntityHandle GetEntityHandle() const;
NetworkEntityHandle GetEntityHandle();
void MarkDirty();

@ -64,10 +64,23 @@ namespace Multiplayer
//! @}
NetEntityRole GetNetEntityRole() const;
bool IsAuthority() const;
bool IsAutonomous() const;
bool IsServer() const;
bool IsClient() const;
//! IsNetEntityRoleAuthority
//! @return true if this network entity is an authoritative proxy on a server (full authority); otherwise false.
bool IsNetEntityRoleAuthority() const;
//! IsNetEntityRoleAutonomous
//! @return true if this network entity is an autonomous proxy on a client (can execute local prediction) or if this network entity is an authoritative proxy on a server but has autonomous privileges (ie: a host who is also a player); otherwise false.
bool IsNetEntityRoleAutonomous() const;
//! IsNetEntityRoleServer
//! @return true if this network entity is a simulated proxy on a server (ie: a different server may have authority for this entity, but the entity has been replicated on this server; otherwise false.
bool IsNetEntityRoleServer() const;
//! IsNetEntityRoleClient
//! @return true if this network entity is a simulated proxy on a client; otherwise false.
bool IsNetEntityRoleClient() const;
bool HasController() const;
NetEntityId GetNetEntityId() const;
const PrefabEntityId& GetPrefabEntityId() const;

@ -46,24 +46,24 @@ namespace Multiplayer
return m_netBindComponent ? m_netBindComponent->GetNetEntityId() : InvalidNetEntityId;
}
bool MultiplayerComponent::IsAuthority() const
bool MultiplayerComponent::IsNetEntityRoleAuthority() const
{
return m_netBindComponent ? m_netBindComponent->IsAuthority() : false;
return m_netBindComponent ? m_netBindComponent->IsNetEntityRoleAuthority() : false;
}
bool MultiplayerComponent::IsAutonomous() const
bool MultiplayerComponent::IsNetEntityRoleAutonomous() const
{
return m_netBindComponent ? m_netBindComponent->IsAutonomous() : false;
return m_netBindComponent ? m_netBindComponent->IsNetEntityRoleAutonomous() : false;
}
bool MultiplayerComponent::IsServer() const
bool MultiplayerComponent::IsNetEntityRoleServer() const
{
return m_netBindComponent ? m_netBindComponent->IsServer() : false;
return m_netBindComponent ? m_netBindComponent->IsNetEntityRoleServer() : false;
}
bool MultiplayerComponent::IsClient() const
bool MultiplayerComponent::IsNetEntityRoleClient() const
{
return m_netBindComponent ? m_netBindComponent->IsClient() : false;
return m_netBindComponent ? m_netBindComponent->IsNetEntityRoleClient() : false;
}
ConstNetworkEntityHandle MultiplayerComponent::GetEntityHandle() const

@ -29,12 +29,12 @@ namespace Multiplayer
bool MultiplayerController::IsAuthority() const
{
return GetNetBindComponent() ? GetNetBindComponent()->IsAuthority() : false;
return GetNetBindComponent() ? GetNetBindComponent()->IsNetEntityRoleAuthority() : false;
}
bool MultiplayerController::IsAutonomous() const
{
return GetNetBindComponent() ? GetNetBindComponent()->IsAutonomous() : false;
return GetNetBindComponent() ? GetNetBindComponent()->IsNetEntityRoleAutonomous() : false;
}
AZ::Entity* MultiplayerController::GetEntity() const

@ -54,69 +54,72 @@ namespace Multiplayer
->Attribute(AZ::Script::Attributes::Module, "multiplayer")
->Attribute(AZ::Script::Attributes::Category, "Multiplayer")
->Method("IsAuthority", [](AZ::EntityId id) -> bool {
->Method("IsNetEntityRoleAuthority", [](AZ::EntityId id) -> bool {
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(id);
if (!entity)
{
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsAuthority failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsNetEntityRoleAuthority failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
return false;
}
NetBindComponent* netBindComponent = entity-> FindComponent<NetBindComponent>();
if (!netBindComponent)
{
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsAuthority failed. Entity '%s' (id: %s) is missing a NetBindComponent, make sure this entity contains a component which derives from NetBindComponent.", entity->GetName().c_str(), id.ToString().c_str())
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsNetEntityRoleAuthority failed. Entity '%s' (id: %s) is missing a NetBindComponent, make sure this entity contains a component which derives from NetBindComponent.", entity->GetName().c_str(), id.ToString().c_str())
return false;
}
return netBindComponent->IsAuthority();
return netBindComponent->IsNetEntityRoleAuthority();
})
->Method("IsAutonomous", [](AZ::EntityId id) -> bool {
->Method("IsNetEntityRoleAutonomous", [](AZ::EntityId id) -> bool {
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(id);
if (!entity)
{
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsAutonomous failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsNetEntityRoleAutonomous failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
return false;
}
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (!netBindComponent)
{
AZ_Warning("NetBindComponent", false, "NetBindComponent IsAutonomous failed. Entity '%s' (id: %s) is missing a NetBindComponent, make sure this entity contains a component which derives from NetBindComponent.", entity->GetName().c_str(), id.ToString().c_str())
AZ_Warning("NetBindComponent", false, "NetBindComponent IsNetEntityRoleAutonomous failed. Entity '%s' (id: %s) is missing a NetBindComponent, make sure this entity contains a component which derives from NetBindComponent.", entity->GetName().c_str(), id.ToString().c_str())
return false;
}
return netBindComponent->IsAutonomous();
return netBindComponent->IsNetEntityRoleAutonomous();
})
->Method("IsClient", [](AZ::EntityId id) -> bool {
->Method("IsNetEntityRoleClient", [](AZ::EntityId id) -> bool {
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(id);
if (!entity)
{
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsClient failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsNetEntityRoleClient failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
return false;
}
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (!netBindComponent)
{
AZ_Warning("NetBindComponent", false, "NetBindComponent IsClient failed. Entity '%s' (id: %s) is missing a NetBindComponent, make sure this entity contains a component which derives from NetBindComponent.", entity->GetName().c_str(), id.ToString().c_str())
AZ_Warning("NetBindComponent", false, "NetBindComponent IsNetEntityRoleClient failed. Entity '%s' (id: %s) is missing a NetBindComponent, make sure this entity contains a component which derives from NetBindComponent.", entity->GetName().c_str(), id.ToString().c_str())
return false;
}
return netBindComponent->IsClient();
return netBindComponent->IsNetEntityRoleClient();
})
->Method("IsServer", [](AZ::EntityId id) -> bool {
->Method("IsNetEntityRoleServer", [](AZ::EntityId id) -> bool {
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(id);
if (!entity)
{
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsServer failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
AZ_Warning( "NetBindComponent", false, "NetBindComponent IsNetEntityRoleServer failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
return false;
}
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (!netBindComponent)
{
AZ_Warning("NetBindComponent", false, "NetBindComponent IsServer failed. Entity '%s' (id: %s) is missing a NetBindComponent, make sure this entity contains a component which derives from NetBindComponent.", entity->GetName().c_str(), id.ToString().c_str())
AZ_Warning("NetBindComponent", false, "NetBindComponent IsNetEntityRoleServer failed. Entity '%s' (id: %s) is missing a NetBindComponent, make sure this entity contains a component which derives from NetBindComponent.", entity->GetName().c_str(), id.ToString().c_str())
return false;
}
return netBindComponent->IsServer();
return netBindComponent->IsNetEntityRoleServer();
})
;
}
@ -179,23 +182,23 @@ namespace Multiplayer
return m_netEntityRole;
}
bool NetBindComponent::IsAuthority() const
bool NetBindComponent::IsNetEntityRoleAuthority() const
{
return (m_netEntityRole == NetEntityRole::Authority);
}
bool NetBindComponent::IsAutonomous() const
bool NetBindComponent::IsNetEntityRoleAutonomous() const
{
return (m_netEntityRole == NetEntityRole::Autonomous)
|| (m_netEntityRole == NetEntityRole::Authority) && m_allowAutonomy;
}
bool NetBindComponent::IsServer() const
bool NetBindComponent::IsNetEntityRoleServer() const
{
return (m_netEntityRole == NetEntityRole::Server);
}
bool NetBindComponent::IsClient() const
bool NetBindComponent::IsNetEntityRoleClient() const
{
return (m_netEntityRole == NetEntityRole::Client);
}

@ -96,7 +96,7 @@ namespace Multiplayer
{
AZ_Assert(entityHandle.GetNetBindComponent(), "No NetBindComponent found on networked entity");
[[maybe_unused]] const bool isClientOnlyEntity = false;// (ServerIdFromEntityId(it->first) == InvalidHostId);
AZ_Assert(entityHandle.GetNetBindComponent()->IsAuthority() || isClientOnlyEntity, "Trying to delete a proxy entity, this will lead to issues deserializing entity updates");
AZ_Assert(entityHandle.GetNetBindComponent()->IsNetEntityRoleAuthority() || isClientOnlyEntity, "Trying to delete a proxy entity, this will lead to issues deserializing entity updates");
}
m_removeList.push_back(entityHandle.GetNetEntityId());
m_removeEntitiesEvent.Enqueue(AZ::TimeMs{ 0 });

@ -17,6 +17,7 @@
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzFramework/Physics/MaterialBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <LyViewPaneNames.h>
@ -56,6 +57,15 @@ namespace PhysX
return false;
}
bool IsDrawColliderReadOnly()
{
bool helpersVisible = false;
AzToolsFramework::EditorRequestBus::BroadcastResult(helpersVisible,
&AzToolsFramework::EditorRequests::DisplayHelpersVisible);
// if helpers are visible, draw colliders is NOT read only and can be changed.
return !helpersVisible;
}
static void BuildAABBVerts(const AZ::Aabb& aabb,
AZStd::vector<AZ::Vector3>& verts,
AZStd::vector<AZ::Vector3>& points,
@ -145,28 +155,42 @@ namespace PhysX
"PhysX Collider Debug Draw", "Manages global and per-collider debug draw settings and logic")
->DataElement(AZ::Edit::UIHandlers::CheckBox, &Collider::m_locallyEnabled, "Draw collider",
"Shows the geometry for the collider in the viewport")
->Attribute(AZ::Edit::Attributes::CheckboxTooltip,
"If set, the geometry of this collider is visible in the viewport")
->Attribute(AZ::Edit::Attributes::Visibility,
VisibilityFunc{ []() { return IsGlobalColliderDebugCheck(GlobalCollisionDebugState::Manual); } })
->Attribute(AZ::Edit::Attributes::CheckboxTooltip,
"If set, the geometry of this collider is visible in the viewport. 'Draw Helpers' needs to be enabled to use.")
->Attribute(AZ::Edit::Attributes::Visibility,
VisibilityFunc{ []() { return IsGlobalColliderDebugCheck(GlobalCollisionDebugState::Manual); } })
->Attribute(AZ::Edit::Attributes::ReadOnly, &IsDrawColliderReadOnly)
->DataElement(AZ::Edit::UIHandlers::Button, &Collider::m_globalButtonState, "Draw collider",
"Shows the geometry for the collider in the viewport")
->Attribute(AZ::Edit::Attributes::ButtonText, "Global override")
->Attribute(AZ::Edit::Attributes::ButtonTooltip,
"A global setting is overriding this property (to disable the override, "
"set the Global Collision Debug setting to \"Set manually\" in the PhysX Configuration)")
->Attribute(AZ::Edit::Attributes::Visibility,
VisibilityFunc{ []() { return !IsGlobalColliderDebugCheck(GlobalCollisionDebugState::Manual); } })
->Attribute(AZ::Edit::Attributes::ChangeNotify, &OpenPhysXSettingsWindow)
->Attribute(AZ::Edit::Attributes::ButtonText, "Global override")
->Attribute(AZ::Edit::Attributes::ButtonTooltip,
"A global setting is overriding this property (to disable the override, "
"set the Global Collision Debug setting to \"Set manually\" in the PhysX Configuration)."
"'Draw Helpers' needs to be enabled to use.")
->Attribute(AZ::Edit::Attributes::Visibility,
VisibilityFunc{ []() { return !IsGlobalColliderDebugCheck(GlobalCollisionDebugState::Manual); } })
->Attribute(AZ::Edit::Attributes::ChangeNotify, &OpenPhysXSettingsWindow)
->Attribute(AZ::Edit::Attributes::ReadOnly, &IsDrawColliderReadOnly)
;
}
}
}
Collider::Collider()
: m_debugDisplayDataChangedEvent(
[this]([[maybe_unused]] const PhysX::Debug::DebugDisplayData& data)
{
this->RefreshTreeHelper();
})
{
}
void Collider::Connect(AZ::EntityId entityId)
{
m_entityId = entityId;
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityId);
AzToolsFramework::EntitySelectionEvents::Bus::Handler::BusConnect(m_entityId);
}
void Collider::SetDisplayCallback(const DisplayCallback* callback)
@ -176,6 +200,11 @@ namespace PhysX
void Collider::Disconnect()
{
if (AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusIsConnected())
{
AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusDisconnect();
}
AzToolsFramework::EntitySelectionEvents::Bus::Handler::BusDisconnect();
AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
m_displayCallback = nullptr;
m_entityId = AZ::EntityId();
@ -731,6 +760,33 @@ namespace PhysX
}
}
void Collider::OnDrawHelpersChanged([[maybe_unused]] bool enabled)
{
RefreshTreeHelper();
}
void Collider::OnSelected()
{
AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusConnect(
AzFramework::g_defaultSceneEntityDebugDisplayId);
if (auto* physXDebug = AZ::Interface<Debug::PhysXDebugInterface>::Get())
{
physXDebug->RegisterDebugDisplayDataChangedEvent(m_debugDisplayDataChangedEvent);
}
}
void Collider::OnDeselected()
{
AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusDisconnect();
m_debugDisplayDataChangedEvent.Disconnect();
}
void Collider::RefreshTreeHelper()
{
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(
&AzToolsFramework::ToolsApplicationEvents::Bus::Events::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
}
AZStd::string Collider::GetEntityName() const
{
AZStd::string entityName;

@ -15,8 +15,11 @@
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzFramework/Physics/ShapeConfiguration.h>
#include <AzFramework/Physics/Shape.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <PhysX/MeshAsset.h>
#include <PhysX/Debug/PhysXDebugConfiguration.h>
#include <PhysX/Debug/PhysXDebugInterface.h>
namespace PhysX
{
@ -40,13 +43,15 @@ namespace PhysX
class Collider
: protected AzFramework::EntityDebugDisplayEventBus::Handler
, protected AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Handler
, protected AzToolsFramework::EntitySelectionEvents::Bus::Handler
{
public:
AZ_CLASS_ALLOCATOR(Collider, AZ::SystemAllocator, 0);
AZ_RTTI(Collider, "{7DE9CA01-DF1E-4D72-BBF4-76C9136BE6A2}");
static void Reflect(AZ::ReflectContext* context);
Collider() = default;
Collider();
void Connect(AZ::EntityId entityId);
void SetDisplayCallback(const DisplayCallback* callback);
@ -109,11 +114,20 @@ namespace PhysX
const AZStd::vector<AZ::u32>& GetIndices(AZ::u32 geomIndex) const;
protected:
// AzFramework::EntityDebugDisplayEventBus
// AzFramework::EntityDebugDisplayEventBus overrides ...
void DisplayEntityViewport(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
// AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Handler overrides ...
void OnDrawHelpersChanged(bool enabled) override;
// AzToolsFramework::EntitySelectionEvents::Bus::Handler overrides ...
void OnSelected() override;
void OnDeselected() override;
void RefreshTreeHelper();
// Internal mesh drawing subroutines
void DrawTriangleMesh(
AzFramework::DebugDisplayRequests& debugDisplay, const Physics::ColliderConfiguration& colliderConfig, AZ::u32 geomIndex,
@ -143,6 +157,8 @@ namespace PhysX
};
mutable AZStd::vector<GeometryData> m_geometry;
PhysX::Debug::DebugDisplayDataChangedEvent::Handler m_debugDisplayDataChangedEvent;
};
} // namespace DebugDraw
} // namespace PhysX

@ -23,7 +23,7 @@ ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux
# platform-specific:
ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-android TARGETS freetype PACKAGE_HASH 74dd75382688323c3a2a5090f473840b5d7e9d2aed1a4fcdff05ed2a09a664f2)
ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-android TARGETS tiff PACKAGE_HASH a9b30a1980946390c2fad0ed94562476a1d7ba8c1f36934ae140a89c54a8efd0)
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-android TARGETS AWSNativeSDK PACKAGE_HASH e2192157534cc8c4e22769545d88dff03ec6c1031599716ef63de3ebbb8c9a44)
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-android TARGETS AWSNativeSDK PACKAGE_HASH 9d163696591a836881fc22dac3c94e57b0278771b6c6cec807ff6a5e96f2669d)
ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-android TARGETS Lua PACKAGE_HASH 1f638e94a17a87fe9e588ea456d5893876094b4db191234380e4c4eb9e06c300)
ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-android TARGETS PhysX PACKAGE_HASH b8cb6aa46b2a21671f6cb1f6a78713a3ba88824d0447560ff5ce6c01014b9f43)
ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-android TARGETS mikkelsen PACKAGE_HASH 075e8e4940884971063b5a9963014e2e517246fa269c07c7dc55b8cf2cd99705)

@ -105,12 +105,10 @@ if(@target_file_dir@ MATCHES ".app/Contents/MacOS")
endif()
endif()
if(anything_new)
unset(fixup_bundle_ignore)
# LYN-4505: Patch dxc, is configured in the wrong folder in 3p
if(EXISTS ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
# we copy to not invalidate the copy check from above
file(COPY ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/lib/libdxcompiler.3.7.dylib
DESTINATION ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin
)
list(APPEND fixup_bundle_ignore dxc-3.7)
endif()
# Python.framework being copied by fixup_bundle
#if(EXISTS ${bundle_path}/Contents/Frameworks/Python.framework)
@ -139,8 +137,17 @@ if(@target_file_dir@ MATCHES ".app/Contents/MacOS")
#endif()
list(REMOVE_DUPLICATES plugin_libs)
list(REMOVE_DUPLICATES plugin_dirs)
fixup_bundle("${bundle_path}" "${plugin_libs}" "${plugin_dirs}")
fixup_bundle("${bundle_path}" "${plugin_libs}" "${plugin_dirs}" IGNORE_ITEM ${fixup_bundle_ignore})
file(TOUCH "${bundle_path}")
file(TOUCH "${fixup_timestamp_file}")
# fixup bundle ends up removing the rpath of dxc (despite we exclude it)
if(EXISTS ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
find_program(LY_INSTALL_NAME_TOOL install_name_tool)
if (NOT LY_INSTALL_NAME_TOOL)
message(FATAL_ERROR "Unable to locate 'install_name_tool'")
endif()
execute_process(COMMAND ${LY_INSTALL_NAME_TOOL} -add_rpath @executable_path/../lib ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7)
endif()
endif()
endif()

@ -0,0 +1,68 @@
#
# 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.
#
import sys
import azlmbr
from pathlib import Path
def fixup_current_level(threshold):
nonUniformScaleComponentId = azlmbr.editor.EditorNonUniformScaleComponentTypeId
# iterate over all entities in the level
entityIdList = azlmbr.entity.SearchBus(azlmbr.bus.Broadcast, 'SearchEntities', azlmbr.entity.SearchFilter())
for entityId in entityIdList:
name = azlmbr.editor.EditorEntityInfoRequestBus(azlmbr.bus.Event, 'GetName', entityId)
local = azlmbr.components.TransformBus(azlmbr.bus.Event, 'GetLocalScale', entityId)
# only process entities where the non-uniformity is greater than the threshold
local_max = max(local.x, local.y, local.z)
local_min = min(local.x, local.y, local.z)
if local_max / local_min > 1 + threshold:
# check if there is already a Non-uniform Scale component
getComponentOutcome = azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast, 'GetComponentOfType', entityId, nonUniformScaleComponentId)
if getComponentOutcome.IsSuccess():
print(f"skipping {name} as it already has a Non-uniform Scale component")
else:
# add Non-uniform Scale component and set it to the non-uniform part of the local scale
azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast,'AddComponentsOfType', entityId, [nonUniformScaleComponentId])
vec = azlmbr.math.Vector3(local.x / local_max, local.y / local_max, local.z / local_max)
azlmbr.entity.NonUniformScaleRequestBus(azlmbr.bus.Event, 'SetScale', entityId, vec)
print(f"added non-uniform scale component for {name}: {local.x}, {local.y}, {local.z}")
if __name__ == '__main__':
# handle the arguments manually since argparse causes problems when run through EditorPythonBindings
process_all_levels = "--all" in sys.argv
# ignore entities where the relative difference between the min and max scale values is less than this threshold
threshold = 0.001
for i in range(len(sys.argv) - 1):
if sys.argv[i] == "--threshold":
try:
threshold = float(sys.argv[i + 1])
except ValueError:
print(f"invalid threshold value {sys.argv[i + 1]}, using default value {threshold}")
pass
if process_all_levels:
game_folder = Path(azlmbr.legacy.general.get_game_folder())
level_folder = game_folder / 'Levels'
levels = [str(level) for level in level_folder.rglob('*.ly')] + [str(level) for level in level_folder.rglob('*.cry')]
for level in levels:
if "_savebackup" not in level:
print(f'loading level {level}')
azlmbr.legacy.general.open_level_no_prompt(level)
azlmbr.legacy.general.idle_wait(2.0)
fixup_current_level(threshold)
azlmbr.legacy.general.save_level()
else:
fixup_current_level(threshold)
Loading…
Cancel
Save