Merge branch 'development' into Prism/ShowRepoGems

This commit is contained in:
nggieber
2021-10-22 16:30:02 -07:00
194 changed files with 2843 additions and 607 deletions
+7 -7
View File
@@ -6,10 +6,7 @@
*
*/
#include "EditorDefs.h"
#include "AboutDialog.h"
// Qt
@@ -47,14 +44,17 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice,
CAboutDialog > QLabel#link { text-decoration: underline; color: #94D2FF; }");
// Prepare background image
m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi(
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")),
screen(),
QSize(m_enforcedWidth, m_enforcedHeight),
QPixmap image = AzQtComponents::ScalePixmapForScreenDpi(
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_2021_11.jpg")),
screen(), QSize(m_imageWidth, m_imageHeight),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation
);
// Crop image to cut out transparent border
QRect cropRect((m_imageWidth - m_enforcedWidth) / 2, (m_imageHeight - m_enforcedHeight) / 2, m_enforcedWidth, m_enforcedHeight);
m_backgroundImage = AzQtComponents::CropPixmapForScreenDpi(image, screen(), cropRect);
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
+4 -2
View File
@@ -38,7 +38,9 @@ private:
QScopedPointer<Ui::CAboutDialog> m_ui;
QPixmap m_backgroundImage;
int m_enforcedWidth = 600;
int m_enforcedHeight = 400;
const int m_imageWidth = 668;
const int m_imageHeight = 368;
const int m_enforcedWidth = 600;
const int m_enforcedHeight = 300;
};
+6 -6
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>600</width>
<height>360</height>
<height>300</height>
</rect>
</property>
<property name="sizePolicy">
@@ -19,13 +19,13 @@
<property name="minimumSize">
<size>
<width>600</width>
<height>360</height>
<height>300</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>600</width>
<height>360</height>
<width>608</width>
<height>300</height>
</size>
</property>
<property name="windowTitle">
@@ -69,7 +69,7 @@
<number>11</number>
</property>
<property name="topMargin">
<number>12</number>
<number>10</number>
</property>
<property name="bottomMargin">
<number>12</number>
@@ -125,7 +125,7 @@
</size>
</property>
<property name="text">
<string>Developer Preview</string>
<string>General Availability</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
+3 -2
View File
@@ -34,11 +34,12 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy
m_ui->setupUi(this);
s_pLogoWindow = this;
setFixedSize(QSize(600, 300));
setFixedSize(QSize(m_enforcedWidth, m_enforcedHeight));
setAttribute(Qt::WA_TranslucentBackground, true);
// Prepare background image
m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi(
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")),
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_2021_11.jpg")),
screen(),
QSize(m_enforcedWidth, m_enforcedHeight),
Qt::IgnoreAspectRatio,
+2 -2
View File
@@ -50,7 +50,7 @@ private:
QScopedPointer<Ui::StartupLogoDialog> m_ui;
QPixmap m_backgroundImage;
const int m_enforcedWidth = 600;
const int m_enforcedHeight = 300;
const int m_enforcedWidth = 668;
const int m_enforcedHeight = 368;
};
+1 -1
View File
@@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/StartupLogoDialog">
<file>o3de_logo.svg</file>
<file>splashscreen_background_developer_preview.jpg</file>
<file>splashscreen_background_2021_11.jpg</file>
</qresource>
</RCC>
+26 -9
View File
@@ -6,13 +6,22 @@
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>300</height>
<width>668</width>
<height>368</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>50</number>
</property>
<property name="topMargin">
<number>42</number>
</property>
<property name="rightMargin">
<number>42</number>
</property>
<property name="bottomMargin">
<number>9</number>
<number>42</number>
</property>
<property name="verticalSpacing">
<number>10</number>
@@ -29,7 +38,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>250</width>
<width>300</width>
<height>20</height>
</size>
</property>
@@ -53,7 +62,7 @@
<number>1</number>
</property>
<property name="topMargin">
<number>28</number>
<number>20</number>
</property>
<property name="bottomMargin">
<number>24</number>
@@ -94,7 +103,7 @@
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Developer Preview</string>
<string>General Availability</string>
</property>
</widget>
</item>
@@ -153,20 +162,28 @@
<property name="minimumSize">
<size>
<width>290</width>
<height>0</height>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>290</width>
<height>16777215</height>
<height>32</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>Starting Editor...</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ffcb7614bed0790bf58a2bb7b2d70958289cb2edf562acc8fc841f4c50a55445
size 2974586
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7105ec99477f124a8ac8d588f2dfc4ee7bb54f39386c8131b7703c86754c0cb8
size 248690
@@ -58,6 +58,7 @@
#include <AzFramework/Script/ScriptComponent.h>
#include <AzFramework/Spawnable/SpawnableSystemComponent.h>
#include <AzFramework/StreamingInstall/StreamingInstall.h>
#include <AzFramework/SurfaceData/SurfaceData.h>
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
#include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Metrics/MetricsPlainTextNameRegistration.h>
@@ -278,6 +279,8 @@ namespace AzFramework
AzFramework::RemoteStorageDriveConfig::Reflect(context);
Physics::ReflectionUtils::ReflectPhysicsApi(context);
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
AzFramework::SurfaceData::SurfacePoint::Reflect(context);
AzFramework::Terrain::TerrainDataRequests::Reflect(context);
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
@@ -286,12 +286,17 @@ namespace Physics
return m_type;
}
void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const
const void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const
{
return m_cachedNativeMesh;
}
void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh) const
void* CookedMeshShapeConfiguration::GetCachedNativeMesh()
{
return m_cachedNativeMesh;
}
void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh)
{
m_cachedNativeMesh = cachedNativeMesh;
}
@@ -353,12 +358,17 @@ namespace Physics
return *this;
}
void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() const
const void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() const
{
return m_cachedNativeHeightfield;
}
void HeightfieldShapeConfiguration::SetCachedNativeHeightfield(void* cachedNativeHeightfield) const
void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield()
{
return m_cachedNativeHeightfield;
}
void HeightfieldShapeConfiguration::SetCachedNativeHeightfield(void* cachedNativeHeightfield)
{
if (m_cachedNativeHeightfield)
{
@@ -427,4 +437,5 @@ namespace Physics
{
m_maxHeightBounds = maxBounds;
}
}
} // namespace Physics
@@ -187,8 +187,9 @@ namespace Physics
MeshType GetMeshType() const;
void* GetCachedNativeMesh() const;
void SetCachedNativeMesh(void* cachedNativeMesh) const;
void* GetCachedNativeMesh();
const void* GetCachedNativeMesh() const;
void SetCachedNativeMesh(void* cachedNativeMesh);
private:
void ReleaseCachedNativeMesh();
@@ -197,7 +198,7 @@ namespace Physics
MeshType m_type = MeshType::TriangleMesh;
//! Cached native mesh object (e.g. PxConvexMesh or PxTriangleMesh). This data is not serialized.
mutable void* m_cachedNativeMesh = nullptr;
void* m_cachedNativeMesh = nullptr;
};
class HeightfieldShapeConfiguration
@@ -217,8 +218,9 @@ namespace Physics
return ShapeType::Heightfield;
}
void* GetCachedNativeHeightfield() const;
void SetCachedNativeHeightfield(void* cachedNativeHeightfield) const;
const void* GetCachedNativeHeightfield() const;
void* GetCachedNativeHeightfield();
void SetCachedNativeHeightfield(void* cachedNativeHeightfield);
AZ::Vector2 GetGridResolution() const;
void SetGridResolution(const AZ::Vector2& gridSpacing);
int32_t GetNumColumns() const;
@@ -246,6 +248,6 @@ namespace Physics
//! The grid of sample points for the heightfield.
AZStd::vector<Physics::HeightMaterialPoint> m_samples;
//! An optional storage pointer for the physics system to cache its native heightfield representation.
mutable void* m_cachedNativeHeightfield{ nullptr };
void* m_cachedNativeHeightfield{ nullptr };
};
} // namespace Physics
@@ -0,0 +1,59 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/SurfaceData/SurfaceData.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AzFramework::SurfaceData
{
void SurfaceTagWeight::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SurfaceTagWeight>()
->Field("m_surfaceType", &SurfaceTagWeight::m_surfaceType)
->Field("m_weight", &SurfaceTagWeight::m_weight)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<SurfaceTagWeight>()
->Attribute(AZ::Script::Attributes::Category, "SurfaceData")
->Constructor()
->Property("surfaceType", BehaviorValueProperty(&SurfaceTagWeight::m_surfaceType))
->Property("weight", BehaviorValueProperty(&SurfaceTagWeight::m_weight))
;
}
}
void SurfacePoint::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SurfacePoint>()
->Field("m_position", &SurfacePoint::m_position)
->Field("m_normal", &SurfacePoint::m_normal)
->Field("m_surfaceTags", &SurfacePoint::m_surfaceTags)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<SurfacePoint>("AzFramework::SurfaceData::SurfacePoint")
->Attribute(AZ::Script::Attributes::Category, "SurfaceData")
->Constructor()
->Property("position", BehaviorValueProperty(&SurfacePoint::m_position))
->Property("normal", BehaviorValueProperty(&SurfacePoint::m_normal))
->Property("surfaceTags", BehaviorValueProperty(&SurfacePoint::m_surfaceTags))
;
}
}
} // namespace AzFramework::SurfaceData
@@ -0,0 +1,72 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Math/Crc.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/std/containers/vector.h>
namespace AzFramework::SurfaceData
{
namespace Constants
{
static constexpr const char* s_unassignedTagName = "(unassigned)";
}
struct SurfaceTagWeight
{
AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}");
SurfaceTagWeight() = default;
SurfaceTagWeight(AZ::Crc32 surfaceType, float weight)
: m_surfaceType(surfaceType)
, m_weight(weight)
{
}
AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName);
float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f]
static void Reflect(AZ::ReflectContext* context);
};
struct SurfaceTagWeightComparator
{
bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const
{
// Return a deterministic sort order for surface tags from highest to lowest weight, with the surface types sorted
// in a predictable order when the weights are equal. The surface type sort order is meaningless since it is sorting CRC
// values, it's really just important for it to be stable.
// For the floating-point weight comparisons we use exact instead of IsClose value comparisons for a similar reason - we
// care about being sorted highest to lowest, but there's no inherent meaning in sorting surface types with *similar* weights
// together.
if (tagWeight1.m_weight != tagWeight2.m_weight)
{
return tagWeight1.m_weight > tagWeight2.m_weight;
}
else
{
return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType;
}
}
};
using SurfaceTagWeightList = AZStd::vector<SurfaceTagWeight>;
struct SurfacePoint final
{
AZ_TYPE_INFO(SurfacePoint, "{331A3D0E-BB1D-47BF-96A2-249FAA0D720D}");
AZ::Vector3 m_position;
AZ::Vector3 m_normal;
SurfaceTagWeightList m_surfaceTags;
static void Reflect(AZ::ReflectContext* context);
};
} // namespace AzFramework::SurfaceData
@@ -8,56 +8,33 @@
#include "TerrainDataRequestBus.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AzFramework
namespace AzFramework::Terrain
{
namespace SurfaceData
void TerrainDataRequests::Reflect(AZ::ReflectContext* context)
{
void SurfaceTagWeight::Reflect(AZ::ReflectContext* context)
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SurfaceTagWeight>()
->Field("m_surfaceType", &SurfaceTagWeight::m_surfaceType)
->Field("m_weight", &SurfaceTagWeight::m_weight)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<SurfaceTagWeight>("SurfaceTagWeight")
->Property("m_surfaceType", BehaviorValueProperty(&SurfaceTagWeight::m_surfaceType))
->Property("m_weight", BehaviorValueProperty(&SurfaceTagWeight::m_weight))
;
}
}
} //namespace SurfaceData
namespace Terrain
{
void TerrainDataRequests::Reflect(AZ::ReflectContext* context)
{
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<AzFramework::Terrain::TerrainDataRequestBus>("TerrainDataRequestBus")
->Attribute(AZ::Script::Attributes::Category, "Terrain")
->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeight)
->Event("GetHeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeightFromFloats)
->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight)
->Event("GetMaxSurfaceWeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromFloats)
->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats)
->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal)
->Event("GetNormalFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormalFromFloats)
->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb)
->Event("GetTerrainHeightQueryResolution",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution)
;
}
behaviorContext->EBus<AzFramework::Terrain::TerrainDataRequestBus>("TerrainDataRequestBus")
->Attribute(AZ::Script::Attributes::Category, "Terrain")
->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeight)
->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal)
->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight)
->Event("GetMaxSurfaceWeightFromVector2",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromVector2)
->Event("GetSurfaceWeights", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeights)
->Event("GetSurfaceWeightsFromVector2",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeightsFromVector2)
->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats)
->Event("GetSurfacePoint", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePoint)
->Event("GetSurfacePointFromVector2",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePointFromVector2)
->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb)
->Event("GetTerrainHeightQueryResolution",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution)
;
}
} //namespace Terrain
} // namespace AzFramework
}
} // namespace AzFramework::Terrain
@@ -8,50 +8,13 @@
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Aabb.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzFramework/SurfaceData/SurfaceData.h>
namespace AzFramework
{
namespace SurfaceData
{
namespace Constants
{
static const char* s_unassignedTagName = "(unassigned)";
}
struct SurfaceTagWeight
{
AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}");
AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName);
float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f]
//! Don't call this directly. TerrainDataRequests::Reflect is doing it already.
static void Reflect(AZ::ReflectContext* context);
};
struct SurfaceTagWeightComparator
{
bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const
{
if (!AZ::IsClose(tagWeight1.m_weight, tagWeight2.m_weight))
{
return tagWeight1.m_weight > tagWeight2.m_weight;
}
else
{
return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType;
}
}
};
using OrderedSurfaceTagWeightSet = AZStd::set<SurfaceTagWeight, SurfaceTagWeightComparator>;
} //namespace SurfaceData
namespace Terrain
{
@@ -91,49 +54,82 @@ namespace AzFramework
//! Returns terrains height in meters at location x,y.
//! @terrainExistsPtr: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will become false,
//! otherwise *terrainExistsPtr will become true.
virtual float GetHeight(AZ::Vector3 position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual float GetHeightFromFloats(float x, float y, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual float GetHeight(const AZ::Vector3& position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual float GetHeightFromVector2(
const AZ::Vector2& position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual float GetHeightFromFloats(
float x, float y, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Returns true if there's a hole at location x,y.
//! Also returns true if there's no terrain data at location x,y.
virtual bool GetIsHole(const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR) const = 0;
virtual bool GetIsHoleFromVector2(const AZ::Vector2& position, Sampler sampleFilter = Sampler::BILINEAR) const = 0;
virtual bool GetIsHoleFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR) const = 0;
// Given an XY coordinate, return the surface normal.
//! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a
//! terrain HOLE then *terrainExistsPtr will be set to false,
//! otherwise *terrainExistsPtr will be set to true.
virtual AZ::Vector3 GetNormal(
const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual AZ::Vector3 GetNormalFromVector2(
const AZ::Vector2& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual AZ::Vector3 GetNormalFromFloats(
float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Given an XY coordinate, return the max surface type and weight.
//! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false,
//! otherwise *terrainExistsPtr will be set to true.
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2(const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0;
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(
const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2(
const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0;
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(
float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Given an XY coordinate, return the set of surface types and weights. The Vector3 input position version is defined to ignore
//! the input Z value.
virtual void GetSurfaceWeights(
const AZ::Vector3& inPosition,
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
SurfaceData::SurfaceTagWeightList& outSurfaceWeights,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
virtual void GetSurfaceWeightsFromVector2(
const AZ::Vector2& inPosition,
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
SurfaceData::SurfaceTagWeightList& outSurfaceWeights,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
virtual void GetSurfaceWeightsFromFloats(
float x,
float y,
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
SurfaceData::SurfaceTagWeightList& outSurfaceWeights,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
//! Convenience function for low level systems that can't do a reverse lookup from Crc to string. Everyone else should use GetMaxSurfaceWeight or GetMaxSurfaceWeightFromFloats.
//! Not available in the behavior context.
//! Returns nullptr if the position is inside a hole or outside of the terrain boundaries.
virtual const char * GetMaxSurfaceName(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual const char* GetMaxSurfaceName(
const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Returns true if there's a hole at location x,y.
//! Also returns true if there's no terrain data at location x,y.
virtual bool GetIsHoleFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR) const = 0;
// Given an XY coordinate, return the surface normal.
//! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false,
//! otherwise *terrainExistsPtr will be set to true.
virtual AZ::Vector3 GetNormal(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual AZ::Vector3 GetNormalFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Given an XY coordinate, return all terrain information at that location. The Vector3 input position version is defined
//! to ignore the input Z value.
virtual void GetSurfacePoint(
const AZ::Vector3& inPosition,
SurfaceData::SurfacePoint& outSurfacePoint,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
virtual void GetSurfacePointFromVector2(
const AZ::Vector2& inPosition,
SurfaceData::SurfacePoint& outSurfacePoint,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
virtual void GetSurfacePointFromFloats(
float x,
float y,
SurfaceData::SurfacePoint& outSurfacePoint,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
};
using TerrainDataRequestBus = AZ::EBus<TerrainDataRequests>;
@@ -169,6 +165,10 @@ namespace AzFramework
}
};
using TerrainDataNotificationBus = AZ::EBus<TerrainDataNotifications>;
} //namespace Terrain
} // namespace Terrain
} // namespace AzFramework
namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(AzFramework::Terrain::TerrainDataRequests::Sampler, "{D29BB6D7-3006-4114-858D-355EAA256B86}");
} // namespace AZ
@@ -252,7 +252,6 @@ set(FILES
Physics/Shape.h
Physics/ShapeConfiguration.h
Physics/ShapeConfiguration.cpp
Physics/HeightfieldProviderBus.h
Physics/SystemBus.h
Physics/ColliderComponentBus.h
Physics/RagdollPhysicsBus.h
@@ -301,6 +300,8 @@ set(FILES
Spawnable/SpawnableMonitor.cpp
Spawnable/SpawnableSystemComponent.h
Spawnable/SpawnableSystemComponent.cpp
SurfaceData/SurfaceData.h
SurfaceData/SurfaceData.cpp
Terrain/TerrainDataRequestBus.h
Terrain/TerrainDataRequestBus.cpp
Thermal/ThermalInfo.h
@@ -28,4 +28,21 @@ namespace AzQtComponents
return scaledPixmap;
}
QPixmap CropPixmapForScreenDpi(
QPixmap pixmap, QScreen* screen, QRect rect)
{
qreal screenDpiFactor = QHighDpiScaling::factor(screen);
pixmap.setDevicePixelRatio(screenDpiFactor);
QRect cropRect(
aznumeric_cast<int>(aznumeric_cast<qreal>(rect.left()) * screenDpiFactor),
aznumeric_cast<int>(aznumeric_cast<qreal>(rect.top()) * screenDpiFactor),
aznumeric_cast<int>(aznumeric_cast<qreal>(rect.width()) * screenDpiFactor),
aznumeric_cast<int>(aznumeric_cast<qreal>(rect.height()) * screenDpiFactor)
);
QPixmap croppedPixmap = pixmap.copy(cropRect);
return croppedPixmap;
}
}
@@ -11,9 +11,11 @@
#include <AzQtComponents/AzQtComponentsAPI.h>
#include <QPixmap>
#include <QRect>
#include <QScreen>
namespace AzQtComponents
{
AZ_QT_COMPONENTS_API QPixmap ScalePixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QSize size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode);
AZ_QT_COMPONENTS_API QPixmap CropPixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QRect rect);
}; // namespace AzQtComponents
@@ -36,6 +36,10 @@ namespace AzToolsFramework
//! the entity type.
virtual AZStd::vector<AZ::Uuid> FindComponentTypeIdsByEntityType(const AZStd::vector<AZStd::string>& componentTypeNames, EntityType entityType) = 0;
//! Return a list of type ids for components that match the required services filter,
//! and don't conflict with any of the incompatible services filter
virtual AZStd::vector<AZ::Uuid> FindComponentTypeIdsByService(const AZStd::vector<AZ::ComponentServiceType>& serviceFilter, const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter) = 0;
//! Finds the component names from their type ids
virtual AZStd::vector<AZStd::string> FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) = 0;
@@ -15,6 +15,7 @@
#include <AzToolsFramework/ToolsComponents/EditorDisabledCompositionBus.h>
#include <AzToolsFramework/ToolsComponents/EditorPendingCompositionBus.h>
#include <AzToolsFramework/Entity/EditorEntityActionComponent.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
@@ -75,6 +76,7 @@ namespace AzToolsFramework
serializeContext->Class<EditorComponentAPIComponent, AZ::Component>();
serializeContext->RegisterGenericType<AZStd::vector<AZ::EntityComponentIdPair>>();
serializeContext->RegisterGenericType<AZStd::vector<AZ::ComponentServiceType>>();
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
@@ -99,6 +101,7 @@ namespace AzToolsFramework
->Attribute(AZ::Script::Attributes::Module, "editor")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("FindComponentTypeIdsByEntityType", &EditorComponentAPIRequests::FindComponentTypeIdsByEntityType)
->Event("FindComponentTypeIdsByService", &EditorComponentAPIRequests::FindComponentTypeIdsByService)
->Event("FindComponentTypeNames", &EditorComponentAPIRequests::FindComponentTypeNames)
->Event("BuildComponentTypeNameListByEntityType", &EditorComponentAPIRequests::BuildComponentTypeNameListByEntityType)
->Event("AddComponentsOfType", &EditorComponentAPIRequests::AddComponentsOfType)
@@ -216,6 +219,33 @@ namespace AzToolsFramework
return foundTypeIds;
}
AZStd::vector<AZ::Uuid> EditorComponentAPIComponent::FindComponentTypeIdsByService(const AZStd::vector<AZ::ComponentServiceType>& serviceFilter, const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter)
{
AZStd::vector<AZ::Uuid> foundTypeIds;
m_serializeContext->EnumerateDerived<AZ::Component>(
[&foundTypeIds, serviceFilter, incompatibleServiceFilter](const AZ::SerializeContext::ClassData* componentClass, const AZ::Uuid& knownType) -> bool
{
AZ_UNUSED(knownType);
if (componentClass->m_editData)
{
// If none of the required services are offered by this component, or the component
// can not be added by the user, skip to the next component
if (!OffersRequiredServices(componentClass, serviceFilter, incompatibleServiceFilter))
{
return true;
}
foundTypeIds.push_back(componentClass->m_typeId);
}
return true;
});
return foundTypeIds;
}
AZStd::vector<AZStd::string> EditorComponentAPIComponent::FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds)
{
AZStd::vector<AZStd::string> foundTypeNames;
@@ -35,6 +35,7 @@ namespace AzToolsFramework
// EditorComponentAPIBus ...
AZStd::vector<AZ::Uuid> FindComponentTypeIdsByEntityType(const AZStd::vector<AZStd::string>& componentTypeNames, EditorComponentAPIRequests::EntityType entityType) override;
AZStd::vector<AZ::Uuid> FindComponentTypeIdsByService(const AZStd::vector<AZ::ComponentServiceType>& serviceFilter, const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter) override;
AZStd::vector<AZStd::string> FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) override;
AZStd::vector<AZStd::string> BuildComponentTypeNameListByEntityType(EditorComponentAPIRequests::EntityType entityType) override;
@@ -271,6 +271,68 @@ namespace AzToolsFramework
return editorComponentBaseComponent;
}
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter,
const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter
)
{
AZ_Assert(componentClass, "Component class must not be null");
if (!componentClass)
{
return false;
}
AZ::ComponentDescriptor* componentDescriptor = nullptr;
AZ::ComponentDescriptorBus::EventResult(
componentDescriptor, componentClass->m_typeId, &AZ::ComponentDescriptor::GetDescriptor);
if (!componentDescriptor)
{
return false;
}
// If no services are provided, this function returns true
if (serviceFilter.empty())
{
return true;
}
AZ::ComponentDescriptor::DependencyArrayType providedServices;
componentDescriptor->GetProvidedServices(providedServices, nullptr);
//reject this component if it does not offer any of the required services
if (AZStd::find_first_of(
providedServices.begin(),
providedServices.end(),
serviceFilter.begin(),
serviceFilter.end()) == providedServices.end())
{
return false;
}
//reject this component if it does offer any of the incompatible services
if (AZStd::find_first_of(
providedServices.begin(),
providedServices.end(),
incompatibleServiceFilter.begin(),
incompatibleServiceFilter.end()) != providedServices.end())
{
return false;
}
return true;
}
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter
)
{
const AZStd::vector<AZ::ComponentServiceType> incompatibleServices;
return OffersRequiredServices(componentClass, serviceFilter, incompatibleServices);
}
bool ShouldInspectorShowComponent(const AZ::Component* component)
{
if (!component)
@@ -105,6 +105,16 @@ namespace AzToolsFramework
AZ::ComponentDescriptor* GetComponentDescriptor(const AZ::Component* component);
Components::EditorComponentDescriptor* GetEditorComponentDescriptor(const AZ::Component* component);
Components::EditorComponentBase* GetEditorComponent(AZ::Component* component);
// Returns true if the given component provides at least one of the services specified or no services are provided
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter,
const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter
);
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter
);
/// Return true if the editor should show this component to users,
/// false if the component should be hidden from users.
@@ -16,6 +16,7 @@
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusNotificationBus.h>
#include <AzToolsFramework/Prefab/PrefabFocusUndo.h>
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
namespace AzToolsFramework::Prefab
{
@@ -79,7 +80,7 @@ namespace AzToolsFramework::Prefab
auto editUndo = aznew PrefabFocusUndo("Edit Prefab");
editUndo->Capture(entityId);
editUndo->SetParent(undoBatch.GetUndoBatch());
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, editUndo);
FocusOnPrefabInstanceOwningEntityId(entityId);
}
return AZ::Success();
@@ -94,9 +95,7 @@ namespace AzToolsFramework::Prefab
InstanceOptionalReference focusedInstance = m_instanceFocusHierarchy[index];
FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId());
return AZ::Success();
return FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId());
}
PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId)
@@ -255,7 +254,7 @@ namespace AzToolsFramework::Prefab
void PrefabFocusHandler::OnEntityInfoUpdatedName(AZ::EntityId entityId, [[maybe_unused]]const AZStd::string& name)
{
// Determine if the entityId is the container for any of the instances in the vector
// Determine if the entityId is the container for any of the instances in the vector.
auto result = AZStd::find_if(
m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(),
[entityId](const InstanceOptionalReference& instance)
@@ -279,6 +278,25 @@ namespace AzToolsFramework::Prefab
PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged);
}
void PrefabFocusHandler::OnPrefabTemplateDirtyFlagUpdated(TemplateId templateId, [[maybe_unused]] bool status)
{
// Determine if the templateId matches any of the instances in the vector.
auto result = AZStd::find_if(
m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(),
[templateId](const InstanceOptionalReference& instance)
{
return (instance->get().GetTemplateId() == templateId);
}
);
if (result != m_instanceFocusHierarchy.end())
{
// Refresh the path and notify changes.
RefreshInstanceFocusPath();
PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged);
}
}
void PrefabFocusHandler::RefreshInstanceFocusList()
{
m_instanceFocusHierarchy.clear();
@@ -293,17 +311,42 @@ namespace AzToolsFramework::Prefab
currentInstance = currentInstance->get().GetParentInstance();
}
// Invert the vector, since we need the top instance to be at index 0
// Invert the vector, since we need the top instance to be at index 0.
AZStd::reverse(m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end());
}
void PrefabFocusHandler::RefreshInstanceFocusPath()
{
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
m_instanceFocusPath.clear();
size_t index = 0;
size_t maxIndex = m_instanceFocusHierarchy.size() - 1;
for (const InstanceOptionalReference& instance : m_instanceFocusHierarchy)
{
m_instanceFocusPath.Append(instance->get().GetContainerEntity()->get().GetName());
AZStd::string prefabName;
if (index < maxIndex)
{
// Get the filename without the extension (stem).
prefabName = instance->get().GetTemplateSourcePath().Stem().Native();
}
else
{
// Get the full filename.
prefabName = instance->get().GetTemplateSourcePath().Filename().Native();
}
if (prefabSystemComponentInterface->IsTemplateDirty(instance->get().GetTemplateId()))
{
prefabName += "*";
}
m_instanceFocusPath.Append(prefabName);
++index;
}
}
@@ -64,8 +64,9 @@ namespace AzToolsFramework::Prefab
void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& name) override;
// PrefabPublicNotifications overrides ...
void OnPrefabInstancePropagationEnd();
void OnPrefabInstancePropagationEnd() override;
void OnPrefabTemplateDirtyFlagUpdated(TemplateId templateId, bool status) override;
private:
PrefabFocusOperationResult FocusOnPrefabInstance(InstanceOptionalReference focusedInstance);
void RefreshInstanceFocusList();
@@ -9,6 +9,7 @@
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzToolsFramework/Prefab/PrefabIdTypes.h>
namespace AzToolsFramework
{
@@ -22,6 +23,9 @@ namespace AzToolsFramework
virtual void OnPrefabInstancePropagationBegin() {}
virtual void OnPrefabInstancePropagationEnd() {}
virtual void OnPrefabTemplateDirtyFlagUpdated(
[[maybe_unused]] TemplateId templateId, [[maybe_unused]] bool status) {}
};
using PrefabPublicNotificationBus = AZ::EBus<PrefabPublicNotifications>;
@@ -185,7 +185,7 @@ namespace AzToolsFramework
if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal)
{
templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator());
templateToUpdate->get().MarkAsDirty(true);
SetTemplateDirtyFlag(templateId, true);
PropagateTemplateChanges(templateId);
}
}
@@ -813,11 +813,12 @@ namespace AzToolsFramework
void PrefabSystemComponent::SetTemplateDirtyFlag(TemplateId templateId, bool dirty)
{
auto templateRef = FindTemplate(templateId);
if (templateRef.has_value())
if (auto templateReference = FindTemplate(templateId); templateReference.has_value())
{
templateRef->get().MarkAsDirty(dirty);
templateReference->get().MarkAsDirty(dirty);
PrefabPublicNotificationBus::Broadcast(
&PrefabPublicNotificationBus::Events::OnPrefabTemplateDirtyFlagUpdated, templateId, dirty);
}
}
@@ -12,6 +12,7 @@
#include <AzCore/Component/Component.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags<Qt::AlignmentFlag>' needs to have dll-interface to be used by clients of class 'QLayoutItem'
#include <AzToolsFramework/UI/SearchWidget/SearchCriteriaWidget.hxx>
AZ_POP_DISABLE_WARNING
@@ -20,67 +21,6 @@ namespace AzToolsFramework
{
namespace ComponentPaletteUtil
{
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter,
const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter
)
{
AZ_Assert(componentClass, "Component class must not be null");
if (!componentClass)
{
return false;
}
AZ::ComponentDescriptor* componentDescriptor = nullptr;
EBUS_EVENT_ID_RESULT(componentDescriptor, componentClass->m_typeId, AZ::ComponentDescriptorBus, GetDescriptor);
if (!componentDescriptor)
{
return false;
}
// If no services are provided, this function returns true
if (serviceFilter.empty())
{
return true;
}
AZ::ComponentDescriptor::DependencyArrayType providedServices;
componentDescriptor->GetProvidedServices(providedServices, nullptr);
//reject this component if it does not offer any of the required services
if (AZStd::find_first_of(
providedServices.begin(),
providedServices.end(),
serviceFilter.begin(),
serviceFilter.end()) == providedServices.end())
{
return false;
}
//reject this component if it does offer any of the incompatible services
if (AZStd::find_first_of(
providedServices.begin(),
providedServices.end(),
incompatibleServiceFilter.begin(),
incompatibleServiceFilter.end()) != providedServices.end())
{
return false;
}
return true;
}
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter
)
{
const AZStd::vector<AZ::ComponentServiceType> incompatibleServices;
return OffersRequiredServices(componentClass, serviceFilter, incompatibleServices);
}
bool IsAddableByUser(const AZ::SerializeContext::ClassData* componentClass)
{
AZ_Assert(componentClass, "component class must not be null");
@@ -26,18 +26,6 @@ namespace AzToolsFramework
using ComponentIconTable = AZStd::map<const AZ::SerializeContext::ClassData*, QString>;
// Returns true if the given component provides at least one of the services specified or no services are provided
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter,
const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter
);
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter
);
// Returns true if the given component is addable by the user
bool IsAddableByUser(const AZ::SerializeContext::ClassData* componentClass);
@@ -10,6 +10,8 @@
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <QTimer>
namespace AzToolsFramework::Prefab
{
PrefabViewportFocusPathHandler::PrefabViewportFocusPathHandler()
@@ -47,6 +49,9 @@ namespace AzToolsFramework::Prefab
[&](const QString&, int linkIndex)
{
m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex);
// Manually refresh path
QTimer::singleShot(0, [&]() { OnPrefabFocusChanged(); });
}
);
@@ -22,6 +22,7 @@
#include <AzToolsFramework/Application/ToolsApplication.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/UnitTest/ToolsTestApplication.h>
// Inspector Test Includes
@@ -313,17 +314,17 @@ namespace UnitTest
AZ_TEST_ASSERT(testComponent1_ProvidedServices.size() == 1);
const AZ::SerializeContext::ClassData* testComponent1_ClassData = context->FindClassData(testComponent1_typeId);
EXPECT_TRUE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, testComponent1_ProvidedServices));
EXPECT_TRUE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, testComponent1_ProvidedServices));
// Verify that OffersRequiredServices returns when given services provided by a different component
AZ::ComponentDescriptor::DependencyArrayType testComponent2_ProvidedServices;
Inspector_TestComponent2::GetProvidedServices(testComponent2_ProvidedServices);
AZ_TEST_ASSERT(testComponent2_ProvidedServices.size() == 1);
AZ_TEST_ASSERT(testComponent1_ProvidedServices != testComponent2_ProvidedServices);
EXPECT_FALSE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, testComponent2_ProvidedServices));
EXPECT_FALSE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, testComponent2_ProvidedServices));
// verify that OffersRequiredServices returns true when provided with an empty list of services
EXPECT_TRUE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, AZ::ComponentDescriptor::DependencyArrayType()));
EXPECT_TRUE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, AZ::ComponentDescriptor::DependencyArrayType()));
//////////////////////////////////////////////////////////////////////////
// TEST IsAddableByUser()
@@ -8,10 +8,12 @@
#include <DownloadController.h>
#include <DownloadWorker.h>
#include <PythonBindings.h>
#include <AzCore/std/algorithm.h>
#include <QMessageBox>
namespace O3DE::ProjectManager
{
DownloadController::DownloadController(QWidget* parent)
@@ -46,6 +48,24 @@ namespace O3DE::ProjectManager
}
}
void DownloadController::CancelGemDownload(const QString& gemName)
{
auto findResult = AZStd::find(m_gemNames.begin(), m_gemNames.end(), gemName);
if (findResult != m_gemNames.end())
{
if (findResult == m_gemNames.begin())
{
// HandleResults will remove the gem upon cancelling
PythonBindingsInterface::Get()->CancelDownload();
}
else
{
m_gemNames.erase(findResult);
}
}
}
void DownloadController::UpdateUIProgress(int progress)
{
m_lastProgress = progress;
@@ -75,10 +95,4 @@ namespace O3DE::ProjectManager
m_workerThread.wait();
}
}
void DownloadController::HandleCancel()
{
m_workerThread.quit();
emit Done(false);
}
} // namespace O3DE::ProjectManager
@@ -27,7 +27,8 @@ namespace O3DE::ProjectManager
explicit DownloadController(QWidget* parent = nullptr);
~DownloadController();
void AddGemDownload(const QString& m_gemName);
void AddGemDownload(const QString& gemName);
void CancelGemDownload(const QString& gemName);
bool IsDownloadQueueEmpty()
{
@@ -54,7 +55,6 @@ namespace O3DE::ProjectManager
public slots:
void UpdateUIProgress(int progress);
void HandleResults(const QString& result);
void HandleCancel();
signals:
void StartGemDownload(const QString& gemName);
@@ -155,6 +155,11 @@ namespace O3DE::ProjectManager
update();
}
void CartOverlayWidget::OnCancelDownloadActivated(const QString& gemName)
{
m_downloadController->CancelGemDownload(gemName);
}
void CartOverlayWidget::CreateDownloadSection()
{
QWidget* widget = new QWidget();
@@ -235,7 +240,9 @@ namespace O3DE::ProjectManager
nameProgressLayout->addWidget(progress);
QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
nameProgressLayout->addSpacerItem(spacer);
QLabel* cancelText = new QLabel(tr("Cancel"));
QLabel* cancelText = new QLabel(QString("<a href=\"%1\">Cancel</a>").arg(downloadQueue[downloadingGemNumber]));
cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated);
nameProgressLayout->addWidget(cancelText);
downloadingItemLayout->addLayout(nameProgressLayout);
QProgressBar* downloadProgessBar = new QProgressBar();
@@ -41,6 +41,7 @@ namespace O3DE::ProjectManager
using GetTagIndicesCallback = AZStd::function<QVector<QModelIndex>()>;
void CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices);
void CreateDownloadSection();
void OnCancelDownloadActivated(const QString& link);
QVBoxLayout* m_layout = nullptr;
GemModel* m_gemModel = nullptr;
@@ -223,6 +223,7 @@ namespace RedirectOutput
}
} // namespace RedirectOutput
namespace O3DE::ProjectManager
{
PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath)
@@ -1125,18 +1126,29 @@ namespace O3DE::ProjectManager
AZ::Outcome<void, AZStd::string> PythonBindings::DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback)
{
// This process is currently limited to download a single gem at a time.
bool downloadSucceeded = false;
m_requestCancelDownload = false;
auto result = ExecuteWithLockErrorHandling(
[&]
{
auto downloadResult = m_download.attr("download_gem")(
QString_To_Py_String(gemName), // gem name
pybind11::none(), // destination path
false// skip auto register
false, // skip auto register
pybind11::cpp_function(
[this, gemProgressCallback](int progress)
{
gemProgressCallback(progress);
return m_requestCancelDownload;
}) // Callback for download progress and cancelling
);
downloadSucceeded = (downloadResult.cast<int>() == 0);
});
if (!result.IsSuccess())
{
return result;
@@ -1149,6 +1161,11 @@ namespace O3DE::ProjectManager
return AZ::Success();
}
void PythonBindings::CancelDownload()
{
m_requestCancelDownload = true;
}
AZ::Outcome<QVector<GemInfo>, AZStd::string> PythonBindings::GetAllGemRepoGemsInfos()
{
QVector<GemInfo> gemInfos;
@@ -63,6 +63,7 @@ namespace O3DE::ProjectManager
bool RemoveGemRepo(const QString& repoUri) override;
AZ::Outcome<QVector<GemRepoInfo>, AZStd::string> GetAllGemRepoInfos() override;
AZ::Outcome<void, AZStd::string> DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback) override;
void CancelDownload() override;
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemRepoGemsInfos() override;
private:
@@ -93,5 +94,7 @@ namespace O3DE::ProjectManager
pybind11::handle m_download;
pybind11::handle m_repo;
pybind11::handle m_pathlib;
bool m_requestCancelDownload = false;
};
}
@@ -196,8 +196,19 @@ namespace O3DE::ProjectManager
*/
virtual AZ::Outcome<QVector<GemRepoInfo>, AZStd::string> GetAllGemRepoInfos() = 0;
/**
* Downloads and registers a Gem.
* @param gemName the name of the Gem to download
* @param gemProgressCallback a callback function that is called with an int percentage download value
* @return an outcome with a string error message on failure.
*/
virtual AZ::Outcome<void, AZStd::string> DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback) = 0;
/**
* Cancels the current download.
*/
virtual void CancelDownload() = 0;
/**
* Gathers all gem infos for all gems registered from repos.
* @return A list of gem infos.