merge stabilization/2106 into development

Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
hultonha
2021-07-06 17:34:04 +01:00
377 changed files with 6549 additions and 9214 deletions
@@ -22,7 +22,7 @@ namespace AWSClientAuth
virtual ~AWSCognitoAuthenticationProvider() = default;
// AuthenticationProviderInterface overrides
bool Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry) override;
bool Initialize() override;
void PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode) override;
@@ -22,9 +22,8 @@ namespace AWSClientAuth
virtual ~AuthenticationProviderInterface() = default;
//! Extract required settings for the provider from setting registry.
//! @param settingsRegistry Passed in initialized settings registry object.
//! @return bool True: if provider can parse required settings and validate. False: fails to parse required settings.
virtual bool Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry) = 0;
virtual bool Initialize() = 0;
//! Call sign in endpoint for provider password grant flow.
//! @param username Username to use to for sign in.
@@ -29,7 +29,7 @@ namespace AWSClientAuth
protected:
// AuthenticationProviderRequestsBus Interface
bool Initialize(const AZStd::vector<ProviderNameEnum>& providerNames, const AZStd::string& settingsRegistryPath) override;
bool Initialize(const AZStd::vector<ProviderNameEnum>& providerNames) override;
void PasswordGrantSingleFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) override;
@@ -42,7 +42,7 @@ namespace AWSClientAuth
AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) override;
// AuthenticationProviderScriptCanvasRequest interface
bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) override;
bool Initialize(const AZStd::vector<AZStd::string>& providerNames) override;
void PasswordGrantSingleFactorSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(
@@ -64,8 +64,6 @@ namespace AWSClientAuth
bool IsProviderInitialized(const ProviderNameEnum& providerName);
void ResetProviders();
ProviderNameEnum GetProviderNameEnum(AZStd::string name);
AZStd::shared_ptr<AZ::SettingsRegistryInterface> m_settingsRegistry;
};
} // namespace AWSClientAuth
@@ -20,9 +20,8 @@ namespace AWSClientAuth
//! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers
//! @param providerNames List of provider names to instantiate and initialize for Authentication.
//! @param settingsRegistryPath Path for the settings registry file to use to configure providers.
//! @return bool True: if all providers initialized successfully. False: If any provider fails initialization.
virtual bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) = 0;
virtual bool Initialize(const AZStd::vector<AZStd::string>& providerNames) = 0;
//! Checks if user is signed in.
//! If access tokens are available and not expired.
@@ -21,7 +21,7 @@ namespace AWSClientAuth
virtual ~GoogleAuthenticationProvider();
// AuthenticationProviderInterface overrides
bool Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry) override;
bool Initialize() override;
void PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode) override;
@@ -21,7 +21,7 @@ namespace AWSClientAuth
virtual ~LWAAuthenticationProvider();
// AuthenticationProviderInterface overrides
bool Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry) override;
bool Initialize() override;
void PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode) override;
@@ -19,9 +19,8 @@ namespace AWSClientAuth
//! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers
//! @param providerNames List of provider names to instantiate and initialize for Authentication.
//! @param settingsRegistryPath Path for the settings registry file to use to configure providers.
//! @return bool True: if all providers initialized successfully. False: If any provider fails initialization.
virtual bool Initialize(const AZStd::vector<ProviderNameEnum>& providerNames, const AZStd::string& settingsRegistryPath) = 0;
virtual bool Initialize(const AZStd::vector<ProviderNameEnum>& providerNames) = 0;
//! Checks if user is signed in.
//! If access tokens are available and not expired.
@@ -30,9 +30,8 @@ namespace AWSClientAuth
constexpr char CognitoRefreshTokenAuthParamKey[] = "REFRESH_TOKEN";
constexpr char CognitoSmsMfaCodeKey[] = "SMS_MFA_CODE";
bool AWSCognitoAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
bool AWSCognitoAuthenticationProvider::Initialize()
{
AZ_UNUSED(settingsRegistry);
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(
m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey);
AZ_Warning("AWSCognitoAuthenticationProvider", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail.");
@@ -6,7 +6,6 @@
*/
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/IO/FileIO.h>
#include <Authentication/AuthenticationProviderTypes.h>
@@ -27,37 +26,21 @@ namespace AWSClientAuth
AuthenticationProviderManager::~AuthenticationProviderManager()
{
ResetProviders();
m_settingsRegistry.reset();
AuthenticationProviderScriptCanvasRequestBus::Handler::BusDisconnect();
AuthenticationProviderRequestBus::Handler::BusDisconnect();
AZ::Interface<IAuthenticationProviderRequests>::Unregister(this);
}
bool AuthenticationProviderManager::Initialize(const AZStd::vector<ProviderNameEnum>& providerNames, const AZStd::string& settingsRegistryPath)
bool AuthenticationProviderManager::Initialize(const AZStd::vector<ProviderNameEnum>& providerNames)
{
ResetProviders();
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
AZ_Assert(fileIO, "File IO is not initialized.");
m_settingsRegistry.reset();
m_settingsRegistry = AZStd::make_shared<AZ::SettingsRegistryImpl>();
AZStd::array<char, AZ::IO::MaxPathLength> resolvedPath{};
fileIO->ResolvePath(settingsRegistryPath.data(), resolvedPath.data(), resolvedPath.size());
if (!m_settingsRegistry->MergeSettingsFile(resolvedPath.data(), AZ::SettingsRegistryInterface::Format::JsonMergePatch))
{
AZ_Error("AuthenticationProviderManager", false, "Error merging settings registry for path: %s", resolvedPath.data());
return false;
}
bool initializeSuccess = true;
for (auto providerName : providerNames)
{
m_authenticationProvidersMap[providerName] = CreateAuthenticationProviderObject(providerName);
initializeSuccess = initializeSuccess && m_authenticationProvidersMap[providerName]->Initialize(m_settingsRegistry);
initializeSuccess = initializeSuccess && m_authenticationProvidersMap[providerName]->Initialize();
}
return initializeSuccess;
@@ -199,14 +182,14 @@ namespace AWSClientAuth
}
bool AuthenticationProviderManager::Initialize(
const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath)
const AZStd::vector<AZStd::string>& providerNames)
{
AZStd::vector<ProviderNameEnum> providerNamesEnum;
for (auto name : providerNames)
{
providerNamesEnum.push_back(GetProviderNameEnum(name));
}
return Initialize(providerNamesEnum, settingsRegistryPath);
return Initialize(providerNamesEnum);
}
void AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password)
@@ -30,9 +30,16 @@ namespace AWSClientAuth
m_settings.reset();
}
bool GoogleAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
bool GoogleAuthenticationProvider::Initialize()
{
if (!settingsRegistry.lock()->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), GoogleSettingsPath))
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to load the setting registry");
return false;
}
if (!settingsRegistry->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), GoogleSettingsPath))
{
AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to get Google settings object for path %s", GoogleSettingsPath);
return false;
@@ -29,9 +29,16 @@ namespace AWSClientAuth
m_settings.reset();
}
bool LWAAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
bool LWAAuthenticationProvider::Initialize()
{
if (!settingsRegistry.lock()->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), LwaSettingsPath))
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to load the setting registry");
return false;
}
if (!settingsRegistry->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), LwaSettingsPath))
{
AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to get login with Amazon settings object for path %s", LwaSettingsPath);
return false;
@@ -351,12 +351,12 @@ namespace AWSClientAuthUnitTest
AuthenticationProviderMock()
{
ON_CALL(*this, Initialize(testing::_)).WillByDefault(testing::Return(true));
ON_CALL(*this, Initialize()).WillByDefault(testing::Return(true));
}
virtual ~AuthenticationProviderMock() = default;
MOCK_METHOD1(Initialize, bool(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry));
MOCK_METHOD0(Initialize, bool());
MOCK_METHOD2(PasswordGrantSingleFactorSignInAsync, void(const AZStd::string& username, const AZStd::string& password));
MOCK_METHOD2(PasswordGrantMultiFactorSignInAsync, void(const AZStd::string& username, const AZStd::string& password));
MOCK_METHOD2(PasswordGrantMultiFactorConfirmSignInAsync, void(const AZStd::string& username, const AZStd::string& confirmationCode));
@@ -495,6 +495,8 @@ namespace AWSClientAuthUnitTest
m_settingsRegistry->SetContext(m_serializeContext.get());
m_settingsRegistry->SetContext(m_registrationContext.get());
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
AZ::ComponentApplicationBus::Handler::BusConnect();
AZ::Interface<AZ::ComponentApplicationRequests>::Register(this);
@@ -555,6 +557,8 @@ namespace AWSClientAuthUnitTest
AWSClientAuth::AWSClientAuthRequestBus::Handler::BusDisconnect();
}
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_testFolder.reset();
m_settingsRegistry.reset();
m_serializeContext.reset();
@@ -660,8 +664,5 @@ namespace AWSClientAuthUnitTest
m_testFolderCreated = true;
return path;
}
};
};
}
@@ -31,7 +31,7 @@ class AWSCognitoAuthenticationProviderTest
{
AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::SetUp();
m_cognitoAuthenticationProviderMock.Initialize(m_settingsRegistry);
m_cognitoAuthenticationProviderMock.Initialize();
AWSCore::AWSCoreRequestBus::Handler::BusConnect();
@@ -98,7 +98,7 @@ TEST_F(AWSCognitoAuthenticationProviderTest, Initialize_Success)
{
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetResourceNameId(testing::_)).Times(1);
AWSClientAuthUnitTest::AWSCognitoAuthenticationProviderrLocalMock mock;
ASSERT_TRUE(mock.Initialize(m_settingsRegistry));
ASSERT_TRUE(mock.Initialize());
ASSERT_EQ(mock.m_cognitoAppClientId, AWSClientAuthUnitTest::TEST_RESOURCE_NAME_ID);
}
@@ -260,5 +260,5 @@ TEST_F(AWSCognitoAuthenticationProviderTest, Initialize_Fail_EmptyResourceName)
{
AWSClientAuthUnitTest::AWSCognitoAuthenticationProviderrLocalMock mock;
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetResourceNameId(testing::_)).Times(1).WillOnce(testing::Return(""));
ASSERT_FALSE(mock.Initialize(m_settingsRegistry));
ASSERT_FALSE(mock.Initialize());
}
@@ -28,7 +28,8 @@ protected:
AWSClientAuth::LWAProviderSetting::Reflect(*m_serializeContext);
AWSClientAuth::GoogleProviderSetting::Reflect(*m_serializeContext);
m_settingspath = AZStd::string::format("%s/%s/authenticationProvider.setreg",
AZStd::string settingspath = AZStd::string::format(
"%s/%s/authenticationProvider.setreg",
m_testFolder->c_str(), AZ::SettingsRegistryInterface::RegistryFolder);
CreateTestFile("authenticationProvider.setreg"
, R"({
@@ -54,6 +55,7 @@ protected:
}
}
})");
m_settingsRegistry->MergeSettingsFile(settingspath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_mockController = AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>>();
}
@@ -66,20 +68,19 @@ protected:
public:
AZStd::unique_ptr<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>> m_mockController;
AZStd::string m_settingspath;
AZStd::vector<AZStd::string> m_enabledProviderNames { AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP,
AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuth::ProvideNameEnumStringGoogle};
};
TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Success)
{
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames, m_settingspath));
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames));
ASSERT_TRUE(m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP] != nullptr);
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantSingleFactorSignInAsync(testing::_, testing::_)).Times(1);
@@ -96,7 +97,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorS
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -111,7 +112,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorSi
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -126,7 +127,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorCo
TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -142,7 +143,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantSignInAsync
TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -157,7 +158,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantConfirmSign
TEST_F(AuthenticationProviderManagerScriptCanvasTest, RefreshTokenAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -172,7 +173,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, RefreshTokenAsync_Success)
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_ValidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@@ -188,7 +189,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_InvalidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens;
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
@@ -209,7 +210,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokens_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@@ -224,7 +225,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokens_Success)
TEST_F(AuthenticationProviderManagerScriptCanvasTest, IsSignedIn_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@@ -238,7 +239,7 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, IsSignedIn_Success)
TEST_F(AuthenticationProviderManagerScriptCanvasTest, SignOut_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* googleProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::Google].get();
EXPECT_CALL(*googleProviderMock, SignOut()).Times(1);
@@ -248,9 +249,3 @@ TEST_F(AuthenticationProviderManagerScriptCanvasTest, SignOut_Success)
googleProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Fail_InvalidPath)
{
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(m_mockController->Initialize(m_enabledProviderNames, ""));
AZ_TEST_STOP_TRACE_SUPPRESSION(2);
}
@@ -27,7 +27,8 @@ protected:
AWSClientAuth::LWAProviderSetting::Reflect(*m_serializeContext);
AWSClientAuth::GoogleProviderSetting::Reflect(*m_serializeContext);
m_settingspath = AZStd::string::format("%s/%s/authenticationProvider.setreg",
AZStd::string settingspath = AZStd::string::format(
"%s/%s/authenticationProvider.setreg",
m_testFolder->c_str(), AZ::SettingsRegistryInterface::RegistryFolder);
CreateTestFile("authenticationProvider.setreg"
, R"({
@@ -53,6 +54,7 @@ protected:
}
}
})");
m_settingsRegistry->MergeSettingsFile(settingspath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_mockController = AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>>();
}
@@ -65,20 +67,19 @@ protected:
public:
AZStd::unique_ptr<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>> m_mockController;
AZStd::string m_settingspath;
AZStd::vector<AWSClientAuth::ProviderNameEnum> m_enabledProviderNames {AWSClientAuth::ProviderNameEnum::AWSCognitoIDP,
AWSClientAuth::ProviderNameEnum::LoginWithAmazon, AWSClientAuth::ProviderNameEnum::Google};
};
TEST_F(AuthenticationProviderManagerTest, Initialize_Success)
{
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames, m_settingspath));
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames));
ASSERT_TRUE(m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP] != nullptr);
}
TEST_F(AuthenticationProviderManagerTest, PasswordGrantSingleFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantSingleFactorSignInAsync(testing::_, testing::_)).Times(1);
@@ -95,7 +96,7 @@ TEST_F(AuthenticationProviderManagerTest, PasswordGrantSingleFactorSignInAsync_F
TEST_F(AuthenticationProviderManagerTest, PasswordGrantMultiFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -110,7 +111,7 @@ TEST_F(AuthenticationProviderManagerTest, PasswordGrantMultiFactorSignInAsync_Su
TEST_F(AuthenticationProviderManagerTest, PasswordGrantMultiFactorConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -125,7 +126,7 @@ TEST_F(AuthenticationProviderManagerTest, PasswordGrantMultiFactorConfirmSignInA
TEST_F(AuthenticationProviderManagerTest, DeviceCodeGrantSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -141,7 +142,7 @@ TEST_F(AuthenticationProviderManagerTest, DeviceCodeGrantSignInAsync_Success)
TEST_F(AuthenticationProviderManagerTest, DeviceCodeGrantConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -156,7 +157,7 @@ TEST_F(AuthenticationProviderManagerTest, DeviceCodeGrantConfirmSignInAsync_Succ
TEST_F(AuthenticationProviderManagerTest, RefreshTokenAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
@@ -171,7 +172,7 @@ TEST_F(AuthenticationProviderManagerTest, RefreshTokenAsync_Success)
TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_ValidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@@ -187,7 +188,7 @@ TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_ValidToken_S
TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_InvalidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens;
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
@@ -208,7 +209,7 @@ TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_NotInitializ
TEST_F(AuthenticationProviderManagerTest, GetTokens_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@@ -223,7 +224,7 @@ TEST_F(AuthenticationProviderManagerTest, GetTokens_Success)
TEST_F(AuthenticationProviderManagerTest, IsSignedIn_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
@@ -237,7 +238,7 @@ TEST_F(AuthenticationProviderManagerTest, IsSignedIn_Success)
TEST_F(AuthenticationProviderManagerTest, SignOut_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
m_mockController->Initialize(m_enabledProviderNames);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* googleProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::Google].get();
EXPECT_CALL(*googleProviderMock, SignOut()).Times(1);
@@ -247,9 +248,3 @@ TEST_F(AuthenticationProviderManagerTest, SignOut_Success)
googleProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerTest, Initialize_Fail_InvalidPath)
{
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(m_mockController->Initialize(m_enabledProviderNames, ""));
AZ_TEST_STOP_TRACE_SUPPRESSION(2);
}
@@ -47,7 +47,7 @@ class GoogleAuthenticationProviderTest
})");
m_settingsRegistry->MergeSettingsFile(path, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_googleAuthenticationProviderLocalMock.Initialize(m_settingsRegistry);
m_googleAuthenticationProviderLocalMock.Initialize();
}
void TearDown() override
@@ -63,7 +63,7 @@ public:
TEST_F(GoogleAuthenticationProviderTest, Initialize_Success)
{
AWSClientAuthUnitTest::GoogleAuthenticationProviderLocalMock mock;
ASSERT_TRUE(mock.Initialize(m_settingsRegistry));
ASSERT_TRUE(mock.Initialize());
ASSERT_EQ(mock.m_settings->m_appClientId, "TestGoogleClientId");
}
@@ -117,14 +117,19 @@ TEST_F(GoogleAuthenticationProviderTest, RefreshTokensAsync_Fail_RequestHttpErro
TEST_F(GoogleAuthenticationProviderTest, Initialize_Fail_EmptyRegistry)
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
AZStd::shared_ptr<AZ::SettingsRegistryImpl> registry = AZStd::make_shared<AZ::SettingsRegistryImpl>();
registry->SetContext(m_serializeContext.get());
AZ::SettingsRegistry::Register(registry.get());
AWSClientAuthUnitTest::GoogleAuthenticationProviderLocalMock mock;
ASSERT_FALSE(mock.Initialize(registry));
ASSERT_FALSE(mock.Initialize());
ASSERT_EQ(mock.m_settings->m_appClientId, "");
AZ::SettingsRegistry::Unregister(registry.get());
registry.reset();
// Restore
mock.Initialize(m_settingsRegistry);
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
mock.Initialize();
}
@@ -47,7 +47,7 @@ class LWAAuthenticationProviderTest
})");
m_settingsRegistry->MergeSettingsFile(path, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_lwaAuthenticationProviderLocalMock.Initialize(m_settingsRegistry);
m_lwaAuthenticationProviderLocalMock.Initialize();
}
void TearDown() override
@@ -63,7 +63,7 @@ public:
TEST_F(LWAAuthenticationProviderTest, Initialize_Success)
{
AWSClientAuthUnitTest::LWAAuthenticationProviderLocalMock mock;
ASSERT_TRUE(mock.Initialize(m_settingsRegistry));
ASSERT_TRUE(mock.Initialize());
ASSERT_EQ(mock.m_settings->m_appClientId, "TestLWAClientId");
}
@@ -117,14 +117,19 @@ TEST_F(LWAAuthenticationProviderTest, RefreshTokensAsync_Fail_RequestHttpError)
TEST_F(LWAAuthenticationProviderTest, Initialize_Fail_EmptyRegistry)
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
AZStd::shared_ptr<AZ::SettingsRegistryImpl> registry = AZStd::make_shared<AZ::SettingsRegistryImpl>();
registry->SetContext(m_serializeContext.get());
AZ::SettingsRegistry::Register(registry.get());
AWSClientAuthUnitTest::LWAAuthenticationProviderLocalMock mock;
ASSERT_FALSE(mock.Initialize(registry));
ASSERT_FALSE(mock.Initialize());
ASSERT_EQ(mock.m_settings->m_appClientId, "");
AZ::SettingsRegistry::Unregister(registry.get());
registry.reset();
// Restore
mock.Initialize(m_settingsRegistry);
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
mock.Initialize();
}
@@ -7,7 +7,6 @@
#pragma once
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/std/string/string.h>
#include <AWSCoreInternalBus.h>
@@ -35,8 +34,10 @@ namespace AWSCore
"Failed to get profile name, return default value instead.";
static constexpr const char ResourceMappingFileNameNotFoundErrorMessage[] =
"Failed to get resource mapping config file name, return empty value instead.";
static constexpr const char SettingsRegistryLoadFailureErrorMessage[] =
static constexpr const char SettingsRegistryFileLoadFailureErrorMessage[] =
"Failed to load AWSCore settings registry file.";
static constexpr const char GlobalSettingsRegistryLoadFailureErrorMessage[] =
"Failed to load AWSCore configurations from global settings registry.";
AWSCoreConfiguration();
@@ -53,9 +54,6 @@ namespace AWSCore
void ReloadConfiguration() override;
private:
// Initialize settings registry reference by loading for project .setreg file
void InitSettingsRegistry();
// Initialize source project folder path
void InitSourceProjectFolderPath();
@@ -66,7 +64,6 @@ namespace AWSCore
void ResetSettingsRegistryData();
AZStd::string m_sourceProjectFolder;
AZ::SettingsRegistryImpl m_settingsRegistry;
AZStd::string m_profileName;
AZStd::string m_resourceMappingConfigFileName;
};
@@ -6,6 +6,8 @@
*/
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzFramework/StringFunc/StringFunc.h>
@@ -69,27 +71,6 @@ namespace AWSCore
void AWSCoreConfiguration::InitConfig()
{
InitSourceProjectFolderPath();
InitSettingsRegistry();
}
void AWSCoreConfiguration::InitSettingsRegistry()
{
if (m_sourceProjectFolder.empty())
{
AZ_Warning(AWSCoreConfigurationName, false, ProjectSourceFolderNotFoundErrorMessage);
return;
}
AZStd::string settingsRegistryPath = AZStd::string::format("%s/%s/%s",
m_sourceProjectFolder.c_str(), AZ::SettingsRegistryInterface::RegistryFolder, AWSCoreConfiguration::AWSCoreConfigurationFileName);
AzFramework::StringFunc::Path::Normalize(settingsRegistryPath);
if (!m_settingsRegistry.MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, ""))
{
AZ_Warning(AWSCoreConfigurationName, false, SettingsRegistryLoadFailureErrorMessage);
return;
}
ParseSettingsRegistryValues();
}
@@ -108,10 +89,17 @@ namespace AWSCore
void AWSCoreConfiguration::ParseSettingsRegistryValues()
{
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning(AWSCoreConfigurationName, false, GlobalSettingsRegistryLoadFailureErrorMessage);
return;
}
m_resourceMappingConfigFileName.clear();
auto resourceMappingConfigFileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreResourceMappingConfigFileNameKey);
if (!m_settingsRegistry.Get(m_resourceMappingConfigFileName, resourceMappingConfigFileNamePath))
if (!settingsRegistry->Get(m_resourceMappingConfigFileName, resourceMappingConfigFileNamePath))
{
AZ_Warning(AWSCoreConfigurationName, false, ResourceMappingFileNameNotFoundErrorMessage);
}
@@ -119,7 +107,7 @@ namespace AWSCore
m_profileName.clear();
auto profileNamePath = AZStd::string::format(
"%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreProfileNameKey);
if (!m_settingsRegistry.Get(m_profileName, profileNamePath))
if (!settingsRegistry->Get(m_profileName, profileNamePath))
{
AZ_Warning(AWSCoreConfigurationName, false, ProfileNameNotFoundErrorMessage);
m_profileName = AWSCoreDefaultProfileName;
@@ -128,20 +116,43 @@ namespace AWSCore
void AWSCoreConfiguration::ResetSettingsRegistryData()
{
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning(AWSCoreConfigurationName, false, GlobalSettingsRegistryLoadFailureErrorMessage);
return;
}
auto profileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreProfileNameKey);
m_settingsRegistry.Remove(profileNamePath);
settingsRegistry->Remove(profileNamePath);
m_profileName = AWSCoreDefaultProfileName;
auto resourceMappingConfigFileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreResourceMappingConfigFileNameKey);
m_settingsRegistry.Remove(resourceMappingConfigFileNamePath);
settingsRegistry->Remove(resourceMappingConfigFileNamePath);
m_resourceMappingConfigFileName.clear();
// Reload the AWSCore setting registry file from disk.
if (m_sourceProjectFolder.empty())
{
AZ_Warning(AWSCoreConfigurationName, false, SettingsRegistryFileLoadFailureErrorMessage);
return;
}
auto settingsRegistryPath = AZ::IO::FixedMaxPath(AZStd::string_view{ m_sourceProjectFolder }) /
AZ::SettingsRegistryInterface::RegistryFolder /
AWSCoreConfiguration::AWSCoreConfigurationFileName;
if (!settingsRegistry->MergeSettingsFile(settingsRegistryPath.c_str(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ""))
{
AZ_Warning(AWSCoreConfigurationName, false, SettingsRegistryFileLoadFailureErrorMessage);
return;
}
}
void AWSCoreConfiguration::ReloadConfiguration()
{
ResetSettingsRegistryData();
InitSettingsRegistry();
ParseSettingsRegistryValues();
}
} // namespace AWSCore
@@ -38,9 +38,8 @@ namespace AWSCore
constexpr char AWSAttributionDelaySecondsKey[] = "/Amazon/AWS/Preferences/AWSAttributionDelaySeconds";
constexpr char AWSAttributionLastTimeStampKey[] = "/Amazon/AWS/Preferences/AWSAttributionLastTimeStamp";
constexpr char AWSAttributionConsentShownKey[] = "/Amazon/AWS/Preferences/AWSAttributionConsentShown";
constexpr char AWSAttributionApiId[] = "2zxvvmv8d7";
constexpr char AWSAttributionChinaApiId[] = "";
constexpr char AWSAttributionApiStage[] = "prod";
constexpr char AWSAttributionEndpoint[] = "https://o3deattribution.us-east-1.amazonaws.com";
constexpr char AWSAttributionChinaEndpoint[] = "";
const int AWSAttributionDefaultDelayInDays = 7;
AWSAttributionManager::AWSAttributionManager()
@@ -253,17 +252,17 @@ namespace AWSCore
// Assumption to determine China region is the default profile is set to China region.
auto profile_name = Aws::Auth::GetConfigProfileName();
Aws::Client::ClientConfiguration clientConfig(profile_name.c_str());
AZStd::string apiId = AWSAttributionApiId;
if (clientConfig.region == Aws::Region::CN_NORTH_1 || clientConfig.region == Aws::Region::CN_NORTHWEST_1)
{
config->region = Aws::Region::CN_NORTH_1;
apiId = AWSAttributionChinaApiId;
config->endpointOverride = AWSAttributionChinaEndpoint;
}
else
{
config->region = Aws::Region::US_EAST_1;
config->endpointOverride = AWSAttributionEndpoint;
}
config->region = Aws::Region::US_WEST_2;
config->endpointOverride =
AWSResourceMappingUtils::FormatRESTApiUrl(apiId, config->region.value().c_str(), AWSAttributionApiStage).c_str();
}
bool AWSAttributionManager::CheckConsentShown()
@@ -31,7 +31,7 @@ namespace AWSCore
void AWSResourceMappingManager::ActivateManager()
{
ReloadConfigFile(true);
ReloadConfigFile();
AWSResourceMappingRequestBus::Handler::BusConnect();
}
@@ -67,10 +67,13 @@ protected:
m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
m_serializeContext->CreateEditContext();
m_behaviorContext = AZStd::make_unique<AZ::BehaviorContext>();
m_componentDescriptor.reset(AWSCoreSystemComponent::CreateDescriptor());
m_componentDescriptor->Reflect(m_serializeContext.get());
m_componentDescriptor->Reflect(m_behaviorContext.get());
m_settingsRegistry->SetContext(m_serializeContext.get());
m_entity = aznew AZ::Entity();
m_coreSystemsComponent.reset(m_entity->CreateComponent<AWSCoreSystemComponent>());
}
@@ -60,6 +60,8 @@ public:
AzFramework::StringFunc::Path::Normalize(m_normalizedSetRegFolderPath);
m_localFileIO->SetAlias("@devassets@", m_normalizedSourceProjectFolder.c_str());
CreateTestSetRegFile(TEST_VALID_RESOURCE_MAPPING_SETREG);
}
void TearDown() override
@@ -73,11 +75,11 @@ public:
}
AZStd::unique_ptr<AWSCore::AWSCoreConfiguration> m_awsCoreConfiguration;
AZStd::string m_normalizedSetRegFilePath;
private:
AZStd::string m_normalizedSourceProjectFolder;
AZStd::string m_normalizedSetRegFolderPath;
AZStd::string m_normalizedSetRegFilePath;
void CreateTestFile(const AZStd::string& filePath, const AZStd::string& fileContent)
{
@@ -118,17 +120,9 @@ private:
TEST_F(AWSCoreConfigurationTest, InitConfig_NoSourceProjectFolderFound_ReturnEmptyConfigFilePath)
{
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_localFileIO->ClearAlias("@devassets@");
AZ_TEST_START_TRACE_SUPPRESSION;
m_awsCoreConfiguration->InitConfig();
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
EXPECT_TRUE(actualConfigFilePath.empty());
}
TEST_F(AWSCoreConfigurationTest, InitConfig_NoSettingsRegistryFileFound_ReturnEmptyConfigFilePath)
{
AZ_TEST_START_TRACE_SUPPRESSION;
m_awsCoreConfiguration->InitConfig();
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
@@ -140,6 +134,7 @@ TEST_F(AWSCoreConfigurationTest, InitConfig_NoSettingsRegistryFileFound_ReturnEm
TEST_F(AWSCoreConfigurationTest, InitConfig_SettingsRegistryIsEmpty_ReturnEmptyConfigFilePath)
{
CreateTestSetRegFile(TEST_INVALID_RESOURCE_MAPPING_SETREG);
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_awsCoreConfiguration->InitConfig();
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
@@ -148,7 +143,7 @@ TEST_F(AWSCoreConfigurationTest, InitConfig_SettingsRegistryIsEmpty_ReturnEmptyC
TEST_F(AWSCoreConfigurationTest, InitConfig_LoadValidSettingsRegistry_ReturnNonEmptyConfigFilePath)
{
CreateTestSetRegFile(TEST_VALID_RESOURCE_MAPPING_SETREG);
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_awsCoreConfiguration->InitConfig();
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
@@ -157,6 +152,7 @@ TEST_F(AWSCoreConfigurationTest, InitConfig_LoadValidSettingsRegistry_ReturnNonE
TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_NoSourceProjectFolderFound_ReturnEmptyConfigFilePath)
{
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_localFileIO->ClearAlias("@devassets@");
m_awsCoreConfiguration->ReloadConfiguration();
@@ -167,6 +163,7 @@ TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_NoSourceProjectFolderFound_
TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_LoadValidSettingsRegistryAfterInvalidOne_ReturnNonEmptyConfigFilePath)
{
CreateTestSetRegFile(TEST_INVALID_RESOURCE_MAPPING_SETREG);
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_awsCoreConfiguration->InitConfig();
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
@@ -185,7 +182,7 @@ TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_LoadValidSettingsRegistryAf
TEST_F(AWSCoreConfigurationTest, ReloadConfiguration_LoadInvalidSettingsRegistryAfterValidOne_ReturnEmptyConfigFilePath)
{
CreateTestSetRegFile(TEST_VALID_RESOURCE_MAPPING_SETREG);
m_settingsRegistry->MergeSettingsFile(m_normalizedSetRegFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_awsCoreConfiguration->InitConfig();
auto actualConfigFilePath = m_awsCoreConfiguration->GetResourceMappingConfigFilePath();
@@ -14,7 +14,6 @@
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/base.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
@@ -161,7 +160,6 @@ namespace AWSAttributionUnitTest
protected:
AZStd::shared_ptr<AZ::SerializeContext> m_serializeContext;
AZStd::unique_ptr<AZ::JsonRegistrationContext> m_registrationContext;
AZStd::shared_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
AZStd::unique_ptr<AZ::JobContext> m_jobContext;
AZStd::unique_ptr<AZ::JobCancelGroup> m_jobCancelGroup;
AZStd::unique_ptr<AZ::JobManager> m_jobManager;
@@ -186,13 +184,9 @@ namespace AWSAttributionUnitTest
AZ::JsonSystemComponent::Reflect(m_registrationContext.get());
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
m_settingsRegistry->SetContext(m_serializeContext.get());
m_settingsRegistry->SetContext(m_registrationContext.get());
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
AZ::JobManagerDesc jobManagerDesc;
AZ::JobManagerThreadDesc threadDesc;
@@ -210,9 +204,6 @@ namespace AWSAttributionUnitTest
m_jobCancelGroup.reset();
m_jobManager.reset();
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_settingsRegistry.reset();
m_serializeContext.reset();
m_registrationContext.reset();
@@ -427,8 +418,8 @@ namespace AWSAttributionUnitTest
manager.SetApiEndpointAndRegion(config);
// THEN
ASSERT_TRUE(config->region == Aws::Region::US_WEST_2);
ASSERT_TRUE(config->endpointOverride->find("execute-api.us-west-2.amazonaws.com") != Aws::String::npos);
ASSERT_TRUE(config->region == Aws::Region::US_EAST_1);
ASSERT_TRUE(config->endpointOverride->find("o3deattribution.us-east-1.amazonaws.com") != Aws::String::npos);
delete config;
}
@@ -8,7 +8,6 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzTest/AzTest.h>
@@ -87,13 +86,9 @@ namespace AWSCoreUnitTest
m_componentDescriptor->Reflect(m_serializeContext.get());
m_componentDescriptor->Reflect(m_behaviorContext.get());
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
m_settingsRegistry->SetContext(m_serializeContext.get());
m_settingsRegistry->SetContext(m_registrationContext.get());
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
m_entity = aznew AZ::Entity();
m_awsCoreSystemComponentMock = aznew testing::NiceMock<AWSCoreSystemComponentMock>();
m_entity->AddComponent(m_awsCoreSystemComponentMock);
@@ -113,7 +108,6 @@ namespace AWSCoreUnitTest
m_awsCoreComponentDescriptor.reset();
m_componentDescriptor.reset();
m_behaviorContext.reset();
m_settingsRegistry.reset();
m_registrationContext.reset();
m_serializeContext.reset();
AWSCoreFixture::TearDown();
@@ -130,7 +124,6 @@ namespace AWSCoreUnitTest
AZStd::unique_ptr<AZ::JsonRegistrationContext> m_registrationContext;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_componentDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_awsCoreComponentDescriptor;
AZStd::shared_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
};
TEST_F(AWSAttributionSystemComponentTest, SystemComponentInitActivate_Success)
@@ -171,7 +171,7 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseInvalidConfigFile_Con
AZStd::string actualRegion;
AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
EXPECT_EQ(m_reloadConfigurationCounter, 1);
EXPECT_EQ(m_reloadConfigurationCounter, 0);
EXPECT_TRUE(actualAccountId.empty());
EXPECT_TRUE(actualRegion.empty());
EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Error);
@@ -186,7 +186,7 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_Confi
AZStd::string actualRegion;
AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
EXPECT_EQ(m_reloadConfigurationCounter, 1);
EXPECT_EQ(m_reloadConfigurationCounter, 0);
EXPECT_FALSE(actualAccountId.empty());
EXPECT_FALSE(actualRegion.empty());
EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Ready);
@@ -413,7 +413,7 @@ TEST_F(AWSResourceMappingManagerTest, ReloadConfigFile_ParseValidConfigFileAfter
AZStd::string actualRegion;
AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
EXPECT_EQ(m_reloadConfigurationCounter, 1);
EXPECT_EQ(m_reloadConfigurationCounter, 0);
EXPECT_TRUE(actualAccountId.empty());
EXPECT_TRUE(actualRegion.empty());
EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Error);
@@ -423,7 +423,7 @@ TEST_F(AWSResourceMappingManagerTest, ReloadConfigFile_ParseValidConfigFileAfter
AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
EXPECT_EQ(m_reloadConfigurationCounter, 1);
EXPECT_EQ(m_reloadConfigurationCounter, 0);
EXPECT_FALSE(actualAccountId.empty());
EXPECT_FALSE(actualRegion.empty());
EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Ready);
@@ -9,6 +9,7 @@
#include <AzCore/Memory/PoolAllocator.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <Framework/JsonObjectHandler.h>
@@ -117,10 +118,16 @@ public:
m_otherFileIO = AZ::IO::FileIOBase::GetInstance();
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(m_localFileIO);
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
}
void TearDown() override
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_settingsRegistry.reset();
AZ::IO::FileIOBase::SetInstance(nullptr);
if (m_otherFileIO)
@@ -160,4 +167,7 @@ public:
private:
AZ::IO::FileIOBase* m_otherFileIO = nullptr;
protected:
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
};
@@ -17,12 +17,16 @@ namespace AWSMetrics
class ClientConfiguration
{
public:
static constexpr const char AWSMetricsMaxQueueSizeInMbKey[] = "/Gems/AWSMetrics/MaxQueueSizeInMb";
static constexpr const char AWSMetricsQueueFlushPeriodInSecondsKey[] = "/Gems/AWSMetrics/QueueFlushPeriodInSeconds";
static constexpr const char AWSMetricsOfflineRecordingEnabledKey[] = "/Gems/AWSMetrics/OfflineRecording";
static constexpr const char AWSMetricsMaxNumRetriesKey[] = "/Gems/AWSMetrics/MaxNumRetries";
ClientConfiguration();
//! Reset the client settings based on the provided configuration file.
//! @param settingsRegistryPath Full path to the configuration file.
//! Initialize the client settings based on the global setting registry.
//! @return whether the operation is successful
bool ResetClientConfiguration(const AZStd::string& settingsRegistryPath);
bool InitClientConfiguration();
//! Retrieve the max queue size setting.
//! @return Max queue size in bytes.
@@ -33,9 +33,8 @@ namespace AWSMetrics
~MetricsManager();
//! Initializing the metrics manager
//! @param settingsRegistryPath Path to the settings registry file.
//! @return Whether the operation is successful.
bool Init(const AZStd::string& settingsRegistryPath = "");
bool Init();
//! Start sending metircs to the backend or a local file.
void StartMetrics();
//! Stop sending metircs to the backend or a local file.
@@ -192,11 +192,7 @@ namespace AWSMetrics
void AWSMetricsSystemComponent::Init()
{
AZStd::string priorAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devroot@");
AZStd::string configFilePath = priorAlias + "\\Gems\\AWSMetrics\\Code\\" + AZ::SettingsRegistryInterface::RegistryFolder + "\\awsMetricsClientConfiguration.setreg";
AzFramework::StringFunc::Path::Normalize(configFilePath);
m_metricsManager->Init(configFilePath);
m_metricsManager->Init();
}
void AWSMetricsSystemComponent::Activate()
@@ -9,6 +9,7 @@
#include <AzCore/IO/FileIO.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzFramework/StringFunc/StringFunc.h>
@@ -23,38 +24,44 @@ namespace AWSMetrics
{
}
bool ClientConfiguration::ResetClientConfiguration(const AZStd::string& settingsRegistryPath)
bool ClientConfiguration::InitClientConfiguration()
{
AZStd::unique_ptr<AZ::SettingsRegistryInterface> settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
AZ_Printf("AWSMetrics", "Reset client settings using the confiugration file %s", settingsRegistryPath.c_str());
if (!settingsRegistry->MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch))
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
if (!settingsRegistry)
{
AZ_Warning("AWSMetrics", false, "Failed to merge the configuration file");
AZ_Warning("AWSMetrics", false, "Failed to load the setting registry");
return false;
}
if (!settingsRegistry->Get(m_maxQueueSizeInMb, "/Amazon/Gems/AWSMetrics/MaxQueueSizeInMb"))
if (!settingsRegistry->Get(
m_maxQueueSizeInMb,
AZStd::string::format("%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSMetricsMaxQueueSizeInMbKey)))
{
AZ_Warning("AWSMetrics", false, "Failed to read the maximum queue size setting in the configuration file");
AZ_Warning("AWSMetrics", false, "Failed to read the maximum queue size setting from the setting registry");
return false;
}
if (!settingsRegistry->Get(m_queueFlushPeriodInSeconds, "/Amazon/Gems/AWSMetrics/QueueFlushPeriodInSeconds"))
if (!settingsRegistry->Get(
m_queueFlushPeriodInSeconds,
AZStd::string::format("%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSMetricsQueueFlushPeriodInSecondsKey)))
{
AZ_Warning("AWSMetrics", false, "Failed to read the queue flush period setting in the configuration file");
AZ_Warning("AWSMetrics", false, "Failed to read the queue flush period setting from the setting registry");
return false;
}
bool enableOfflineRecording = false;
if (!settingsRegistry->Get(enableOfflineRecording, "/Amazon/Gems/AWSMetrics/OfflineRecording"))
if (!settingsRegistry->Get(
enableOfflineRecording,
AZStd::string::format("%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSMetricsOfflineRecordingEnabledKey)))
{
AZ_Warning("AWSMetrics", false, "Failed to read the submission target setting in the configuration file");
AZ_Warning("AWSMetrics", false, "Failed to read the submission target setting from the setting registry");
return false;
}
m_offlineRecordingEnabled = enableOfflineRecording;
if (!settingsRegistry->Get(m_maxNumRetries, "/Amazon/Gems/AWSMetrics/MaxNumRetries"))
if (!settingsRegistry->Get(
m_maxNumRetries,
AZStd::string::format("%s%s", AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSMetricsMaxNumRetriesKey)))
{
AZ_Warning("AWSMetrics", false, "Failed to read the maximum number of retries setting in the configuration file");
return false;
@@ -34,9 +34,9 @@ namespace AWSMetrics
ShutdownMetrics();
}
bool MetricsManager::Init(const AZStd::string& settingsRegistryPath)
bool MetricsManager::Init()
{
if (!m_clientConfiguration->ResetClientConfiguration(settingsRegistryPath))
if (!m_clientConfiguration->InitClientConfiguration())
{
return false;
}
@@ -52,10 +52,14 @@ namespace AWSMetrics
m_settingsRegistry->SetContext(m_serializeContext.get());
m_settingsRegistry->SetContext(m_registrationContext.get());
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
}
void TearDown() override
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_registrationContext->EnableRemoveReflection();
AZ::JsonSystemComponent::Reflect(m_registrationContext.get());
m_registrationContext->DisableRemoveReflection();
@@ -130,7 +134,7 @@ namespace AWSMetrics
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
AZStd::unique_ptr<AZ::JsonRegistrationContext> m_registrationContext;
AZStd::shared_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
private:
AZStd::string GetTestFolderPath()
@@ -135,7 +135,8 @@ namespace AWSMetrics
m_metricsManager = AZStd::make_unique<MetricsManager>();
AZStd::string configFilePath = CreateClientConfigFile(true, (double) TestMetricsEventSizeInBytes / MbToBytes * 2, DefaultFlushPeriodInSeconds, 0);
m_metricsManager->Init(configFilePath);
m_settingsRegistry->MergeSettingsFile(configFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_metricsManager->Init();
RemoveFile(m_metricsManager->GetMetricsFilePath());
@@ -161,7 +162,8 @@ namespace AWSMetrics
RevertMockIOToLocalFileIO();
AZStd::string configFilePath = CreateClientConfigFile(offlineRecordingEnabled, maxQueueSizeInMb, queueFlushPeriodInSeconds, MaxNumRetries);
m_metricsManager->Init(configFilePath);
m_settingsRegistry->MergeSettingsFile(configFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
m_metricsManager->Init();
ReplaceLocalFileIOWithMockIO();
}
@@ -555,10 +557,11 @@ namespace AWSMetrics
AZStd::unique_ptr<ClientConfiguration> m_clientConfiguration;
};
TEST_F(ClientConfigurationTest, ResetClientConfiguration_ValidConfigurationFile_Success)
TEST_F(ClientConfigurationTest, ResetClientConfiguration_ValidClientConfiguration_Success)
{
AZStd::string configFilePath = CreateClientConfigFile(true, DEFAULT_MAX_QUEUE_SIZE_IN_MB, DefaultFlushPeriodInSeconds, DEFAULT_MAX_NUM_RETRIES);
ASSERT_TRUE(m_clientConfiguration->ResetClientConfiguration(configFilePath));
m_settingsRegistry->MergeSettingsFile(configFilePath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, {});
ASSERT_TRUE(m_clientConfiguration->InitClientConfiguration());
ASSERT_TRUE(m_clientConfiguration->OfflineRecordingEnabled());
ASSERT_EQ(m_clientConfiguration->GetMaxQueueSizeInBytes(), DEFAULT_MAX_QUEUE_SIZE_IN_MB * 1000000);
@@ -573,12 +576,4 @@ namespace AWSMetrics
ASSERT_EQ(strcmp(m_clientConfiguration->GetMetricsFileDir(), resolvedPath), 0);
ASSERT_EQ(m_clientConfiguration->GetMetricsFileFullPath(), expectedMetricsFilePath);
}
TEST_F(ClientConfigurationTest, ResetClientConfiguration_InvalidConfigurationFile_Fail)
{
AZStd::string configFilePath = "invalidConfig";
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(m_clientConfiguration->ResetClientConfiguration(configFilePath));
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
}
+8
View File
@@ -14,3 +14,11 @@ add_subdirectory(RPI)
add_subdirectory(Tools)
add_subdirectory(Utils)
# The "Atom" Gem will alias the real Atom_AtomBridge target variants
# allows the enabling and disabling the "Atom" Gem to build the pre-requisite dependencies
ly_create_alias(NAME Atom.Clients NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Clients)
ly_create_alias(NAME Atom.Servers NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Servers)
if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME Atom.Builders NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Builders)
ly_create_alias(NAME Atom.Tools NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Tools)
endif()
@@ -33,7 +33,12 @@ bool m_detail_normal_flipX; \
bool m_detail_normal_flipY; \
\
float3x3 m_detailUvMatrix; \
float3x3 m_detailUvMatrixInverse;
float4 m_detailUvMatrixPad; \
float3x3 m_detailUvMatrixInverse; \
float4 m_detailUvMatrixInversePad;
// [GFX TODO][ATOM-14595] m_detailUvMatrixPad and m_detailUvMatrixInversePad are a workaround for a data stomping bug.
// Remove them once the bug is fixed.
#define COMMON_OPTIONS_DETAIL_MAPS(prefix) \
@@ -82,6 +82,12 @@ function ProcessEditor(context)
context:SetMaterialPropertyVisibility("opacity.factor", mainVisibility)
context:SetMaterialPropertyVisibility("opacity.doubleSided", mainVisibility)
if(opacityMode == OpacityMode_Blended or opacityMode == OpacityMode_TintedTransparent) then
context:SetMaterialPropertyVisibility("opacity.alphaAffectsSpecular", MaterialPropertyVisibility_Enabled)
else
context:SetMaterialPropertyVisibility("opacity.alphaAffectsSpecular", MaterialPropertyVisibility_Hidden)
end
if(mainVisibility == MaterialPropertyVisibility_Enabled) then
local alphaSource = context:GetMaterialPropertyValue_enum("opacity.alphaSource")
@@ -54,7 +54,7 @@
"Attachment": "Depth"
},
"ImageDescriptor": {
"Format": "R32_FLOAT"
"Format": "R16_FLOAT"
}
}
],
@@ -54,7 +54,7 @@
"Attachment": "Input"
},
"ImageDescriptor": {
"Format": "R32_FLOAT"
"Format": "R16_FLOAT"
}
}
],
@@ -356,8 +356,9 @@ float DirectionalLightShadow::GetVisibilityFromLightEsm()
{
const float distanceWithinCameraView = depthDiff / (1. - distanceMin);
const float3 coord = float3(shadowCoord.xy, indexOfCascade);
const float expDepthInShadowmap = expShadowmap.Sample(PassSrg::LinearSampler, coord).r;
const float ratio = exp(-EsmExponentialShift * distanceWithinCameraView) * expDepthInShadowmap;
const float occluder = expShadowmap.Sample(PassSrg::LinearSampler, coord).r;
const float exponent = -EsmExponentialShift * (distanceWithinCameraView - occluder);
const float ratio = exp(exponent);
m_debugInfo.m_cascadeIndex = indexOfCascade;
return saturate(ratio);
@@ -385,8 +386,9 @@ float DirectionalLightShadow::GetVisibilityFromLightEsmPcf()
{
const float distanceWithinCameraView = depthDiff / (1. - distanceMin);
const float3 coord = float3(shadowCoord.xy, indexOfCascade);
const float expDepthInShadowmap = expShadowmap.Sample(PassSrg::LinearSampler, coord).r;
float ratio = exp(-EsmExponentialShift * distanceWithinCameraView) * expDepthInShadowmap;
const float occluder = expShadowmap.Sample(PassSrg::LinearSampler, coord).r;
const float exponent = -EsmExponentialShift * (distanceWithinCameraView - occluder);
float ratio = exp(exponent);
static const float pcfFallbackThreshold = 1.04;
if (ratio > pcfFallbackThreshold)
@@ -63,12 +63,7 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
// So this converts it to "depth" to emphasize the difference
// within the frustum.
const float depth = (depthInClip - distanceMin) / (1. - distanceMin);
// Todo: Expose Esm exponent slider for directional lights
// This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli
// ATOM-15775
const float outValue = exp(EsmExponentialShift * depth);
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
PassSrg::m_outputShadowmap[dispatchId].r = depth;
break;
}
case ShadowmapLightType::Spot:
+9
View File
@@ -14,3 +14,12 @@ add_subdirectory(TechnicalArt)
add_subdirectory(AtomBridge)
add_subdirectory(AtomViewportDisplayInfo)
add_subdirectory(AtomViewportDisplayIcons)
# The "AtomLyIntegration" Gem will also alias the real Atom_AtomBridge target variants
# The Atom Gem does the same at the moment.
ly_create_alias(NAME AtomLyIntegration.Clients NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Clients)
ly_create_alias(NAME AtomLyIntegration.Servers NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Servers)
if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AtomLyIntegration.Builders NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Builders)
ly_create_alias(NAME AtomLyIntegration.Tools NAMESPACE Gem TARGETS Gem::Atom_AtomBridge.Tools)
endif()
-1
View File
@@ -2598,7 +2598,6 @@ struct ImFontAtlas
// NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data.
IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin
IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters
IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 2999 Ideographs
IMGUI_API const ImWchar* GetGlyphRangesChineseFull(); // Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs
IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese
IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters
-89
View File
@@ -2901,95 +2901,6 @@ const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon()
return &full_ranges[0];
}
const ImWchar* ImFontAtlas::GetGlyphRangesJapanese()
{
// 2999 ideograms code points for Japanese
// - 2136 Joyo (meaning "for regular use" or "for common use") Kanji code points
// - 863 Jinmeiyo (meaning "for personal name") Kanji code points
// - Sourced from the character information database of the Information-technology Promotion Agency, Japan
// - https://mojikiban.ipa.go.jp/mji/
// - Available under the terms of the Creative Commons Attribution-ShareAlike 2.1 Japan (CC BY-SA 2.1 JP).
// - https://creativecommons.org/licenses/by-sa/2.1/jp/deed.en
// - https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode
// - You can generate this code by the script at:
// - https://github.com/vaiorabbit/everyday_use_kanji
// - References:
// - List of Joyo Kanji
// - (Official list by the Agency for Cultural Affairs) https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kakuki/14/tosin02/index.html
// - (Wikipedia) https://en.wikipedia.org/wiki/List_of_j%C5%8Dy%C5%8D_kanji
// - List of Jinmeiyo Kanji
// - (Official list by the Ministry of Justice) http://www.moj.go.jp/MINJI/minji86.html
// - (Wikipedia) https://en.wikipedia.org/wiki/Jinmeiy%C5%8D_kanji
// - Missing 1 Joyo Kanji: U+20B9F (Kun'yomi: Shikaru, On'yomi: Shitsu,shichi), see https://github.com/ocornut/imgui/pull/3627 for details.
// You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters.
// (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.)
static const short accumulative_offsets_from_0x4E00[] =
{
0,1,2,4,1,1,1,1,2,1,3,3,2,2,1,5,3,5,7,5,6,1,2,1,7,2,6,3,1,8,1,1,4,1,1,18,2,11,2,6,2,1,2,1,5,1,2,1,3,1,2,1,2,3,3,1,1,2,3,1,1,1,12,7,9,1,4,5,1,
1,2,1,10,1,1,9,2,2,4,5,6,9,3,1,1,1,1,9,3,18,5,2,2,2,2,1,6,3,7,1,1,1,1,2,2,4,2,1,23,2,10,4,3,5,2,4,10,2,4,13,1,6,1,9,3,1,1,6,6,7,6,3,1,2,11,3,
2,2,3,2,15,2,2,5,4,3,6,4,1,2,5,2,12,16,6,13,9,13,2,1,1,7,16,4,7,1,19,1,5,1,2,2,7,7,8,2,6,5,4,9,18,7,4,5,9,13,11,8,15,2,1,1,1,2,1,2,2,1,2,2,8,
2,9,3,3,1,1,4,4,1,1,1,4,9,1,4,3,5,5,2,7,5,3,4,8,2,1,13,2,3,3,1,14,1,1,4,5,1,3,6,1,5,2,1,1,3,3,3,3,1,1,2,7,6,6,7,1,4,7,6,1,1,1,1,1,12,3,3,9,5,
2,6,1,5,6,1,2,3,18,2,4,14,4,1,3,6,1,1,6,3,5,5,3,2,2,2,2,12,3,1,4,2,3,2,3,11,1,7,4,1,2,1,3,17,1,9,1,24,1,1,4,2,2,4,1,2,7,1,1,1,3,1,2,2,4,15,1,
1,2,1,1,2,1,5,2,5,20,2,5,9,1,10,8,7,6,1,1,1,1,1,1,6,2,1,2,8,1,1,1,1,5,1,1,3,1,1,1,1,3,1,1,12,4,1,3,1,1,1,1,1,10,3,1,7,5,13,1,2,3,4,6,1,1,30,
2,9,9,1,15,38,11,3,1,8,24,7,1,9,8,10,2,1,9,31,2,13,6,2,9,4,49,5,2,15,2,1,10,2,1,1,1,2,2,6,15,30,35,3,14,18,8,1,16,10,28,12,19,45,38,1,3,2,3,
13,2,1,7,3,6,5,3,4,3,1,5,7,8,1,5,3,18,5,3,6,1,21,4,24,9,24,40,3,14,3,21,3,2,1,2,4,2,3,1,15,15,6,5,1,1,3,1,5,6,1,9,7,3,3,2,1,4,3,8,21,5,16,4,
5,2,10,11,11,3,6,3,2,9,3,6,13,1,2,1,1,1,1,11,12,6,6,1,4,2,6,5,2,1,1,3,3,6,13,3,1,1,5,1,2,3,3,14,2,1,2,2,2,5,1,9,5,1,1,6,12,3,12,3,4,13,2,14,
2,8,1,17,5,1,16,4,2,2,21,8,9,6,23,20,12,25,19,9,38,8,3,21,40,25,33,13,4,3,1,4,1,2,4,1,2,5,26,2,1,1,2,1,3,6,2,1,1,1,1,1,1,2,3,1,1,1,9,2,3,1,1,
1,3,6,3,2,1,1,6,6,1,8,2,2,2,1,4,1,2,3,2,7,3,2,4,1,2,1,2,2,1,1,1,1,1,3,1,2,5,4,10,9,4,9,1,1,1,1,1,1,5,3,2,1,6,4,9,6,1,10,2,31,17,8,3,7,5,40,1,
7,7,1,6,5,2,10,7,8,4,15,39,25,6,28,47,18,10,7,1,3,1,1,2,1,1,1,3,3,3,1,1,1,3,4,2,1,4,1,3,6,10,7,8,6,2,2,1,3,3,2,5,8,7,9,12,2,15,1,1,4,1,2,1,1,
1,3,2,1,3,3,5,6,2,3,2,10,1,4,2,8,1,1,1,11,6,1,21,4,16,3,1,3,1,4,2,3,6,5,1,3,1,1,3,3,4,6,1,1,10,4,2,7,10,4,7,4,2,9,4,3,1,1,1,4,1,8,3,4,1,3,1,
6,1,4,2,1,4,7,2,1,8,1,4,5,1,1,2,2,4,6,2,7,1,10,1,1,3,4,11,10,8,21,4,6,1,3,5,2,1,2,28,5,5,2,3,13,1,2,3,1,4,2,1,5,20,3,8,11,1,3,3,3,1,8,10,9,2,
10,9,2,3,1,1,2,4,1,8,3,6,1,7,8,6,11,1,4,29,8,4,3,1,2,7,13,1,4,1,6,2,6,12,12,2,20,3,2,3,6,4,8,9,2,7,34,5,1,18,6,1,1,4,4,5,7,9,1,2,2,4,3,4,1,7,
2,2,2,6,2,3,25,5,3,6,1,4,6,7,4,2,1,4,2,13,6,4,4,3,1,5,3,4,4,3,2,1,1,4,1,2,1,1,3,1,11,1,6,3,1,7,3,6,2,8,8,6,9,3,4,11,3,2,10,12,2,5,11,1,6,4,5,
3,1,8,5,4,6,6,3,5,1,1,3,2,1,2,2,6,17,12,1,10,1,6,12,1,6,6,19,9,6,16,1,13,4,4,15,7,17,6,11,9,15,12,6,7,2,1,2,2,15,9,3,21,4,6,49,18,7,3,2,3,1,
6,8,2,2,6,2,9,1,3,6,4,4,1,2,16,2,5,2,1,6,2,3,5,3,1,2,5,1,2,1,9,3,1,8,6,4,8,11,3,1,1,1,1,3,1,13,8,4,1,3,2,2,1,4,1,11,1,5,2,1,5,2,5,8,6,1,1,7,
4,3,8,3,2,7,2,1,5,1,5,2,4,7,6,2,8,5,1,11,4,5,3,6,18,1,2,13,3,3,1,21,1,1,4,1,4,1,1,1,8,1,2,2,7,1,2,4,2,2,9,2,1,1,1,4,3,6,3,12,5,1,1,1,5,6,3,2,
4,8,2,2,4,2,7,1,8,9,5,2,3,2,1,3,2,13,7,14,6,5,1,1,2,1,4,2,23,2,1,1,6,3,1,4,1,15,3,1,7,3,9,14,1,3,1,4,1,1,5,8,1,3,8,3,8,15,11,4,14,4,4,2,5,5,
1,7,1,6,14,7,7,8,5,15,4,8,6,5,6,2,1,13,1,20,15,11,9,2,5,6,2,11,2,6,2,5,1,5,8,4,13,19,25,4,1,1,11,1,34,2,5,9,14,6,2,2,6,1,1,14,1,3,14,13,1,6,
12,21,14,14,6,32,17,8,32,9,28,1,2,4,11,8,3,1,14,2,5,15,1,1,1,1,3,6,4,1,3,4,11,3,1,1,11,30,1,5,1,4,1,5,8,1,1,3,2,4,3,17,35,2,6,12,17,3,1,6,2,
1,1,12,2,7,3,3,2,1,16,2,8,3,6,5,4,7,3,3,8,1,9,8,5,1,2,1,3,2,8,1,2,9,12,1,1,2,3,8,3,24,12,4,3,7,5,8,3,3,3,3,3,3,1,23,10,3,1,2,2,6,3,1,16,1,16,
22,3,10,4,11,6,9,7,7,3,6,2,2,2,4,10,2,1,1,2,8,7,1,6,4,1,3,3,3,5,10,12,12,2,3,12,8,15,1,1,16,6,6,1,5,9,11,4,11,4,2,6,12,1,17,5,13,1,4,9,5,1,11,
2,1,8,1,5,7,28,8,3,5,10,2,17,3,38,22,1,2,18,12,10,4,38,18,1,4,44,19,4,1,8,4,1,12,1,4,31,12,1,14,7,75,7,5,10,6,6,13,3,2,11,11,3,2,5,28,15,6,18,
18,5,6,4,3,16,1,7,18,7,36,3,5,3,1,7,1,9,1,10,7,2,4,2,6,2,9,7,4,3,32,12,3,7,10,2,23,16,3,1,12,3,31,4,11,1,3,8,9,5,1,30,15,6,12,3,2,2,11,19,9,
14,2,6,2,3,19,13,17,5,3,3,25,3,14,1,1,1,36,1,3,2,19,3,13,36,9,13,31,6,4,16,34,2,5,4,2,3,3,5,1,1,1,4,3,1,17,3,2,3,5,3,1,3,2,3,5,6,3,12,11,1,3,
1,2,26,7,12,7,2,14,3,3,7,7,11,25,25,28,16,4,36,1,2,1,6,2,1,9,3,27,17,4,3,4,13,4,1,3,2,2,1,10,4,2,4,6,3,8,2,1,18,1,1,24,2,2,4,33,2,3,63,7,1,6,
40,7,3,4,4,2,4,15,18,1,16,1,1,11,2,41,14,1,3,18,13,3,2,4,16,2,17,7,15,24,7,18,13,44,2,2,3,6,1,1,7,5,1,7,1,4,3,3,5,10,8,2,3,1,8,1,1,27,4,2,1,
12,1,2,1,10,6,1,6,7,5,2,3,7,11,5,11,3,6,6,2,3,15,4,9,1,1,2,1,2,11,2,8,12,8,5,4,2,3,1,5,2,2,1,14,1,12,11,4,1,11,17,17,4,3,2,5,5,7,3,1,5,9,9,8,
2,5,6,6,13,13,2,1,2,6,1,2,2,49,4,9,1,2,10,16,7,8,4,3,2,23,4,58,3,29,1,14,19,19,11,11,2,7,5,1,3,4,6,2,18,5,12,12,17,17,3,3,2,4,1,6,2,3,4,3,1,
1,1,1,5,1,1,9,1,3,1,3,6,1,8,1,1,2,6,4,14,3,1,4,11,4,1,3,32,1,2,4,13,4,1,2,4,2,1,3,1,11,1,4,2,1,4,4,6,3,5,1,6,5,7,6,3,23,3,5,3,5,3,3,13,3,9,10,
1,12,10,2,3,18,13,7,160,52,4,2,2,3,2,14,5,4,12,4,6,4,1,20,4,11,6,2,12,27,1,4,1,2,2,7,4,5,2,28,3,7,25,8,3,19,3,6,10,2,2,1,10,2,5,4,1,3,4,1,5,
3,2,6,9,3,6,2,16,3,3,16,4,5,5,3,2,1,2,16,15,8,2,6,21,2,4,1,22,5,8,1,1,21,11,2,1,11,11,19,13,12,4,2,3,2,3,6,1,8,11,1,4,2,9,5,2,1,11,2,9,1,1,2,
14,31,9,3,4,21,14,4,8,1,7,2,2,2,5,1,4,20,3,3,4,10,1,11,9,8,2,1,4,5,14,12,14,2,17,9,6,31,4,14,1,20,13,26,5,2,7,3,6,13,2,4,2,19,6,2,2,18,9,3,5,
12,12,14,4,6,2,3,6,9,5,22,4,5,25,6,4,8,5,2,6,27,2,35,2,16,3,7,8,8,6,6,5,9,17,2,20,6,19,2,13,3,1,1,1,4,17,12,2,14,7,1,4,18,12,38,33,2,10,1,1,
2,13,14,17,11,50,6,33,20,26,74,16,23,45,50,13,38,33,6,6,7,4,4,2,1,3,2,5,8,7,8,9,3,11,21,9,13,1,3,10,6,7,1,2,2,18,5,5,1,9,9,2,68,9,19,13,2,5,
1,4,4,7,4,13,3,9,10,21,17,3,26,2,1,5,2,4,5,4,1,7,4,7,3,4,2,1,6,1,1,20,4,1,9,2,2,1,3,3,2,3,2,1,1,1,20,2,3,1,6,2,3,6,2,4,8,1,3,2,10,3,5,3,4,4,
3,4,16,1,6,1,10,2,4,2,1,1,2,10,11,2,2,3,1,24,31,4,10,10,2,5,12,16,164,15,4,16,7,9,15,19,17,1,2,1,1,5,1,1,1,1,1,3,1,4,3,1,3,1,3,1,2,1,1,3,3,7,
2,8,1,2,2,2,1,3,4,3,7,8,12,92,2,10,3,1,3,14,5,25,16,42,4,7,7,4,2,21,5,27,26,27,21,25,30,31,2,1,5,13,3,22,5,6,6,11,9,12,1,5,9,7,5,5,22,60,3,5,
13,1,1,8,1,1,3,3,2,1,9,3,3,18,4,1,2,3,7,6,3,1,2,3,9,1,3,1,3,2,1,3,1,1,1,2,1,11,3,1,6,9,1,3,2,3,1,2,1,5,1,1,4,3,4,1,2,2,4,4,1,7,2,1,2,2,3,5,13,
18,3,4,14,9,9,4,16,3,7,5,8,2,6,48,28,3,1,1,4,2,14,8,2,9,2,1,15,2,4,3,2,10,16,12,8,7,1,1,3,1,1,1,2,7,4,1,6,4,38,39,16,23,7,15,15,3,2,12,7,21,
37,27,6,5,4,8,2,10,8,8,6,5,1,2,1,3,24,1,16,17,9,23,10,17,6,1,51,55,44,13,294,9,3,6,2,4,2,2,15,1,1,1,13,21,17,68,14,8,9,4,1,4,9,3,11,7,1,1,1,
5,6,3,2,1,1,1,2,3,8,1,2,2,4,1,5,5,2,1,4,3,7,13,4,1,4,1,3,1,1,1,5,5,10,1,6,1,5,2,1,5,2,4,1,4,5,7,3,18,2,9,11,32,4,3,3,2,4,7,11,16,9,11,8,13,38,
32,8,4,2,1,1,2,1,2,4,4,1,1,1,4,1,21,3,11,1,16,1,1,6,1,3,2,4,9,8,57,7,44,1,3,3,13,3,10,1,1,7,5,2,7,21,47,63,3,15,4,7,1,16,1,1,2,8,2,3,42,15,4,
1,29,7,22,10,3,78,16,12,20,18,4,67,11,5,1,3,15,6,21,31,32,27,18,13,71,35,5,142,4,10,1,2,50,19,33,16,35,37,16,19,27,7,1,133,19,1,4,8,7,20,1,4,
4,1,10,3,1,6,1,2,51,5,40,15,24,43,22928,11,1,13,154,70,3,1,1,7,4,10,1,2,1,1,2,1,2,1,2,2,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,
3,2,1,1,1,1,2,1,1,
};
static ImWchar base_ranges[] = // not zero-terminated
{
0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
0x31F0, 0x31FF, // Katakana Phonetic Extensions
0xFF00, 0xFFEF // Half-width characters
};
static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 };
if (!full_ranges[0])
{
memcpy(full_ranges, base_ranges, sizeof(base_ranges));
UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges));
}
return &full_ranges[0];
}
const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic()
{
static const ImWchar ranges[] =
+1 -7
View File
@@ -1,9 +1,3 @@
<EngineDependencies versionnumber="1.0.0">
<Dependency path="textures/defaults/unchecked_nohover.tif" optional="true" />
<Dependency path="textures/defaults/unchecked_nohover.sprite" optional="true" />
<Dependency path="textures/defaults/checkmark.tif" optional="true" />
<Dependency path="textures/defaults/checkmark.sprite" optional="true" />
<Dependency path="textures/defaults/sliderManipulator.tif" optional="true" />
<Dependency path="textures/defaults/sliderManipulator.sprite" optional="true" />
<Dependency path="engineassets/textures/cursor_green.sprite" optional="true" />
<Dependency path="textures/cursor_default.tif" optional="true" />
</EngineDependencies>
@@ -1 +0,0 @@
/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a268774eb6d4d4590960c28edbf2a35d3fb7a73caab38d9ad15812c3df1c0c02
size 4529
@@ -0,0 +1,69 @@
<ObjectStream version="3">
<Class name="TextureSettings" version="1" type="{980132FF-C450-425D-8AE0-BD96A8486177}">
<Class name="AZ::Uuid" field="PresetID" value="{83003128-F63E-422B-AEC2-68F0A947225F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="SizeReduceLevel" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="bool" field="EngineReduce" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="EnableMipmap" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="MaintainAlphaCoverage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="AZStd::vector" field="MipMapAlphaAdjustments" type="{3349AACD-BE04-50BC-9478-528BF2ACFD55}">
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="MipMapGenEval" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="ImageProcessingAtom::MipGenType" field="MipMapGenType" value="1" type="{8524F650-1417-44DA-BBB0-C707A7A1A709}"/>
<Class name="AZStd::map" field="PlatformSpecificOverrides" type="{74E4843B-0924-583D-8C6E-A37B09BD51FE}">
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="android" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="ios" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="mac" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="pc" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
</Class>
<Class name="AZStd::string" field="OverridingPlatform" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</ObjectStream>
+1 -17
View File
@@ -1,28 +1,12 @@
<ObjectStream version="3">
<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{EFA11E15-FC2F-533B-9E73-6351C0E82EF2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/basic/button_sliced_normal.sprite" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{99FDCF74-F290-5367-BAE4-05AB38996ED8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="engineassets/textures/cursor_green.dds" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{E993215C-FF5F-5891-8475-D4EDBD560807}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/basic/button_sliced_normal.dds" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="AZStd::string" field="pathHint" value="textures/cursor_default.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-3
View File
@@ -112,7 +112,6 @@ enum class FusibleCommand
#include "FileHelpers.h"
#include "ComponentHelpers.h"
#include "HierarchyHelpers.h"
#include "PrefabHelpers.h"
#include "UiSliceManager.h"
#include "SelectionHelpers.h"
#include "ViewportInteraction.h"
@@ -173,8 +172,6 @@ bool ClipboardContainsOurDataType();
#define UICANVASEDITOR_COORDINATE_SYSTEM_CYCLE_SHORTCUT_KEY_SEQUENCE QKeySequence(Qt::CTRL + Qt::Key_W)
#define UICANVASEDITOR_SNAP_TO_GRID_TOGGLE_SHORTCUT_KEY_SEQUENCE QKeySequence(Qt::Key_G)
#define UICANVASEDITOR_PREFAB_EXTENSION "uiprefab"
#define UICANVASEDITOR_CANVAS_DIRECTORY "UI/Canvases"
#define UICANVASEDITOR_CANVAS_EXTENSION "uicanvas"
-13
View File
@@ -146,19 +146,6 @@ void EditorWindow::AddMenu_File()
menu->addSeparator();
// "Save as Prefab..." file menu option
{
HierarchyWidget* widget = GetHierarchy();
QAction* action = PrefabHelpers::CreateSavePrefabAction(widget);
action->setEnabled(canvasLoaded);
// This menu option is always available to the user
menu->addAction(action);
addAction(action); // Also add the action to the window until the shortcut dispatcher can find the menu action
}
menu->addSeparator();
// Close the active canvas
{
QAction* action = CreateCloseCanvasAction(GetCanvas());
-43
View File
@@ -128,7 +128,6 @@ EditorWindow::EditorWindow(QWidget* parent, Qt::WindowFlags flags)
, m_previewActionLogDockWidget(nullptr)
, m_previewAnimationListDockWidget(nullptr)
, m_editorMode(UiEditorMode::Edit)
, m_prefabFiles()
, m_actionsEnabledWithSelection()
, m_pasteAsSiblingAction(nullptr)
, m_pasteAsChildAction(nullptr)
@@ -160,8 +159,6 @@ EditorWindow::EditorWindow(QWidget* parent, Qt::WindowFlags flags)
connect(m_hierarchy, &HierarchyWidget::SetUserSelection, this, &EditorWindow::UpdateActionsEnabledState);
m_clipboardConnection = connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &EditorWindow::UpdateActionsEnabledState);
UpdatePrefabFiles();
// Create the cursor to be used when picking an element in the hierarchy or viewport during object pick mode.
// Uses the default hot spot which is the center of the image
m_entityPickerCursor = QCursor(QPixmap(UICANVASEDITOR_ENTITY_PICKER_CURSOR));
@@ -1551,46 +1548,6 @@ AssetTreeEntry* EditorWindow::GetSliceLibraryTree()
return m_sliceLibraryTree;
}
void EditorWindow::UpdatePrefabFiles()
{
m_prefabFiles.clear();
// IMPORTANT: ScanDirectory() is VERY slow. It can easily take as much
// as a whole second to execute. That's why we want to cache its result
// up front and ONLY access the cached data.
GetIEditor()->GetFileUtil()->ScanDirectory("", "*." UICANVASEDITOR_PREFAB_EXTENSION, m_prefabFiles);
SortPrefabsList();
}
IFileUtil::FileArray& EditorWindow::GetPrefabFiles()
{
return m_prefabFiles;
}
void EditorWindow::AddPrefabFile(const QString& prefabFilename)
{
IFileUtil::FileDesc fd;
fd.filename = prefabFilename;
m_prefabFiles.push_back(fd);
SortPrefabsList();
}
void EditorWindow::SortPrefabsList()
{
AZStd::sort<IFileUtil::FileArray::iterator>(m_prefabFiles.begin(), m_prefabFiles.end(),
[](const IFileUtil::FileDesc& fd1, const IFileUtil::FileDesc& fd2)
{
// Some of the files in the list are in different directories, so we
// explicitly sort by filename only.
AZStd::string fd1Filename;
AzFramework::StringFunc::Path::GetFileName(fd1.filename.toUtf8().data(), fd1Filename);
AZStd::string fd2Filename;
AzFramework::StringFunc::Path::GetFileName(fd2.filename.toUtf8().data(), fd2Filename);
return fd1Filename < fd2Filename;
});
}
void EditorWindow::ToggleEditorMode()
{
m_editorMode = (m_editorMode == UiEditorMode::Edit) ? UiEditorMode::Preview : UiEditorMode::Edit;
-9
View File
@@ -139,11 +139,6 @@ public: // member functions
AssetTreeEntry* GetSliceLibraryTree();
//! WARNING: This is a VERY slow function.
void UpdatePrefabFiles();
IFileUtil::FileArray& GetPrefabFiles();
void AddPrefabFile(const QString& prefabFilename);
//! Returns the current mode of the editor (Edit or Preview)
UiEditorMode GetEditorMode() { return m_editorMode; }
@@ -325,8 +320,6 @@ private: // member functions
QAction* CreateCloseAllOtherCanvasesAction(AZ::EntityId canvasEntityId, bool forContextMenu = false);
QAction* CreateCloseAllCanvasesAction(bool forContextMenu = false);
void SortPrefabsList();
void SaveModeSettings(UiEditorMode mode, bool syncSettings);
void RestoreModeSettings(UiEditorMode mode);
@@ -391,8 +384,6 @@ private: // data
//! This tree caches the folder view of all the slice assets under the slice library path
AssetTreeEntry* m_sliceLibraryTree = nullptr;
IFileUtil::FileArray m_prefabFiles;
//! Values for setting up undoable canvas/entity changes
SerializeHelpers::SerializedEntryList m_preChangeState;
bool m_haveValidEntitiesPreChangeState = false;
+1 -40
View File
@@ -26,8 +26,7 @@ HierarchyMenu::HierarchyMenu(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList selectedItems = hierarchy->selectedItems();
if (showMask & (Show::kNew_EmptyElement | Show::kNew_ElementFromPrefabs |
Show::kNew_EmptyElementAtRoot | Show::kNew_ElementFromPrefabsAtRoot))
if (showMask & (Show::kNew_EmptyElement | Show::kNew_EmptyElementAtRoot))
{
QMenu* menu = (addMenuForNewElement ? addMenu("&New...") : this);
@@ -40,11 +39,6 @@ HierarchyMenu::HierarchyMenu(HierarchyWidget* hierarchy,
{
New_ElementFromSlice(hierarchy, selectedItems, menu, (showMask & Show::kNew_InstantiateSliceAtRoot), optionalPos);
}
if (showMask & (Show::kNew_ElementFromPrefabs | Show::kNew_ElementFromPrefabsAtRoot))
{
New_ElementFromPrefabs(hierarchy, selectedItems, menu, (showMask & Show::kNew_ElementFromPrefabsAtRoot), optionalPos);
}
}
if (showMask & (Show::kNewSlice | Show::kPushToSlice))
@@ -52,11 +46,6 @@ HierarchyMenu::HierarchyMenu(HierarchyWidget* hierarchy,
SliceMenuItems(hierarchy, selectedItems, showMask);
}
if (showMask & Show::kSavePrefab)
{
SavePrefab(hierarchy, selectedItems);
}
addSeparator();
if (showMask & Show::kCutCopyPaste)
@@ -192,21 +181,6 @@ void HierarchyMenu::CutCopyPaste(HierarchyWidget* hierarchy,
}
}
void HierarchyMenu::SavePrefab(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems)
{
QAction* action = PrefabHelpers::CreateSavePrefabAction(hierarchy);
// Only enable "save as prefab" option if exactly one element is selected
// in the hierarchy pane
if (selectedItems.size() != 1)
{
action->setEnabled(false);
}
addAction(action);
}
void HierarchyMenu::SliceMenuItems(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems,
size_t showMask)
@@ -404,19 +378,6 @@ void HierarchyMenu::New_EmptyElement(HierarchyWidget* hierarchy,
optionalPos));
}
void HierarchyMenu::New_ElementFromPrefabs(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems,
QMenu* menu,
bool addAtRoot,
const QPoint* optionalPos)
{
PrefabHelpers::CreateAddPrefabMenu(hierarchy,
selectedItems,
menu,
addAtRoot,
optionalPos);
}
void HierarchyMenu::New_ElementFromSlice(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems,
QMenu* menu,
-11
View File
@@ -26,11 +26,8 @@ public:
kNone = 0x0000,
kCutCopyPaste = 0x0001,
kSavePrefab = 0x0002,
kNew_EmptyElement = 0x0004,
kNew_EmptyElementAtRoot = 0x0008,
kNew_ElementFromPrefabs = 0x0010,
kNew_ElementFromPrefabsAtRoot = 0x0020,
kAddComponents = 0x0040,
kDeleteElement = 0x0080,
kNewSlice = 0x0100,
@@ -52,9 +49,6 @@ private:
void CutCopyPaste(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems);
void SavePrefab(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems);
void SliceMenuItems(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems,
size_t showMask);
@@ -64,11 +58,6 @@ private:
QMenu* menu,
bool addAtRoot,
const QPoint* optionalPos);
void New_ElementFromPrefabs(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems,
QMenu* menu,
bool addAtRoot,
const QPoint* optionalPos);
void New_ElementFromSlice(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems,
QMenu* menu,
@@ -235,9 +235,7 @@ void HierarchyWidget::contextMenuEvent(QContextMenuEvent* ev)
{
HierarchyMenu contextMenu(this,
(HierarchyMenu::Show::kCutCopyPaste |
HierarchyMenu::Show::kSavePrefab |
HierarchyMenu::Show::kNew_EmptyElement |
HierarchyMenu::Show::kNew_ElementFromPrefabs |
HierarchyMenu::Show::kDeleteElement |
HierarchyMenu::Show::kNewSlice |
HierarchyMenu::Show::kNew_InstantiateSlice |
@@ -21,7 +21,6 @@ NewElementToolbarSection::NewElementToolbarSection(QToolBar* parent, bool addSep
{
HierarchyMenu contextMenu(editorWindow->GetHierarchy(),
(HierarchyMenu::Show::kNew_EmptyElementAtRoot |
HierarchyMenu::Show::kNew_ElementFromPrefabsAtRoot |
HierarchyMenu::Show::kNew_InstantiateSliceAtRoot),
false);
-199
View File
@@ -1,199 +0,0 @@
/*
* 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 "UiCanvasEditor_precompiled.h"
#include "EditorCommon.h"
#include "AzFramework/StringFunc/StringFunc.h"
#include "Util/PathUtil.h"
#include <QMessageBox>
#include <QFileDialog>
namespace PrefabHelpers
{
QAction* CreateSavePrefabAction(HierarchyWidget* hierarchy)
{
QAction* action = new QAction("(Deprecated) Save as Prefab...", hierarchy);
QObject::connect(action,
&QAction::triggered,
hierarchy,
[ hierarchy ]([[maybe_unused]] bool checked)
{
// Note that selectedItems() can be expensive, so call it once and save the value.
QTreeWidgetItemRawPtrQList selectedItems(hierarchy->selectedItems());
if (selectedItems.isEmpty())
{
QMessageBox(QMessageBox::Information,
"Selection Needed",
"Please select an element in the Hierarchy pane",
QMessageBox::Ok, hierarchy->GetEditorWindow()).exec();
return;
}
else if (selectedItems.size() > 1)
{
QMessageBox(QMessageBox::Information,
"Too Many Items Selected",
"Please select only one element in the Hierarchy pane",
QMessageBox::Ok, hierarchy->GetEditorWindow()).exec();
return;
}
QString selectedFile = QFileDialog::getSaveFileName(nullptr,
QString(),
FileHelpers::GetAbsoluteGameDir(),
"*." UICANVASEDITOR_PREFAB_EXTENSION,
nullptr,
QFileDialog::DontConfirmOverwrite);
if (selectedFile.isEmpty())
{
// Nothing to do.
return;
}
FileHelpers::AppendExtensionIfNotPresent(selectedFile, UICANVASEDITOR_PREFAB_EXTENSION);
AZ::EntityId canvasEntityId = hierarchy->GetEditorWindow()->GetCanvas();
// We've already checked if selectedItems is empty, so calling front() should be fine here
HierarchyItem* hierarchyItem = HierarchyItem::RttiCast(selectedItems.front());
AZ::Entity* element = hierarchyItem->GetElement();
// Check if this element is OK to save as a prefab
UiCanvasInterface::ErrorCode errorCode = UiCanvasInterface::ErrorCode::NoError;
EBUS_EVENT_ID_RESULT(errorCode, canvasEntityId, UiCanvasBus, CheckElementValidToSaveAsPrefab,
element);
if (errorCode != UiCanvasInterface::ErrorCode::NoError)
{
if (errorCode == UiCanvasInterface::ErrorCode::PrefabContainsExternalEntityRefs)
{
QMessageBox box(QMessageBox::Question,
"External references",
"The selected element contains references to elements that will not be in the prefab.\n"
"If saved these references will be cleared in the prefab.\n\n"
"Do you wish to save as prefab anyway?",
(QMessageBox::Yes | QMessageBox::No), hierarchy->GetEditorWindow());
box.setDefaultButton(QMessageBox::No);
int result = box.exec();
if (result == QMessageBox::No)
{
return;
}
}
else
{
// this should never happen, but will if we forget to update this code when a new error is
// added
QMessageBox(QMessageBox::Information,
"Cannot save as prefab",
"Unknown error",
QMessageBox::Ok, hierarchy->GetEditorWindow()).exec();
return;
}
}
FileHelpers::SourceControlAddOrEdit(selectedFile.toStdString().c_str(), hierarchy->GetEditorWindow());
bool saveSuccessful = false;
EBUS_EVENT_ID_RESULT(saveSuccessful, canvasEntityId, UiCanvasBus, SaveAsPrefab,
selectedFile.toStdString().c_str(), element);
// Refresh the menu to update "Add prefab...".
if (saveSuccessful)
{
QString gamePath(Path::FullPathToGamePath(selectedFile));
hierarchy->GetEditorWindow()->AddPrefabFile(gamePath);
return;
}
QMessageBox(QMessageBox::Critical,
"Error",
"Unable to save file. Is the file read-only?",
QMessageBox::Ok, hierarchy->GetEditorWindow()).exec();
});
return action;
}
void CreateAddPrefabMenu(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems,
QMenu* parent,
bool addAtRoot,
const QPoint* optionalPos)
{
// Find all the prefabs in the project directory and in any enabled Gems
IFileUtil::FileArray& files = hierarchy->GetEditorWindow()->GetPrefabFiles();
if (files.empty())
{
// Since this feature is deprecated we don't show the menu unles there are prefabs
return;
}
QMenu* prefabMenu = parent->addMenu(QString("(Deprecated) Element%1 from prefab").arg(!addAtRoot && selectedItems.size() > 1 ? "s" : ""));
QList<QAction*> result;
{
for (auto file : files)
{
// Get the filepath from the engine root directory
QString fullFileName = Path::GamePathToFullPath(file.filename);
QString filepath(fullFileName);
// Extract the filename without its extension, get it from fullFileName rather than
// file.filename because the former preserves case
AZStd::string filename;
AzFramework::StringFunc::Path::GetFileName(fullFileName.toUtf8().data(), filename);
QAction* action = new QAction(filename.c_str(), prefabMenu);
QObject::connect(action,
&QAction::triggered,
hierarchy,
[filepath, hierarchy, addAtRoot, optionalPos]([[maybe_unused]] bool checked)
{
if (addAtRoot)
{
hierarchy->clearSelection();
}
CommandHierarchyItemCreateFromData::Push(hierarchy->GetEditorWindow()->GetActiveStack(),
hierarchy,
hierarchy->selectedItems(),
true,
[hierarchy, filepath, optionalPos](HierarchyItem* parent,
LyShine::EntityArray& listOfNewlyCreatedTopLevelElements)
{
AZ::Entity* newEntity = nullptr;
EBUS_EVENT_ID_RESULT(newEntity,
hierarchy->GetEditorWindow()->GetCanvas(),
UiCanvasBus,
LoadFromPrefab,
filepath.toStdString().c_str(),
true,
(parent ? parent->GetElement() : nullptr));
if (newEntity)
{
if (optionalPos)
{
EntityHelpers::MoveElementToGlobalPosition(newEntity, *optionalPos);
}
listOfNewlyCreatedTopLevelElements.push_back(newEntity);
}
},
"Prefab");
});
result.push_back(action);
}
}
prefabMenu->addActions(result);
}
} // namespace PrefabHelpers
-18
View File
@@ -1,18 +0,0 @@
/*
* 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
namespace PrefabHelpers
{
QAction* CreateSavePrefabAction(HierarchyWidget* hierarchy);
void CreateAddPrefabMenu(HierarchyWidget* hierarchy,
QTreeWidgetItemRawPtrQList& selectedItems,
QMenu* parent,
bool addAtRoot,
const QPoint* optionalPos);
} // namespace PrefabHelpers
@@ -428,9 +428,7 @@ void ViewportWidget::contextMenuEvent(QContextMenuEvent* e)
const QPoint pos = e->pos();
HierarchyMenu contextMenu(m_editorWindow->GetHierarchy(),
HierarchyMenu::Show::kCutCopyPaste |
HierarchyMenu::Show::kSavePrefab |
HierarchyMenu::Show::kNew_EmptyElement |
HierarchyMenu::Show::kNew_ElementFromPrefabs |
HierarchyMenu::Show::kDeleteElement |
HierarchyMenu::Show::kNewSlice |
HierarchyMenu::Show::kNew_InstantiateSlice |
+2 -5
View File
@@ -536,22 +536,19 @@ AZ::Vector2 CDraw2d::Align(AZ::Vector2 position, AZ::Vector2 size,
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::Data::Instance<AZ::RPI::Image> CDraw2d::LoadTexture(const AZStd::string& pathName)
{
AZStd::string sourceRelativePath(pathName);
AZStd::string cacheRelativePath = sourceRelativePath + ".streamingimage";
// The file may not be in the AssetCatalog at this point if it is still processing or doesn't exist on disk.
// Use GenerateAssetIdTEMP instead of GetAssetIdByPath so that it will return a valid AssetId anyways
AZ::Data::AssetId streamingImageAssetId;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
streamingImageAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GenerateAssetIdTEMP,
sourceRelativePath.c_str());
pathName.c_str());
streamingImageAssetId.m_subId = AZ::RPI::StreamingImageAsset::GetImageAssetSubId();
auto streamingImageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset<AZ::RPI::StreamingImageAsset>(streamingImageAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
AZ::Data::Instance<AZ::RPI::Image> image = AZ::RPI::StreamingImage::FindOrCreate(streamingImageAsset);
if (!image)
{
AZ_Error("Draw2d", false, "Failed to find or create an image instance from image asset '%s'", streamingImageAsset.GetHint().c_str());
AZ_Error("Draw2d", false, "Failed to find or create an image instance from image asset '%s'", pathName.c_str());
}
return image;
@@ -135,7 +135,7 @@ namespace LyShine
////////////////////////////////////////////////////////////////////////////////////////////////////
LyShineSystemComponent::LyShineSystemComponent()
{
m_cursorImagePathname.SetAssetPath("engineassets/textures/cursor_green.tif");
m_cursorImagePathname.SetAssetPath("Textures/Cursor_Default.tif");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
+3 -169
View File
@@ -590,174 +590,6 @@ bool UiCanvasComponent::SaveToXml(const string& assetIdPathname, const string& s
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
UiCanvasInterface::ErrorCode UiCanvasComponent::CheckElementValidToSaveAsPrefab(AZ::Entity* entity)
{
AZ_Assert(entity, "null entity ptr passed to SaveAsPrefab");
// Check that none of the EntityId's in this entity or its children reference entities that
// are not part of the prefab.
// First make a list of all entityIds that will be in the prefab
AZStd::vector<AZ::EntityId> entitiesInPrefab = GetEntityIdsOfElementAndDescendants(entity);
// Next check all entity refs in the element to see if any are externel
// We use ReplaceEntityRefs even though we don't want to change anything
bool foundRefOutsidePrefab = false;
AZ::SerializeContext* context = nullptr;
EBUS_EVENT_RESULT(context, AZ::ComponentApplicationBus, GetSerializeContext);
AZ_Assert(context, "No serialization context found");
AZ::EntityUtils::ReplaceEntityRefs(entity, [&](const AZ::EntityId& key, bool /*isEntityId*/) -> AZ::EntityId
{
if (key.IsValid())
{
auto iter = AZStd::find(entitiesInPrefab.begin(), entitiesInPrefab.end(), key);
if (iter == entitiesInPrefab.end())
{
foundRefOutsidePrefab = true;
}
}
return key; // always leave key unchanged
}, context);
if (foundRefOutsidePrefab)
{
return UiCanvasInterface::ErrorCode::PrefabContainsExternalEntityRefs;
}
return UiCanvasInterface::ErrorCode::NoError;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool UiCanvasComponent::SaveAsPrefab(const string& pathname, AZ::Entity* entity)
{
AZ_Assert(entity, "null entity ptr passed to SaveAsPrefab");
AZ::SerializeContext* context = nullptr;
EBUS_EVENT_RESULT(context, AZ::ComponentApplicationBus, GetSerializeContext);
AZ_Assert(context, "No serialization context found");
// To be sure that we do not save an invalid prefab, if this entity contains entity references
// outside of the prefab set them to invalid references
// First make a list of all entityIds that will be in the prefab
AZStd::vector<AZ::EntityId> entitiesInPrefab = GetEntityIdsOfElementAndDescendants(entity);
// Next make a serializable object containing all the entities to save (in order to check for invalid refs)
AZ::SliceComponent::InstantiatedContainer sourceObjects(false);
for (const AZ::EntityId& id : entitiesInPrefab)
{
AZ::Entity* sourceEntity = nullptr;
EBUS_EVENT_RESULT(sourceEntity, AZ::ComponentApplicationBus, FindEntity, id);
if (sourceEntity)
{
sourceObjects.m_entities.push_back(sourceEntity);
}
}
// clone all the objects in order to replace external references
AZ::SliceComponent::InstantiatedContainer* clonedObjects = context->CloneObject(&sourceObjects);
AZ::Entity* clonedRootEntity = clonedObjects->m_entities[0];
// use ReplaceEntityRefs to replace external references with invalid IDs
// Note that we are not generating new IDs so we do not need to fixup internal references
AZ::EntityUtils::ReplaceEntityRefs(clonedObjects, [&](const AZ::EntityId& key, bool /*isEntityId*/) -> AZ::EntityId
{
if (key.IsValid())
{
auto iter = AZStd::find(entitiesInPrefab.begin(), entitiesInPrefab.end(), key);
if (iter == entitiesInPrefab.end())
{
return AZ::EntityId();
}
}
return key; // leave key unchanged
}, context);
// make a wrapper object around the prefab entity so that we have an opportunity to change what
// is in a prefab file in future.
UiSerialize::PrefabFileObject fileObject;
fileObject.m_rootEntityId = clonedRootEntity->GetId();
// add all of the entities that are not the root entity to a childEntities list
for (auto descendant : clonedObjects->m_entities)
{
fileObject.m_entities.push_back(descendant);
}
bool result = AZ::Utils::SaveObjectToFile(pathname.c_str(), AZ::ObjectStream::ST_XML, &fileObject);
// now delete the cloned entities we created, fixed up and saved
delete clonedObjects;
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::Entity* UiCanvasComponent::LoadFromPrefab(const string& pathname, bool makeUniqueName, AZ::Entity* optionalInsertionPoint)
{
AZ::Entity* newEntity = nullptr;
// Currently LoadObjectFromFile will hang if the file cannot be parsed
// (LMBR-10078). So first check that it is in the right format
if (!IsValidAzSerializedFile(pathname))
{
return nullptr;
}
// The top level object in the file is a wrapper object called PrefabFileObject
// this is to give us more protection against changes to what we store in the file in future
// NOTE: this read doesn't support pak files but that is OK because prefab files are an
// editor only feature.
UiSerialize::PrefabFileObject* fileObject =
AZ::Utils::LoadObjectFromFile<UiSerialize::PrefabFileObject>(pathname.c_str());
AZ_Assert(fileObject, "Failed to load prefab");
if (fileObject)
{
// We want new IDs so generate them and fixup all references within the list of entities
{
AZ::SerializeContext* context = nullptr;
EBUS_EVENT_RESULT(context, AZ::ComponentApplicationBus, GetSerializeContext);
AZ_Assert(context, "No serialization context found");
AZ::SliceComponent::EntityIdToEntityIdMap entityIdMap;
AZ::IdUtils::Remapper<AZ::EntityId>::GenerateNewIdsAndFixRefs(fileObject, entityIdMap, context);
}
// add all of the entities to this canvases EntityContext
m_entityContext->AddUiEntities(fileObject->m_entities);
EBUS_EVENT_RESULT(newEntity, AZ::ComponentApplicationBus, FindEntity, fileObject->m_rootEntityId);
delete fileObject; // we do not keep the file wrapper object around
if (makeUniqueName)
{
AZ::EntityId parentEntityId;
if (optionalInsertionPoint)
{
parentEntityId = optionalInsertionPoint->GetId();
}
AZStd::string uniqueName = GetUniqueChildName(parentEntityId, newEntity->GetName(), nullptr);
newEntity->SetName(uniqueName);
}
UiElementComponent* elementComponent = newEntity->FindComponent<UiElementComponent>();
AZ_Assert(elementComponent, "No element component found on prefab entity");
AZ::Entity* parent = (optionalInsertionPoint) ? optionalInsertionPoint : GetRootElement();
// recursively visit all the elements and set their canvas and parent pointers
elementComponent->FixupPostLoad(newEntity, this, parent, true);
// add this new entity as a child of the parent (insertionPoint or root)
UiElementComponent* parentElementComponent = parent->FindComponent<UiElementComponent>();
AZ_Assert(parentElementComponent, "No element component found on parent entity");
parentElementComponent->AddChild(newEntity);
}
return newEntity;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiCanvasComponent::FixupCreatedEntities(LyShine::EntityArray topLevelEntities, bool makeUniqueNamesAndIds, AZ::Entity* optionalInsertionPoint)
{
@@ -3695,6 +3527,7 @@ void UiCanvasComponent::CreateRenderTarget()
return;
}
#ifdef LYSHINE_ATOM_TODO // [LYN-3359] Support RTT using Atom
// Create a render target that this canvas will be rendered to.
// The render target size is the canvas size.
m_renderTargetHandle = gEnv->pRenderer->CreateRenderTarget(m_renderTargetName.c_str(),
@@ -3716,6 +3549,7 @@ void UiCanvasComponent::CreateRenderTarget()
ISystem::CrySystemNotificationBus::Handler::BusConnect();
}
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -3734,7 +3568,7 @@ void UiCanvasComponent::DestroyRenderTarget()
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiCanvasComponent::RenderCanvasToTexture()
{
#ifdef LYSHINE_ATOM_TODO
#ifdef LYSHINE_ATOM_TODO // [LYN-3359] Support RTT using Atom
if (m_renderTargetHandle <= 0)
{
return;
@@ -99,11 +99,6 @@ public: // member functions
AZ::EntityId FindInteractableToHandleEvent(AZ::Vector2 point) override;
bool SaveToXml(const string& assetIdPathname, const string& sourceAssetPathname) override;
bool SaveAsPrefab(const string& pathname, AZ::Entity* entity) override;
UiCanvasInterface::ErrorCode CheckElementValidToSaveAsPrefab(AZ::Entity* entity) override;
AZ::Entity* LoadFromPrefab(const string& pathname,
bool makeUniqueName,
AZ::Entity* optionalInsertionPoint) override;
void FixupCreatedEntities(LyShine::EntityArray topLevelEntities, bool makeUniqueNamesAndIds, AZ::Entity* optionalInsertionPoint) override;
void AddElement(AZ::Entity* element, AZ::Entity* parent, AZ::Entity* insertBefore) override;
void ReinitializeElements() override;
@@ -452,6 +452,7 @@ void UiFaderComponent::CreateOrResizeRenderTarget(const AZ::Vector2& pixelAligne
m_viewportTopLeft = pixelAlignedTopLeft;
m_viewportSize = renderTargetSize;
#ifdef LYSHINE_ATOM_TODO // [LYN-3359] Support RTT using Atom
// Check if the render target already exists
if (m_renderTargetHandle != -1)
{
@@ -494,6 +495,7 @@ void UiFaderComponent::CreateOrResizeRenderTarget(const AZ::Vector2& pixelAligne
DestroyRenderTarget();
}
}
#endif
// at this point either all render targets and depth surfaces are created or none are.
// If all succeeded then update the render target size
@@ -637,6 +639,7 @@ void UiFaderComponent::RenderRttFader(LyShine::IRenderGraph* renderGraph, UiElem
}
}
#ifdef LYSHINE_ATOM_TODO // [LYN-3359] Support RTT using Atom
// Add a primitive to render a quad using the render target we have created
{
// Set the texture and other render state required
@@ -650,6 +653,7 @@ void UiFaderComponent::RenderRttFader(LyShine::IRenderGraph* renderGraph, UiElem
renderGraph->AddPrimitive(&m_cachedPrimitive, texture,
isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode);
}
#endif
}
}
@@ -553,6 +553,7 @@ void UiMaskComponent::CreateOrResizeRenderTarget(const AZ::Vector2& pixelAligned
m_viewportTopLeft = pixelAlignedTopLeft;
m_viewportSize = renderTargetSize;
#ifdef LYSHINE_ATOM_TODO // [LYN-3359] Support RTT using Atom
// Check if the render target already exists
if (m_contentRenderTargetHandle != -1)
{
@@ -618,6 +619,7 @@ void UiMaskComponent::CreateOrResizeRenderTarget(const AZ::Vector2& pixelAligned
DestroyRenderTarget();
}
}
#endif
// at this point either all render targets and depth surfaces are created or none are.
// If all succeeded then update the render target size
@@ -803,6 +805,7 @@ void UiMaskComponent::RenderUsingGradientMask(LyShine::IRenderGraph* renderGraph
}
}
#ifdef LYSHINE_ATOM_TODO // [LYN-3359] Support RTT using Atom
// Add a primitive to do the alpha mask
{
// Set the texture and other render state required
@@ -817,6 +820,7 @@ void UiMaskComponent::RenderUsingGradientMask(LyShine::IRenderGraph* renderGraph
renderGraph->AddAlphaMaskPrimitive(&m_cachedPrimitive, texture, maskTexture,
isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode);
}
#endif
}
}
-53
View File
@@ -556,11 +556,6 @@ namespace UiSerialize
serializeContext->Class<CryStringT<char> >()->
Serializer(&AZ::Serialize::StaticInstance<CryStringTCharSerializer>::s_instance);
serializeContext->Class<PrefabFileObject>()
->Version(2, &PrefabFileObject::VersionConverter)
->Field("RootEntity", &PrefabFileObject::m_rootEntityId)
->Field("Entities", &PrefabFileObject::m_entities);
serializeContext->Class<AnimationData>()
->Version(1)
->Field("SerializeString", &AnimationData::m_serializeData);
@@ -607,54 +602,6 @@ namespace UiSerialize
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool PrefabFileObject::VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
if (classElement.GetVersion() == 1)
{
// this is an old UI prefab (prior to UI Slices). We need to move all of the owned child entities into a
// separate list and have the references to them be via entity ID
// Find the m_rootEntity in the PrefabFileObject, in the old format this is an entity,
// we will replace it with an entityId
int rootEntityIndex = classElement.FindElement(AZ_CRC("RootEntity", 0x3cead042));
if (rootEntityIndex == -1)
{
return false;
}
AZ::SerializeContext::DataElementNode& rootEntityNode = classElement.GetSubElement(rootEntityIndex);
// All UI element entities will be copied to this container and then added to the m_childEntities list
AZStd::vector<AZ::SerializeContext::DataElementNode> copiedEntities;
// recursively process the root element and all of its child elements, copying their child entities to the
// entities container and replacing them with EntityIds
if (!UiElementComponent::MoveEntityAndDescendantsToListAndReplaceWithEntityId(context, rootEntityNode, -1, copiedEntities))
{
return false;
}
// Create the child entities member (which is a generic vector)
using entityVector = AZStd::vector<AZ::Entity*>;
AZ::SerializeContext::ClassData* classData = AZ::SerializeGenericTypeInfo<entityVector>::GetGenericInfo()->GetClassData();
int entitiesIndex = classElement.AddElement(context, "Entities", *classData);
if (entitiesIndex == -1)
{
return false;
}
AZ::SerializeContext::DataElementNode& entitiesNode = classElement.GetSubElement(entitiesIndex);
// now add all of the copied entities to the entities vector node
for (AZ::SerializeContext::DataElementNode& entityElement : copiedEntities)
{
entityElement.SetName("element"); // all elements in the Vector should have this name
entitiesNode.AddElement(entityElement);
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Helper function to VersionConverter to move three state actions from the derived interactable
// to the interactable base class
-14
View File
@@ -16,20 +16,6 @@ namespace UiSerialize
//! Define the Cry and UI types for the AZ Serialize system
void ReflectUiTypes(AZ::ReflectContext* context);
//! Wrapper class for prefab file. This allows us to make changes to what the top
//! level objects are in the prefab file and do some conversion
//! NOTE: This is only used for old pre-slices UI prefabs
class PrefabFileObject
{
public:
virtual ~PrefabFileObject() { }
AZ_CLASS_ALLOCATOR(PrefabFileObject, AZ::SystemAllocator, 0);
AZ_RTTI(PrefabFileObject, "{C264CC6F-E50C-4813-AAE6-F7AB0B1774D0}");
static bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
AZ::EntityId m_rootEntityId;
AZStd::vector<AZ::Entity*> m_entities;
};
//! Wrapper class for animation system data file. This allows us to use the old Cry
//! serialize for the animation data
class AnimationData
@@ -62,7 +62,7 @@ public: // static member functions
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC("LegacyMeshService", 0xb462a299));
required.push_back(AZ_CRC("MeshService", 0x71d8a455));
required.push_back(AZ_CRC("UiCanvasRefService", 0xb4cb5ef4));
}
@@ -108,8 +108,6 @@ set(FILES
Editor/PivotPresets.h
Editor/PivotPresetsWidget.cpp
Editor/PivotPresetsWidget.h
Editor/PrefabHelpers.cpp
Editor/PrefabHelpers.h
Editor/PresetButton.cpp
Editor/PresetButton.h
Editor/PreviewActionLog.cpp
+3 -6
View File
@@ -22,7 +22,7 @@ ly_add_target(
Source
BUILD_DEPENDENCIES
PRIVATE
Gem::AudioSystem
Gem::AudioSystem.Static
PUBLIC
3rdParty::libsamplerate
Legacy::CryCommon
@@ -39,10 +39,7 @@ ly_add_target(
BUILD_DEPENDENCIES
PRIVATE
Gem::Microphone.Static
RUNTIME_DEPENDENCIES
Gem::AudioSystem
)
# The above "Microphone" target is used by all interactive applications
ly_create_alias(NAME Microphone.Clients NAMESPACE Gem TARGETS Gem::Microphone)
ly_create_alias(NAME Microphone.Tools NAMESPACE Gem TARGETS Gem::Microphone)
ly_create_alias(NAME Microphone.Clients NAMESPACE Gem TARGETS Gem::Microphone Gem::AudioSystem)
ly_create_alias(NAME Microphone.Tools NAMESPACE Gem TARGETS Gem::Microphone Gem::AudioSystem.Editor)
@@ -72,21 +72,24 @@ namespace Multiplayer
}
static void GatherNetEntities(
AzToolsFramework::Prefab::Instance* instance,
AZStd::vector<AZStd::pair<AZ::Entity*, AzToolsFramework::Prefab::Instance*>>& output)
AzToolsFramework::Prefab::Instance* instance,
AZStd::unordered_map<AZ::Entity*, AzToolsFramework::Prefab::Instance*>& entityToInstanceMap,
AZStd::vector<AZ::Entity*>& netEntities)
{
instance->GetEntities([instance, &output](AZStd::unique_ptr<AZ::Entity>& prefabEntity)
instance->GetEntities([instance, &entityToInstanceMap, &netEntities](AZStd::unique_ptr<AZ::Entity>& prefabEntity)
{
if (prefabEntity->FindComponent<NetBindComponent>())
{
output.push_back(AZStd::make_pair(prefabEntity.get(), instance));
AZ::Entity* entity = prefabEntity.get();
entityToInstanceMap[entity] = instance;
netEntities.push_back(entity);
}
return true;
});
instance->GetNestedInstances([&output](AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& nestedInstance)
instance->GetNestedInstances([&entityToInstanceMap, &netEntities](AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& nestedInstance)
{
GatherNetEntities(nestedInstance.get(), output);
GatherNetEntities(nestedInstance.get(), entityToInstanceMap, netEntities);
});
}
@@ -112,33 +115,32 @@ namespace Multiplayer
auto&& [object, networkSpawnable] =
ProcessedObjectStore::Create<AzFramework::Spawnable>(uniqueName, context.GetSourceUuid(), AZStd::move(serializer));
auto& netSpawnableEntities = networkSpawnable->GetEntities();
// Grab all net entities with their corresponding Instances to handle nested prefabs correctly
AZStd::vector<AZStd::pair<AZ::Entity*, AzToolsFramework::Prefab::Instance*>> netEntities;
GatherNetEntities(sourceInstance.get(), netEntities);
AZStd::unordered_map<AZ::Entity*, AzToolsFramework::Prefab::Instance*> netEntityToInstanceMap;
AZStd::vector<AZ::Entity*> prefabNetEntities;
GatherNetEntities(sourceInstance.get(), netEntityToInstanceMap, prefabNetEntities);
if (netEntities.empty())
if (prefabNetEntities.empty())
{
// No networked entities in the prefab, no need to do anything in this processor.
return;
}
// Instance container for net entities
AZStd::unique_ptr<Instance> networkInstance(aznew Instance());
networkInstance->SetTemplateSourcePath(AZ::IO::PathView(uniqueName));
// Sort the entities prior to processing. The entities will end up in the net spawnable in this order.
SpawnableUtils::SortEntitiesByTransformHierarchy(prefabNetEntities);
// Create an asset for our future network spawnable: this allows us to put references to the asset in the components
AZ::Data::Asset<AzFramework::Spawnable> networkSpawnableAsset;
networkSpawnableAsset.Create(networkSpawnable->GetId());
networkSpawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
// Each spawnable has a root meta-data entity at position 0, so starting net indices from 1
size_t netEntitiesIndexCounter = 1;
size_t netEntitiesIndexCounter = 0;
for (auto& entityInstancePair : netEntities)
for (auto* prefabEntity : prefabNetEntities)
{
AZ::Entity* prefabEntity = entityInstancePair.first;
Instance* instance = entityInstancePair.second;
Instance* instance = netEntityToInstanceMap[prefabEntity];
AZ::EntityId entityId = prefabEntity->GetId();
AZ::Entity* netEntity = instance->DetachEntity(entityId).release();
@@ -147,7 +149,11 @@ namespace Multiplayer
// Net entity will need a new ID to avoid IDs collision
netEntity->SetId(AZ::Entity::MakeId());
networkInstance->AddEntity(*netEntity);
netEntity->InvalidateDependencies();
netEntity->EvaluateDependencies();
// Insert the entity into the target net spawnable
netSpawnableEntities.emplace_back(netEntity);
// Use the old ID for the breadcrumb entity to keep parent-child relationship in the original spawnable
AZ::Entity* breadcrumbEntity = aznew AZ::Entity(entityId, netEntity->GetName());
@@ -185,37 +191,12 @@ namespace Multiplayer
}
// save the final result in the target Prefab DOM.
PrefabDom networkPrefab;
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*networkInstance, networkPrefab))
{
AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed.");
return;
}
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab))
{
AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed.");
return;
}
bool result = SpawnableUtils::CreateSpawnable(*networkSpawnable, networkPrefab);
if (result)
{
AzFramework::Spawnable::EntityList& entities = networkSpawnable->GetEntities();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
(*it)->InvalidateDependencies();
(*it)->EvaluateDependencies();
}
SpawnableUtils::SortEntitiesByTransformHierarchy(*networkSpawnable);
context.GetProcessedObjects().push_back(AZStd::move(object));
}
else
{
AZ_Error("Prefabs", false, "Failed to convert prefab '%.*s' to a spawnable.", AZ_STRING_ARG(prefabName));
context.ErrorEncountered();
}
context.GetProcessedObjects().push_back(AZStd::move(object));
}
}
@@ -45,11 +45,17 @@ namespace PhysX
hit.m_distance = pxHit.distance;
hit.m_resultFlags |= AzPhysics::SceneQuery::ResultFlags::Distance;
hit.m_position = PxMathConvert(pxHit.position);
hit.m_resultFlags |= AzPhysics::SceneQuery::ResultFlags::Position;
if (pxHit.flags & physx::PxHitFlag::ePOSITION)
{
hit.m_position = PxMathConvert(pxHit.position);
hit.m_resultFlags |= AzPhysics::SceneQuery::ResultFlags::Position;
}
hit.m_normal = PxMathConvert(pxHit.normal);
hit.m_resultFlags |= AzPhysics::SceneQuery::ResultFlags::Normal;
if (pxHit.flags & physx::PxHitFlag::eNORMAL)
{
hit.m_normal = PxMathConvert(pxHit.normal);
hit.m_resultFlags |= AzPhysics::SceneQuery::ResultFlags::Normal;
}
const ActorData* actorData = Utils::GetUserData(pxHit.actor);
hit.m_bodyHandle = actorData->GetBodyHandle();
@@ -348,6 +348,8 @@ namespace PhysX
{
const physx::PxTransform pose = PxMathConvert(shapecastRequest->m_start);
const physx::PxVec3 dir = PxMathConvert(shapecastRequest->m_direction.GetNormalized());
AZ_Warning("PhysXScene", (static_cast<AZ::u16>(shapecastRequest->m_hitFlags & AzPhysics::SceneQuery::HitFlags::MTD) != 0),
"Not having MTD set for shape scene queries may result in incorrect reporting of colliders that are in contact or intersect the initial pose of the sweep.");
const physx::PxHitFlags hitFlags = SceneQueryHelpers::GetPxHitFlags(shapecastRequest->m_hitFlags);
bool status = false;
@@ -19,7 +19,7 @@
#include <Builder/ScriptCanvasBuilderWorker.h>
#include <LyViewPaneNames.h>
// Undo this
// Undo this
AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option")
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
@@ -90,8 +90,8 @@ namespace ScriptCanvasEditor
void EditorAssetSystemComponent::Deactivate()
{
ScriptCanvas::Translation::RequestBus::Handler::BusDisconnect();
ScriptCanvas::Grammar::RequestBus::Handler::BusDisconnect();
ScriptCanvas::Grammar::RequestBus::Handler::BusDisconnect();
EditorAssetConversionBus::Handler::BusDisconnect();
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
m_editorAssetRegistry.Unregister();
@@ -119,8 +119,8 @@ namespace ScriptCanvasEditor
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> EditorAssetSystemComponent::LoadAsset(AZStd::string_view graphPath)
{
auto outcome = ScriptCanvasBuilder::LoadEditorAsset(graphPath);
auto outcome = ScriptCanvasBuilder::LoadEditorAsset(graphPath, AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
if (outcome.IsSuccess())
{
return outcome.GetValue();
@@ -21,8 +21,10 @@ namespace ScriptCanvas
void RuntimeAssetSystemComponent::Reflect(AZ::ReflectContext* context)
{
ScriptCanvas::RuntimeData::Reflect(context);
ScriptCanvas::SubgraphInterfaceData::Reflect(context);
RuntimeData::Reflect(context);
RuntimeDataOverrides::Reflect(context);
SubgraphInterfaceData::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<RuntimeAssetSystemComponent, AZ::Component>()
@@ -0,0 +1,376 @@
/*
* 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 <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <Builder/ScriptCanvasBuilder.h>
#include <Builder/ScriptCanvasBuilderWorker.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Grammar/AbstractCodeModel.h>
namespace ScriptCanvasBuilderCpp
{
void AppendTabs(AZStd::string& result, size_t depth)
{
for (size_t i = 0; i < depth; ++i)
{
result += "\t";
}
}
}
namespace ScriptCanvasBuilder
{
void BuildVariableOverrides::Clear()
{
m_source.Reset();
m_variables.clear();
m_entityIds.clear();
m_dependencies.clear();
}
void BuildVariableOverrides::CopyPreviousOverriddenValues(const BuildVariableOverrides& source)
{
for (auto& overriddenValue : m_overrides)
{
auto iter = AZStd::find_if(source.m_overrides.begin(), source.m_overrides.end(), [&overriddenValue](const auto& candidate) { return candidate.GetVariableId() == overriddenValue.GetVariableId(); });
if (iter != source.m_overrides.end())
{
overriddenValue.DeepCopy(*iter);
overriddenValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
overriddenValue.SetAllowSignalOnChange(false);
// check that a name update is not necessary anymore
}
}
//////////////////////////////////////////////////////////////////////////
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
// the above will provide the data to handle the cases where only certain dependency nodes were removed
// until then we do a sanity check, if any part of the depenecies were altered, assume no overrides are valid.
if (m_dependencies.size() != source.m_dependencies.size())
{
return;
}
else
{
for (size_t index = 0; index != m_dependencies.size(); ++index)
{
if (m_dependencies[index].m_source != source.m_dependencies[index].m_source)
{
return;
}
}
}
//////////////////////////////////////////////////////////////////////////
for (size_t index = 0; index != m_dependencies.size(); ++index)
{
m_dependencies[index].CopyPreviousOverriddenValues(source.m_dependencies[index]);
}
}
bool BuildVariableOverrides::IsEmpty() const
{
return m_variables.empty() && m_entityIds.empty() && m_dependencies.empty();
}
void BuildVariableOverrides::Reflect(AZ::ReflectContext* reflectContext)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
{
serializeContext->Class<BuildVariableOverrides>()
->Version(0)
->Field("source", &BuildVariableOverrides::m_source)
->Field("variables", &BuildVariableOverrides::m_variables)
->Field("entityId", &BuildVariableOverrides::m_entityIds)
->Field("overrides", &BuildVariableOverrides::m_overrides)
->Field("dependencies", &BuildVariableOverrides::m_dependencies)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class< BuildVariableOverrides>("Variables", "Variables exposed by the attached Script Canvas Graph")
->ClassElement(AZ::Edit::ClassElements::Group, "Variable Fields")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &BuildVariableOverrides::m_overrides, "Variables", "Array of Variables within Script Canvas Graph")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &BuildVariableOverrides::m_dependencies, "Dependencies", "Variables in Dependencies of the Script Canvas Graph")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
;
}
}
}
// use this to initialize the new data, and make sure they have a editor graph variable for proper editor display
void BuildVariableOverrides::PopulateFromParsedResults(const ScriptCanvas::Grammar::ParsedRuntimeInputs& inputs, const ScriptCanvas::VariableData& variables)
{
for (auto& variable : inputs.m_variables)
{
auto graphVariable = variables.FindVariable(variable.first);
if (!graphVariable)
{
AZ_Error("ScriptCanvasBuilder", false, "Missing Variable from graph data that was just parsed");
continue;
}
m_variables.push_back(*graphVariable);
auto& buildVariable = m_variables.back();
buildVariable.DeepCopy(*graphVariable); // in case of BCO, a new one needs to be created
// copy to override list for editor display
m_overrides.push_back(*graphVariable);
auto& overrideValue = m_overrides.back();
overrideValue.DeepCopy(*graphVariable);
overrideValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
overrideValue.SetAllowSignalOnChange(false);
}
for (auto& entityId : inputs.m_entityIds)
{
m_entityIds.push_back(entityId);
if (!ScriptCanvas::Grammar::IsParserGeneratedId(entityId.first))
{
auto graphEntityId = variables.FindVariable(entityId.first);
if (!graphEntityId)
{
AZ_Error("ScriptCanvasBuilder", false, "Missing EntityId from graph data that was just parsed");
continue;
}
// copy to override list for editor display
if (graphEntityId->IsComponentProperty())
{
m_overrides.push_back(*graphEntityId);
auto& overrideValue = m_overrides.back();
overrideValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
overrideValue.SetAllowSignalOnChange(false);
}
}
}
}
EditorAssetTree* EditorAssetTree::ModRoot()
{
if (!m_parent)
{
return this;
}
return m_parent->ModRoot();
}
void EditorAssetTree::SetParent(EditorAssetTree& parent)
{
m_parent = &parent;
}
AZStd::string EditorAssetTree::ToString(size_t depth) const
{
AZStd::string result;
ScriptCanvasBuilderCpp::AppendTabs(result, depth);
result += m_asset.GetId().ToString<AZStd::string>();
result += m_asset.GetHint();
depth += m_dependencies.empty() ? 0 : 1;
for (const auto& dependency : m_dependencies)
{
result += "\n";
ScriptCanvasBuilderCpp::AppendTabs(result, depth);
result += dependency.ToString(depth);
}
return result;
}
ScriptCanvas::RuntimeDataOverrides ConvertToRuntime(const BuildVariableOverrides& buildOverrides)
{
ScriptCanvas::RuntimeDataOverrides runtimeOverrides;
runtimeOverrides.m_runtimeAsset = AZ::Data::Asset<ScriptCanvas::RuntimeAsset>
(AZ::Data::AssetId(buildOverrides.m_source.GetId().m_guid, AZ_CRC("RuntimeData", 0x163310ae)), azrtti_typeid<ScriptCanvas::RuntimeAsset>(), {});
runtimeOverrides.m_runtimeAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
runtimeOverrides.m_variableIndices.resize(buildOverrides.m_variables.size());
for (size_t index = 0; index != buildOverrides.m_variables.size(); ++index)
{
auto& variable = buildOverrides.m_variables[index];
auto iter = AZStd::find_if
( buildOverrides.m_overrides.begin()
, buildOverrides.m_overrides.end()
, [&variable](auto& candidate) { return candidate.GetVariableId() == variable.GetVariableId(); });
if (iter != buildOverrides.m_overrides.end())
{
if (iter->GetDatum())
{
runtimeOverrides.m_variables.push_back(ScriptCanvas::RuntimeVariable(iter->GetDatum()->ToAny()));
runtimeOverrides.m_variableIndices[index] = true;
}
else
{
AZ_Warning("ScriptCanvasBuilder", false, "build overrides missing variable override, Script may not function properly");
runtimeOverrides.m_variableIndices[index] = false;
}
}
else
{
runtimeOverrides.m_variableIndices[index] = false;
}
}
for (auto& entity : buildOverrides.m_entityIds)
{
auto& variableId = entity.first;
auto iter = AZStd::find_if(buildOverrides.m_overrides.begin(), buildOverrides.m_overrides.end(), [&variableId](auto& candidate) { return candidate.GetVariableId() == variableId; });
if (iter != buildOverrides.m_overrides.end())
{
// the entity was overridden on the instance
if (iter->GetDatum() && iter->GetDatum()->GetAs<AZ::EntityId>())
{
runtimeOverrides.m_entityIds.push_back(*iter->GetDatum()->GetAs<AZ::EntityId>());
}
else
{
AZ_Warning("ScriptCanvasBuilder", false, "build overrides missing EntityId, Script may not function properly");
runtimeOverrides.m_entityIds.push_back(AZ::EntityId{});
}
}
else
{
// the entity is overridden, as part of the required process of to instantiation
runtimeOverrides.m_entityIds.push_back(entity.second);
}
}
for (auto& buildDependency : buildOverrides.m_dependencies)
{
runtimeOverrides.m_dependencies.push_back(ConvertToRuntime(buildDependency));
}
return runtimeOverrides;
}
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(AZ::Data::AssetId editorAssetId, AZStd::string_view assetHint, EditorAssetTree* parent)
{
EditorAssetTree result;
AZ::Data::AssetInfo assetInfo;
AZStd::string watchFolder;
bool resultFound = false;
if (!AzToolsFramework::AssetSystemRequestBus::FindFirstHandler())
{
return AZ::Failure(AZStd::string("LoadEditorAssetTree found no handler for AzToolsFramework::AssetSystemRequestBus."));
}
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( resultFound
, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourceUUID
, editorAssetId.m_guid
, assetInfo
, watchFolder);
if (!resultFound)
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to get engine relative path from %s-%.*s.", editorAssetId.ToString<AZStd::string>().c_str(), aznumeric_cast<int>(assetHint.size()), assetHint.data()));
}
AZStd::vector<AZ::Data::AssetId> dependentAssets;
auto filterCB = [&dependentAssets](const AZ::Data::AssetFilterInfo& filterInfo)->bool
{
if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>())
{
dependentAssets.push_back(AZ::Data::AssetId(filterInfo.m_assetId.m_guid, 0));
}
else if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>())
{
dependentAssets.push_back(filterInfo.m_assetId);
}
return true;
};
auto loadAssetOutcome = ScriptCanvasBuilder::LoadEditorAsset(assetInfo.m_relativePath, editorAssetId, filterCB);
if (!loadAssetOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load graph from %s-%s: %s", editorAssetId.ToString<AZStd::string>().c_str(), assetHint.data(), loadAssetOutcome.GetError().c_str()));
}
for (auto& dependentAsset : dependentAssets)
{
auto loadDependentOutcome = LoadEditorAssetTree(dependentAsset, "", &result);
if (!loadDependentOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load dependent graph from %s-%s: %s", editorAssetId.ToString<AZStd::string>().c_str(), assetHint.data(), loadDependentOutcome.GetError().c_str()));
}
result.m_dependencies.push_back(loadDependentOutcome.TakeValue());
}
if (parent)
{
result.SetParent(*parent);
}
result.m_asset = loadAssetOutcome.TakeValue();
return AZ::Success(result);
}
AZ::Outcome<BuildVariableOverrides, AZStd::string> ParseEditorAssetTree(const EditorAssetTree& editorAssetTree)
{
auto buildEntity = editorAssetTree.m_asset->GetScriptCanvasEntity();
if (!buildEntity)
{
return AZ::Failure(AZStd::string("No entity from source asset"));
}
auto variableComponent = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::GraphVariableManagerComponent>(buildEntity);
if (!variableComponent)
{
return AZ::Failure(AZStd::string("No GraphVariableManagerComponent in source Entity"));
}
const ScriptCanvas::VariableData* variableData = variableComponent->GetVariableDataConst(); // get this from the entity
if (!variableData)
{
return AZ::Failure(AZStd::string("No variableData in source GraphVariableManagerComponent"));
}
auto parseOutcome = ScriptCanvasBuilder::ParseGraph(*buildEntity, "");
if (!parseOutcome.IsSuccess() || !parseOutcome.GetValue())
{
return AZ::Failure(AZStd::string("graph failed to parse"));
}
BuildVariableOverrides result;
result.m_source = editorAssetTree.m_asset;
result.PopulateFromParsedResults(parseOutcome.GetValue()->GetRuntimeInputs(), *variableData);
// recurse...
for (auto& dependentAsset : editorAssetTree.m_dependencies)
{
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
auto parseDependentOutcome = ParseEditorAssetTree(dependentAsset);
if (!parseDependentOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format
("ParseEditorAssetTree failed to parse dependent graph from %s-%s: %s"
, dependentAsset.m_asset.GetId().ToString<AZStd::string>().c_str()
, dependentAsset.m_asset.GetHint().c_str()
, parseDependentOutcome.GetError().c_str()));
}
result.m_dependencies.push_back(parseDependentOutcome.TakeValue());
}
return AZ::Success(result);
}
}
@@ -0,0 +1,82 @@
/*
* 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/Asset/AssetCommon.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Variable/VariableCore.h>
namespace ScriptCanvas
{
namespace Grammar
{
struct ParsedRuntimeInputs;
}
}
namespace ScriptCanvasEditor
{
class ScriptCanvasAsset;
}
namespace ScriptCanvasBuilder
{
class BuildVariableOverrides
{
public:
AZ_TYPE_INFO(BuildVariableOverrides, "{8336D44C-8EDC-4C28-AEB4-3420D5FD5AE2}");
AZ_CLASS_ALLOCATOR(BuildVariableOverrides, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* reflectContext);
void Clear();
// use this to preserve old values that may have been overridden on the instance, and are still valid in the parsed graph
void CopyPreviousOverriddenValues(const BuildVariableOverrides& source);
bool IsEmpty() const;
// use this to initialize the new data, and make sure they have a editor graph variable for proper editor display
void PopulateFromParsedResults(const ScriptCanvas::Grammar::ParsedRuntimeInputs& inputs, const ScriptCanvas::VariableData& variables);
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> m_source;
// all of the variables here are overrides
AZStd::vector<ScriptCanvas::GraphVariable> m_variables;
// the values here may or may not be overrides
AZStd::vector<AZStd::pair<ScriptCanvas::VariableId, AZ::EntityId>> m_entityIds;
// this is all that gets exposed to the edit context
AZStd::vector<ScriptCanvas::GraphVariable> m_overrides;
// AZStd::vector<size_t> m_entityIdRuntimeInputIndices; since all of the entity ids need to go in, they may not need indices
AZStd::vector<BuildVariableOverrides> m_dependencies;
};
class EditorAssetTree
{
public:
AZ_CLASS_ALLOCATOR(EditorAssetTree, AZ::SystemAllocator, 0);
EditorAssetTree* m_parent = nullptr;
AZStd::vector<EditorAssetTree> m_dependencies;
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> m_asset;
EditorAssetTree* ModRoot();
void SetParent(EditorAssetTree& parent);
AZStd::string ToString(size_t depth = 0) const;
};
// copy the variables overridden during editor / prefab build time back to runtime data
ScriptCanvas::RuntimeDataOverrides ConvertToRuntime(const BuildVariableOverrides& overrides);
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(AZ::Data::AssetId editorAssetId, AZStd::string_view assetHint, EditorAssetTree* parent = nullptr);
AZ::Outcome<BuildVariableOverrides, AZStd::string> ParseEditorAssetTree(const EditorAssetTree& editorAssetTree);
}
@@ -10,6 +10,7 @@
#include <AssetBuilderSDK/AssetBuilderBusses.h>
#include <AzCore/std/containers/map.h>
#include <AzToolsFramework/ToolsComponents/ToolsAssetCatalogBus.h>
#include <Builder/ScriptCanvasBuilder.h>
#include <Builder/ScriptCanvasBuilderComponent.h>
#include <Builder/ScriptCanvasBuilderWorker.h>
#include <ScriptCanvas/Asset/Functions/RuntimeFunctionAssetHandler.h>
@@ -163,6 +164,8 @@ namespace ScriptCanvasBuilder
void PluginComponent::Reflect(AZ::ReflectContext* context)
{
BuildVariableOverrides::Reflect(context);
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<PluginComponent, AZ::Component>()
@@ -70,6 +70,7 @@ namespace ScriptCanvasBuilder
AZ_Warning(s_scriptCanvasBuilder, false, "CreateJobs for \"%s\" failed because the source file could not be opened.", fullPath.data());
return;
}
AZStd::vector<AZ::u8> fileBuffer(ioStream.GetLength());
size_t bytesRead = ioStream.Read(fileBuffer.size(), fileBuffer.data());
if (bytesRead != ioStream.GetLength())
@@ -87,15 +88,15 @@ namespace ScriptCanvasBuilder
{
// force load these before processing
if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>()
|| filterInfo.m_assetType == azrtti_typeid<ScriptEvents::ScriptEventsAsset>())
|| filterInfo.m_assetType == azrtti_typeid<ScriptEvents::ScriptEventsAsset>())
{
this->m_processEditorAssetDependencies.push_back(filterInfo);
}
// these trigger re-processing
if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>()
|| filterInfo.m_assetType == azrtti_typeid<ScriptEvents::ScriptEventsAsset>()
|| filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>())
|| filterInfo.m_assetType == azrtti_typeid<ScriptEvents::ScriptEventsAsset>()
|| filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>())
{
AssetBuilderSDK::SourceFileDependency dependency;
dependency.m_sourceFileDependencyUUID = filterInfo.m_assetId.m_guid;
@@ -210,7 +211,7 @@ namespace ScriptCanvasBuilder
bool pathFound = false;
AZStd::string relativePath;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( pathFound
(pathFound
, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath
, request.m_fullPath.c_str(), relativePath);
@@ -55,6 +55,8 @@ namespace ScriptCanvasBuilder
DependencyArguments,
DependencyRequirementsData,
AddAssetDependencySearch,
PrefabIntegration,
CorrectGraphVariableVersion,
// add new entries above
Current,
};
@@ -130,10 +132,12 @@ namespace ScriptCanvasBuilder
int GetBuilderVersion();
AZ::Outcome<AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view graphPath);
AZ::Outcome<AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view graphPath, AZ::Data::AssetId assetId, AZ::Data::AssetFilterCB assetFilterCB = {});
AZ::Outcome<AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasFunctionAsset>, AZStd::string> LoadEditorFunctionAsset(AZStd::string_view graphPath);
AZ::Outcome<ScriptCanvas::Grammar::AbstractCodeModelConstPtr, AZStd::string> ParseGraph(AZ::Entity& buildEntity, AZStd::string_view graphPath);
AZ::Outcome<void, AZStd::string> ProcessTranslationJob(ProcessTranslationJobInput& input);
ScriptCanvasEditor::Graph* PrepareSourceGraph(AZ::Entity* const buildEntity);
@@ -149,7 +153,7 @@ namespace ScriptCanvasBuilder
{
public:
static AZ::Uuid GetUUID();
Worker() = default;
Worker(const Worker&) = delete;
@@ -175,7 +179,7 @@ namespace ScriptCanvasBuilder
// cached on first time query
mutable AZStd::string m_fingerprintString;
};
class FunctionWorker
: public AssetBuilderSDK::AssetBuilderCommandBus::Handler
{
@@ -195,7 +199,7 @@ namespace ScriptCanvasBuilder
int GetVersionNumber() const;
void ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const;
void ShutDown() override {};
private:
@@ -17,9 +17,7 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Script/ScriptComponent.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <Builder/ScriptCanvasBuilderWorker.h>
#include <ScriptCanvas/Asset/Functions/RuntimeFunctionAssetHandler.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Asset/RuntimeAssetHandler.h>
@@ -32,7 +30,6 @@
#include <ScriptCanvas/Grammar/AbstractCodeModel.h>
#include <ScriptCanvas/Results/ErrorText.h>
#include <ScriptCanvas/Utils/BehaviorContextUtils.h>
#include <Source/Components/SceneComponent.h>
namespace ScriptCanvasBuilder
@@ -62,6 +59,26 @@ namespace ScriptCanvasBuilder
}
}
AZ::Outcome<ScriptCanvas::Grammar::AbstractCodeModelConstPtr, AZStd::string> ParseGraph(AZ::Entity& buildEntity, AZStd::string_view graphPath)
{
AZStd::string fileNameOnly;
AzFramework::StringFunc::Path::GetFullFileName(graphPath.data(), fileNameOnly);
ScriptCanvas::Grammar::Request request;
request.graph = PrepareSourceGraph(&buildEntity);
if (!request.graph)
{
return AZ::Failure(AZStd::string("build entity did not have source graph components"));
}
request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFileAtPrefabTime;
request.printModelToConsole = ScriptCanvas::Grammar::g_printAbstractCodeModelAtPrefabTime;
request.name = fileNameOnly.empty() ? fileNameOnly : "BuilderGraph";
request.addDebugInformation = false;
return ScriptCanvas::Translation::ParseGraph(request);
}
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(AZ::Entity* buildEntity, AZ::Data::AssetId scriptAssetId, AZStd::string_view rawLuaFilePath)
{
AZStd::string fullPath(rawLuaFilePath);
@@ -72,7 +89,7 @@ namespace ScriptCanvasBuilder
auto sourceGraph = PrepareSourceGraph(buildEntity);
ScriptCanvas::Grammar::Request request;
request.assetId = scriptAssetId;
request.scriptAssetId = scriptAssetId;
request.graph = sourceGraph;
request.name = fileNameOnly;
request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile;
@@ -82,7 +99,7 @@ namespace ScriptCanvasBuilder
bool pathFound = false;
AZStd::string relativePath;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( pathFound
(pathFound
, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath
, fullPath.c_str(), relativePath);
@@ -396,7 +413,7 @@ namespace ScriptCanvasBuilder
;
}
AZ::Outcome < AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view filePath)
AZ::Outcome < AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view filePath, AZ::Data::AssetId assetId, AZ::Data::AssetFilterCB assetFilterCB)
{
AZStd::shared_ptr<AZ::Data::AssetDataStream> assetDataStream = AZStd::make_shared<AZ::Data::AssetDataStream>();
@@ -425,9 +442,9 @@ namespace ScriptCanvasBuilder
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> asset;
asset.Create(AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
asset.Create(assetId);
if (editorAssetHandler.LoadAssetData(asset, assetDataStream, AZ::Data::AssetFilterCB{}) != AZ::Data::AssetHandler::LoadResult::LoadComplete)
if (editorAssetHandler.LoadAssetData(asset, assetDataStream, assetFilterCB) != AZ::Data::AssetHandler::LoadResult::LoadComplete)
{
return AZ::Failure(AZStd::string::format("Failed to load ScriptCavas asset: %s", filePath.data()));
}
@@ -513,10 +530,7 @@ namespace ScriptCanvasBuilder
}
}
if (buildEntity->GetState() == AZ::Entity::State::Constructed)
{
buildEntity->Init();
}
ScriptCanvas::ScopedAuxiliaryEntityHandler entityHandler(buildEntity);
if (buildEntity->GetState() == AZ::Entity::State::Init)
{
@@ -533,7 +547,7 @@ namespace ScriptCanvasBuilder
auto version = sourceGraph->GetVersion();
if (version.grammarVersion == ScriptCanvas::GrammarVersion::Initial
|| version.runtimeVersion == ScriptCanvas::RuntimeVersion::Initial)
|| version.runtimeVersion == ScriptCanvas::RuntimeVersion::Initial)
{
return AZ::Failure(AZStd::string(ScriptCanvas::ParseErrors::SourceUpdateRequired));
}
@@ -542,7 +556,7 @@ namespace ScriptCanvasBuilder
request.path = input.fullPath;
request.name = input.fileNameOnly;
request.namespacePath = input.namespacePath;
request.assetId = input.assetID;
request.scriptAssetId = input.assetID;
request.graph = sourceGraph;
request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile;
request.printModelToConsole = ScriptCanvas::Grammar::g_printAbstractCodeModel;
@@ -728,6 +742,6 @@ namespace ScriptCanvasBuilder
ScriptCanvas::Translation::Result TranslateToLua(ScriptCanvas::Grammar::Request& request)
{
request.translationTargetFlags = ScriptCanvas::Translation::TargetFlags::Lua;
return ScriptCanvas::Translation::ParseGraph(request);
return ScriptCanvas::Translation::ParseAndTranslateGraph(request);
}
}
@@ -19,19 +19,30 @@
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Core/ScriptCanvasBus.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
#include <ScriptCanvas/Core/Node.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <ScriptCanvas/PerformanceStatisticsBus.h>
namespace EditorScriptCanvasComponentCpp
{
enum Version
{
PrefabIntegration = 10,
// add description above
Current
};
}
namespace ScriptCanvasEditor
{
static bool EditorScriptCanvasComponentVersionConverter(AZ::SerializeContext& serializeContext, AZ::SerializeContext::DataElementNode& rootElement)
@@ -74,6 +85,63 @@ namespace ScriptCanvasEditor
rootElement.RemoveElementByName(AZ_CRC("m_variableEntityIdMap", 0xdc6c75a8));
}
if (rootElement.GetVersion() <= EditorScriptCanvasComponentCpp::Version::PrefabIntegration)
{
auto variableDataElementIndex = rootElement.FindElement(AZ_CRC_CE("m_variableData"));
if (variableDataElementIndex == -1)
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: 'm_variableData' index was missing");
return false;
}
auto& variableDataElement = rootElement.GetSubElement(variableDataElementIndex);
ScriptCanvas::EditableVariableData editableData;
if (!variableDataElement.GetData(editableData))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: could not retrieve old 'm_variableData'");
return false;
}
auto scriptCanvasAssetHolderElementIndex = rootElement.FindElement(AZ_CRC_CE("m_assetHolder"));
if (scriptCanvasAssetHolderElementIndex == -1)
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: 'm_assetHolder' index was missing");
return false;
}
auto& scriptCanvasAssetHolderElement = rootElement.GetSubElement(scriptCanvasAssetHolderElementIndex);
ScriptCanvasAssetHolder assetHolder;
if (!scriptCanvasAssetHolderElement.GetData(assetHolder))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: could not retrieve old 'm_assetHolder'");
return false;
}
rootElement.RemoveElement(variableDataElementIndex);
if (!rootElement.AddElementWithData(serializeContext, "runtimeDataIsValid", true))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: failed to add 'runtimeDataIsValid'");
return false;
}
ScriptCanvasBuilder::BuildVariableOverrides overrides;
overrides.m_source = AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>(assetHolder.GetAssetId(), assetHolder.GetAssetType(), assetHolder.GetAssetHint());;
for (auto& variable : editableData.GetVariables())
{
overrides.m_overrides.push_back(variable.m_graphVariable);
}
if (!rootElement.AddElementWithData(serializeContext, "runtimeDataOverrides", overrides))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: failed to add 'runtimeDataOverrides'");
return false;
}
}
return true;
}
@@ -83,10 +151,11 @@ namespace ScriptCanvasEditor
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<EditorScriptCanvasComponent, EditorComponentBase>()
->Version(8, &EditorScriptCanvasComponentVersionConverter)
->Version(EditorScriptCanvasComponentCpp::Version::Current, &EditorScriptCanvasComponentVersionConverter)
->Field("m_name", &EditorScriptCanvasComponent::m_name)
->Field("m_assetHolder", &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder)
->Field("m_variableData", &EditorScriptCanvasComponent::m_editableData)
->Field("runtimeDataIsValid", &EditorScriptCanvasComponent::m_runtimeDataIsValid)
->Field("runtimeDataOverrides", &EditorScriptCanvasComponent::m_variableOverrides)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@@ -103,9 +172,9 @@ namespace ScriptCanvasEditor
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Level", 0x9aeacc13))
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/script-canvas/")
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder, "Script Canvas Asset", "Script Canvas asset associated with this component")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_editableData, "Properties", "Script Canvas Graph Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_variableOverrides, "Properties", "Script Canvas Graph Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
;
}
}
@@ -133,6 +202,11 @@ namespace ScriptCanvasEditor
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
}
const AZStd::string& EditorScriptCanvasComponent::GetName() const
{
return m_name;
}
void EditorScriptCanvasComponent::UpdateName()
{
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
@@ -208,18 +282,7 @@ namespace ScriptCanvasEditor
if (fileAssetId.IsValid())
{
AssetTrackerNotificationBus::Handler::BusConnect(fileAssetId);
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, fileAssetId);
if (memoryAsset && memoryAsset->GetAsset().GetStatus() == AZ::Data::AssetData::AssetStatus::Ready)
{
OnScriptCanvasAssetReady(memoryAsset);
}
else
{
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::Load, m_scriptCanvasAssetHolder.GetAssetId(), m_scriptCanvasAssetHolder.GetAssetType(), nullptr);
}
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
}
}
@@ -233,81 +296,67 @@ namespace ScriptCanvasEditor
EditorComponentBase::Deactivate();
//EditorScriptCanvasAssetNotificationBus::Handler::BusDisconnect();
EditorScriptCanvasComponentRequestBus::Handler::BusDisconnect();
EditorContextMenuRequestBus::Handler::BusDisconnect();
}
//=========================================================================
void EditorScriptCanvasComponent::BuildGameEntityData()
{
using namespace ScriptCanvasBuilder;
m_runtimeDataIsValid = false;
auto assetTreeOutcome = LoadEditorAssetTree(m_scriptCanvasAssetHolder.GetAssetId(), m_scriptCanvasAssetHolder.GetAssetHint());
if (!assetTreeOutcome.IsSuccess())
{
AZ_Warning("ScriptCanvas", false, "EditorScriptCanvasComponent::BuildGameEntityData failed: %s", assetTreeOutcome.GetError().c_str());
return;
}
EditorAssetTree& editorAssetTree = assetTreeOutcome.GetValue();
auto parseOutcome = ParseEditorAssetTree(editorAssetTree);
if (!parseOutcome.IsSuccess())
{
AZ_Warning("ScriptCanvas", false, "EditorScriptCanvasComponent::BuildGameEntityData failed: %s", parseOutcome.GetError().c_str());
return;
}
auto& variableOverrides = parseOutcome.GetValue();
if (!m_variableOverrides.IsEmpty())
{
variableOverrides.CopyPreviousOverriddenValues(m_variableOverrides);
}
m_variableOverrides = parseOutcome.TakeValue();
m_runtimeDataIsValid = true;
}
void EditorScriptCanvasComponent::BuildGameEntity(AZ::Entity* gameEntity)
{
AZ::Data::AssetId editorAssetId = m_scriptCanvasAssetHolder.GetAssetId();
if (!editorAssetId.IsValid())
if (!m_runtimeDataIsValid)
{
// this is fine, there could have been no graph set, or set to a graph that failed to compile
return;
}
AZ::Data::AssetId runtimeAssetId(editorAssetId.m_guid, AZ_CRC("RuntimeData", 0x163310ae));
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> runtimeAsset(runtimeAssetId, azrtti_typeid<ScriptCanvas::RuntimeAsset>(), {});
// build everything again as a sanity check against dependencies. All of the variable overrides that were valid will be copied over
BuildGameEntityData();
/*
This defense against creating useless runtime components is pending changes the slice update system.
It also would require better abilities to check asset integrity when building assets that depend
on ScriptCanvas assets.
AZ::Data::AssetInfo assetInfo;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, runtimeAssetId);
if (assetInfo.m_assetType == AZ::Data::s_invalidAssetType)
if (!m_runtimeDataIsValid)
{
AZ_Warning("ScriptCanvas", false, "No ScriptCanvas Runtime Asset information for Entity ('%s' - '%s') Graph ('%s'), asset may be in error or deleted"
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
AZ_Error("ScriptCanvasBuilder", false, "Runtime information did not build for ScriptCanvas Component using asset: %s", m_scriptCanvasAssetHolder.GetAssetId().ToString<AZStd::string>().c_str());
return;
}
AzFramework::AssetSystem::AssetStatus statusResult = AzFramework::AssetSystem::AssetStatus_Unknown;
AzFramework::AssetSystemRequestBus::BroadcastResult(statusResult, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, runtimeAssetId);
if (statusResult != AzFramework::AssetSystem::AssetStatus_Compiled)
{
AZ_Warning("ScriptCanvas", false, "No ScriptCanvas Runtime Asset for Entity ('%s' - '%s') Graph ('%s'), compilation may have failed or not completed"
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
return;
}
*/
// #functions2 dependency-ctor-args make recursive
auto executionComponent = gameEntity->CreateComponent<ScriptCanvas::RuntimeComponent>(runtimeAsset);
ScriptCanvas::VariableData varData;
for (const auto& varConfig : m_editableData.GetVariables())
{
if (varConfig.m_graphVariable.GetDatum()->Empty())
{
AZ_Error("ScriptCanvas", false, "Data loss detected for GraphVariable ('%s') on Entity ('%s' - '%s') Graph ('%s')"
, varConfig.m_graphVariable.GetVariableName().data()
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
}
else
{
varData.AddVariable(varConfig.m_graphVariable.GetVariableName(), varConfig.m_graphVariable);
}
}
executionComponent->SetVariableOverrides(varData);
auto runtimeComponent = gameEntity->CreateComponent<ScriptCanvas::RuntimeComponent>();
auto runtimeOverrides = ConvertToRuntime(m_variableOverrides);
runtimeComponent->SetRuntimeDataOverrides(runtimeOverrides);
}
void EditorScriptCanvasComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
{
// If we removed out asset due to the catalog removing. Just set it back.
if (m_removedCatalogId == assetId)
{
if (!m_scriptCanvasAssetHolder.GetAssetId().IsValid())
@@ -317,12 +366,9 @@ namespace ScriptCanvasEditor
}
}
}
void EditorScriptCanvasComponent::OnCatalogAssetRemoved(const AZ::Data::AssetId& removedAssetId, const AZ::Data::AssetInfo& /*assetInfo*/)
{
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
// If the Asset gets removed from disk while the Editor is loaded clear out the asset reference.
if (assetId == removedAssetId)
{
m_removedCatalogId = assetId;
@@ -355,8 +401,6 @@ namespace ScriptCanvasEditor
}
}
AzToolsFramework::ScopedUndoBatch undo("Update Entity With New SC Graph");
AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, GetEntityId());
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
}
@@ -448,7 +492,6 @@ namespace ScriptCanvasEditor
{
// Invalidate the previously removed catalog id if we are setting a new asset id
m_removedCatalogId.SetInvalid();
SetPrimaryAsset(assetId);
}
}
@@ -469,125 +512,17 @@ namespace ScriptCanvasEditor
{
if (memoryAsset->GetFileAssetId() == m_scriptCanvasAssetHolder.GetAssetId())
{
LoadVariables(memoryAsset);
auto assetData = memoryAsset->GetAsset();
[[maybe_unused]] AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity");
BuildGameEntityData();
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
UpdateName();
}
}
/*! Start Variable Block Implementation */
void EditorScriptCanvasComponent::AddVariable(AZStd::string_view varName, const ScriptCanvas::GraphVariable& graphVariable)
{
// We only add component properties to the component
if (!graphVariable.IsComponentProperty())
{
return;
}
const auto& variableId = graphVariable.GetVariableId();
ScriptCanvas::EditableVariableConfiguration* originalVarNameValuePair = m_editableData.FindVariable(variableId);
if (!originalVarNameValuePair)
{
m_editableData.AddVariable(varName, graphVariable);
originalVarNameValuePair = m_editableData.FindVariable(variableId);
}
if (!originalVarNameValuePair)
{
AZ_Error("Script Canvas", false, "Unable to find variable with id %s and name %s on the ScriptCanvas Component. There is an issue in AddVariable",
variableId.ToString().data(), varName.data());
return;
}
// Update the variable name as it may have changed
originalVarNameValuePair->m_graphVariable.SetVariableName(varName);
originalVarNameValuePair->m_graphVariable.SetExposureCategory(graphVariable.GetExposureCategory());
originalVarNameValuePair->m_graphVariable.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
originalVarNameValuePair->m_graphVariable.SetAllowSignalOnChange(false);
}
void EditorScriptCanvasComponent::AddNewVariables(const ScriptCanvas::VariableData& graphVarData)
{
for (auto&& variablePair : graphVarData.GetVariables())
{
AddVariable(variablePair.second.GetVariableName(), variablePair.second);
}
}
void EditorScriptCanvasComponent::RemoveVariable(const ScriptCanvas::VariableId& varId)
{
m_editableData.RemoveVariable(varId);
}
void EditorScriptCanvasComponent::RemoveOldVariables(const ScriptCanvas::VariableData& graphVarData)
{
AZStd::vector<ScriptCanvas::VariableId> oldVariableIds;
for (auto varConfig : m_editableData.GetVariables())
{
const auto& variableId = varConfig.m_graphVariable.GetVariableId();
// We only add component sourced graph properties to the script canvas component, so if this variable was switched to a graph-only property remove it.
// Also be sure to remove this variable if it's been deleted entirely.
auto graphVariable = graphVarData.FindVariable(variableId);
if (!graphVariable || !graphVariable->IsComponentProperty())
{
oldVariableIds.push_back(variableId);
}
}
for (const auto& oldVariableId : oldVariableIds)
{
RemoveVariable(oldVariableId);
}
}
bool EditorScriptCanvasComponent::UpdateVariable(const ScriptCanvas::GraphVariable& graphDatum, ScriptCanvas::GraphVariable& updateDatum, ScriptCanvas::GraphVariable& originalDatum)
{
// If the editable datum is the different than the original datum, then the "variable value" has been overridden on this component
// Variable values only propagate from the Script Canvas graph to this component if the original "variable value" has not been overridden
// by the editable "variable value" on this component and the "variable value" on the graph is different than the variable value on this component
auto isNotOverridden = (*updateDatum.GetDatum()) == (*originalDatum.GetDatum());
auto scGraphIsModified = (*originalDatum.GetDatum()) != (*graphDatum.GetDatum());
if (isNotOverridden && scGraphIsModified)
{
ScriptCanvas::ModifiableDatumView originalDatumView;
originalDatum.ConfigureDatumView(originalDatumView);
originalDatumView.AssignToDatum((*graphDatum.GetDatum()));
ScriptCanvas::ModifiableDatumView updatedDatumView;
updateDatum.ConfigureDatumView(updatedDatumView);
updatedDatumView.AssignToDatum((*graphDatum.GetDatum()));
return true;
}
return false;
}
void EditorScriptCanvasComponent::LoadVariables(const ScriptCanvasMemoryAsset::pointer memoryAsset)
{
auto assetData = memoryAsset->GetAsset();
AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity");
auto variableComponent = scriptCanvasEntity ? AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::GraphVariableManagerComponent>(scriptCanvasEntity) : nullptr;
if (variableComponent)
{
// Add properties from the SC Asset to the SC Component if they do not exist on the SC Component
AddNewVariables(*variableComponent->GetVariableData());
RemoveOldVariables(*variableComponent->GetVariableData());
}
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
}
void EditorScriptCanvasComponent::ClearVariables()
{
m_editableData.Clear();
m_variableOverrides.Clear();
}
/* End Variable Block Implementation*/
}
@@ -19,8 +19,15 @@ namespace ScriptCanvas
namespace ScriptCanvasEditor
{
using LoadedInterpretedDependencies = AZStd::vector<AZStd::pair<AZStd::string, ScriptCanvas::Translation::LuaAssetResult>>;
AZ_INLINE LoadedInterpretedDependencies LoadInterpretedDepencies(const ScriptCanvas::DependencySet& dependencySet);
struct LoadedInterpretedDependency
{
AZStd::string path;
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> runtimeAsset;
ScriptCanvas::Translation::LuaAssetResult luaAssetResult;
AZStd::vector<LoadedInterpretedDependency> dependencies;
};
AZ_INLINE AZStd::vector<LoadedInterpretedDependency> LoadInterpretedDepencies(const ScriptCanvas::DependencySet& dependencySet);
AZ_INLINE LoadTestGraphResult LoadTestGraph(AZStd::string_view path);
@@ -49,10 +56,11 @@ namespace ScriptCanvasEditor
AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, Reporter& reporter);
AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, LoadTestGraphResult& loadGraphResult, Reporter& reporter);
AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, Reporters& reporters);
AZ_INLINE void Simulate(const DurationSpec& duration);
AZ_INLINE void SimulateDuration(const DurationSpec& duration);
AZ_INLINE void SimulateSeconds(const DurationSpec& duration);
AZ_INLINE void SimulateTicks(const DurationSpec& duration);
} // ScriptCanvasEditor
#include <Editor/Framework/ScriptCanvasGraphUtilities.inl>
@@ -26,9 +26,25 @@ namespace ScriptCanvasEditor
{
using namespace ScriptCanvas;
AZ_INLINE LoadedInterpretedDependencies LoadInterpretedDepencies(const ScriptCanvas::DependencySet& dependencySet)
// The runtime context (appropriately) always assumes that EntityIds are overridden, this step copies the values from the runtime data
// over to the override data to simulate build step that does this when building prefabs
AZ_INLINE void CopyAssetEntityIdsToOverrides(RuntimeDataOverrides& runtimeDataOverrides)
{
LoadedInterpretedDependencies loadedAssets;
runtimeDataOverrides.m_entityIds.reserve(runtimeDataOverrides.m_runtimeAsset->GetData().m_input.m_entityIds.size());
for (auto& varEntityPar : runtimeDataOverrides.m_runtimeAsset->GetData().m_input.m_entityIds)
{
runtimeDataOverrides.m_entityIds.push_back(varEntityPar.second);
}
for (auto& dependency : runtimeDataOverrides.m_dependencies)
{
CopyAssetEntityIdsToOverrides(dependency);
}
}
AZ_INLINE AZStd::vector<LoadedInterpretedDependency> LoadInterpretedDepencies(const ScriptCanvas::DependencySet& dependencySet)
{
AZStd::vector<LoadedInterpretedDependency> loadedAssets;
if (!dependencySet.empty())
{
@@ -41,7 +57,7 @@ namespace ScriptCanvasEditor
AZ_Assert(namespacePath.size() >= 3, "This functions assumes unit test dependencies are in the ScriptCanvas gem unit test folder");
AZStd::string originalPath = namespacePath[2].data();
for (size_t index = 3; index < namespacePath.size(); ++index)
{
originalPath += "/";
@@ -52,11 +68,11 @@ namespace ScriptCanvasEditor
{
originalPath.resize(originalPath.size() - AZStd::string_view(Grammar::k_internalRuntimeSuffix).size());
}
AZStd::string path = AZStd::string::format("%s/%s.scriptcanvas", k_unitTestDirPathRelative, originalPath.data());
LoadTestGraphResult loadResult = LoadTestGraph(path);
AZ_Assert(loadResult.m_runtimeAsset, "failed to load dependent asset");
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> luaAssetOutcome = AZ::Failure(AZStd::string("lua asset creation for function failed"));
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_graphPath);
AZ_Assert(luaAssetOutcome.IsSuccess(), "failed to create Lua asset");
@@ -69,8 +85,9 @@ namespace ScriptCanvasEditor
}
const ScriptCanvas::Translation::LuaAssetResult& luaAssetResult = luaAssetOutcome.GetValue();
loadedAssets.push_back({ modulePath, luaAssetResult });
}
// #functions2_recursive_unit_tests
loadedAssets.push_back({ modulePath, loadResult.m_runtimeAsset, luaAssetResult, {} });
}
}
return loadedAssets;
@@ -182,7 +199,7 @@ namespace ScriptCanvasEditor
RuntimeData runtimeDataBuffer;
AZStd::vector<RuntimeData> dependencyDataBuffer;
LoadedInterpretedDependencies dependencies;
AZStd::vector<LoadedInterpretedDependency> dependencies;
if (runGraphSpec.runSpec.execution == ExecutionMode::Interpreted)
{
@@ -202,9 +219,12 @@ namespace ScriptCanvasEditor
{
dependencies = LoadInterpretedDepencies(luaAssetResult.m_dependencies.source.userSubgraphs);
RuntimeDataOverrides runtimeDataOverrides;
runtimeDataOverrides.m_runtimeAsset = loadResult.m_runtimeAsset;
if (!dependencies.empty())
{
// eventually, this will need to be recursive, or the full asset handling system will need to be integrated into the testing framework
// #functions2_recursive_unit_tests eventually, this will need to be recursive, or the full asset handling system will need to be integrated into the testing framework
// in order to test functionality with a dependency stack greater than 2
// load all script assets, and their dependencies, initialize statics on all those dependencies if it is the first time loaded
@@ -215,7 +235,7 @@ namespace ScriptCanvasEditor
for (auto& dependency : dependencies)
{
inMemoryModules.emplace_back(dependency.first, dependency.second.m_scriptAsset);
inMemoryModules.emplace_back(dependency.path, dependency.luaAssetResult.m_scriptAsset);
}
AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::UseInMemoryRequireHook, inMemoryModules, AZ::ScriptContextIds::DefaultScriptContextId);
@@ -224,7 +244,11 @@ namespace ScriptCanvasEditor
for (size_t index = 0; index < dependencies.size(); ++index)
{
auto& dependency = dependencies[index];
const ScriptCanvas::Translation::LuaAssetResult& depencyAssetResult = dependency.second;
const ScriptCanvas::Translation::LuaAssetResult& depencyAssetResult = dependency.luaAssetResult;
RuntimeDataOverrides dependencyRuntimeDataOverrides;
dependencyRuntimeDataOverrides.m_runtimeAsset = dependency.runtimeAsset;
runtimeDataOverrides.m_dependencies.push_back(dependencyRuntimeDataOverrides);
RuntimeData& dependencyData = dependencyDataBuffer[index];
dependencyData.m_input = depencyAssetResult.m_runtimeInputs;
@@ -239,7 +263,9 @@ namespace ScriptCanvasEditor
loadResult.m_runtimeAsset.Get()->GetData().m_script = loadResult.m_scriptAsset;
loadResult.m_runtimeAsset.Get()->GetData().m_input = luaAssetResult.m_runtimeInputs;
loadResult.m_runtimeAsset.Get()->GetData().m_debugMap = luaAssetResult.m_debugMap;
loadResult.m_runtimeComponent = loadResult.m_entity->CreateComponent<ScriptCanvas::RuntimeComponent>(loadResult.m_runtimeAsset);
loadResult.m_runtimeComponent = loadResult.m_entity->CreateComponent<ScriptCanvas::RuntimeComponent>();
CopyAssetEntityIdsToOverrides(runtimeDataOverrides);
loadResult.m_runtimeComponent->SetRuntimeDataOverrides(runtimeDataOverrides);
Execution::Context::InitializeActivationData(loadResult.m_runtimeAsset->GetData());
Execution::InitializeInterpretedStatics(loadResult.m_runtimeAsset->GetData());
}
@@ -8,14 +8,14 @@
#pragma once
#include <AzFramework/Asset/AssetCatalogBus.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
#include <Builder/ScriptCanvasBuilder.h>
#include <Editor/Assets/ScriptCanvasAssetHolder.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <ScriptCanvas/Variable/VariableBus.h>
#include <ScriptCanvas/Variable/VariableData.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
namespace ScriptCanvasEditor
{
@@ -27,11 +27,10 @@ namespace ScriptCanvasEditor
which it uses to maintain the asset data in memory. Therefore removing an open ScriptCanvasAsset from the file system
will remove the reference from the EditorScriptCanvasComponent, but not the reference from the MainWindow allowing the
ScriptCanvas graph to still be modified while open
Finally per graph instance variables values are stored on the EditorScriptCanvasComponent and injected into the runtime ScriptCanvas component in BuildGameEntity
*/
class EditorScriptCanvasComponent
: public AzToolsFramework::Components::EditorComponentBase
: public AzToolsFramework::Components::EditorComponentBase
, private EditorContextMenuRequestBus::Handler
, private AzFramework::AssetCatalogEventBus::Handler
, private EditorScriptCanvasComponentLoggingBus::Handler
@@ -54,7 +53,6 @@ namespace ScriptCanvasEditor
void Deactivate() override;
//=====================================================================
//=====================================================================
// EditorComponentBase
void BuildGameEntity(AZ::Entity* gameEntity) override;
@@ -71,10 +69,10 @@ namespace ScriptCanvasEditor
void CloseGraph();
void SetName(const AZStd::string& name) { m_name = name; }
const AZStd::string& GetName() const { return m_name; };
const AZStd::string& GetName() const;
AZ::EntityId GetEditorEntityId() const { return GetEntity() ? GetEntityId() : AZ::EntityId(); }
AZ::NamedEntityId GetNamedEditorEntityId() const { return GetEntity() ? GetNamedEntityId() : AZ::NamedEntityId(); }
//=====================================================================
// EditorScriptCanvasComponentRequestBus
void SetAssetId(const AZ::Data::AssetId& assetId) override;
@@ -119,12 +117,8 @@ namespace ScriptCanvasEditor
(void)incompatible;
}
//=====================================================================
// AssetCatalogEventBus
void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override;
void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override;
//=====================================================================
void OnScriptCanvasAssetChanged(AZ::Data::AssetId assetId);
void UpdateName();
@@ -133,21 +127,15 @@ namespace ScriptCanvasEditor
void OnScriptCanvasAssetReady(const ScriptCanvasMemoryAsset::pointer asset);
//=====================================================================
void AddVariable(AZStd::string_view varName, const ScriptCanvas::GraphVariable& varDatum);
void AddNewVariables(const ScriptCanvas::VariableData& graphVarData);
void RemoveVariable(const ScriptCanvas::VariableId& varId);
void RemoveOldVariables(const ScriptCanvas::VariableData& graphVarData);
bool UpdateVariable(const ScriptCanvas::GraphVariable& graphDatum, ScriptCanvas::GraphVariable& updateDatum, ScriptCanvas::GraphVariable& originalDatum);
void LoadVariables(const ScriptCanvasMemoryAsset::pointer memoryAsset);
void BuildGameEntityData();
void ClearVariables();
private:
AZ::Data::AssetId m_removedCatalogId;
AZ::Data::AssetId m_previousAssetId;
AZStd::string m_name;
ScriptCanvasAssetHolder m_scriptCanvasAssetHolder;
ScriptCanvas::EditableVariableData m_editableData;
bool m_runtimeDataIsValid = false;
ScriptCanvasBuilder::BuildVariableOverrides m_variableOverrides;
};
}
@@ -1,6 +1,6 @@
/*
* 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
*
*/
@@ -289,7 +289,7 @@ namespace ScriptCanvasEditor
void LoggingDataAggregator::OnRegistrationDisabled(const AZ::NamedEntityId&, const ScriptCanvas::GraphIdentifier&)
{
}
void LoggingDataAggregator::ResetLog()
@@ -324,7 +324,7 @@ namespace ScriptCanvasEditor
m_hasAnchor = false;
m_anchorTimeStamp = ScriptCanvas::Timestamp(0);
}
void LoggingDataAggregator::RegisterScriptCanvas(const AZ::NamedEntityId& entityId, const ScriptCanvas::GraphIdentifier& graphIdentifier)
{
bool foundMatch = false;
@@ -335,7 +335,7 @@ namespace ScriptCanvasEditor
if (mapIter->second == graphIdentifier)
{
foundMatch = true;
AZ_Error("ScriptCanvas", false, "Received a duplicated registration callback.");
AZ_Warning("ScriptCanvas", false, "Received a duplicated registration callback.");
}
}
@@ -523,7 +523,7 @@ namespace ScriptCanvasEditor
// Creation Actions
{
m_createScriptCanvas = new QToolButton();
m_createScriptCanvas->setIcon(QIcon(ScriptCanvas::AssetDescription::GetIconPath<ScriptCanvasAsset>()));
m_createScriptCanvas->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/create_graph.png"));
m_createScriptCanvas->setToolTip("Creates a new Script Canvas Graph");
QObject::connect(m_createScriptCanvas, &QToolButton::clicked, this, &MainWindow::OnFileNew);
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f920ea2cd388c6db572344e33ccbf96f65ee6d391ae1880cfe16eff58d0da381
size 4016
@@ -12,6 +12,7 @@
<file>Resources/capture_offline.png</file>
<file>Resources/create_function_input.png</file>
<file>Resources/create_function_output.png</file>
<file>Resources/create_graph.png</file>
<file>Resources/CollapseAll_Icon.png</file>
<file>Resources/edit_icon.png</file>
<file>Resources/error_icon.png</file>
@@ -1,6 +1,6 @@
/*
* 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
*
*/
@@ -15,17 +15,28 @@ namespace ScriptCanvasRuntimeAssetCpp
{
AddDependencies = 3,
ChangeScriptRequirementToAsset,
// add your entry above
// add description above
Current
};
enum class RuntimeDataOverridesVersion : unsigned int
{
Initial = 0,
AddRuntimeAsset,
// add description above
Current,
};
enum class FunctionRuntimeDataVersion
{
MergeBackEnd2dotZero,
AddSubgraphInterface,
RemoveLegacyData,
RemoveConnectionToRuntimeData,
// add your entry above
// add description above
Current
};
}
@@ -87,9 +98,9 @@ namespace ScriptCanvas
{
return data.m_input.GetConstructorParameterCount() != 0
|| AZStd::any_of(data.m_requiredAssets.begin(), data.m_requiredAssets.end(), [](const AZ::Data::Asset<RuntimeAsset>& asset)
{
return RequiresDependencyConstructionParametersRecurse(asset.Get()->m_runtimeData);
});
{
return RequiresDependencyConstructionParametersRecurse(asset.Get()->m_runtimeData);
});
}
bool RuntimeData::RequiresStaticInitialization() const
@@ -97,6 +108,80 @@ namespace ScriptCanvas
return !m_cloneSources.empty();
}
bool RuntimeDataOverrides::IsPreloadBehaviorEnforced(const RuntimeDataOverrides& overrides)
{
if (overrides.m_runtimeAsset.GetAutoLoadBehavior() != AZ::Data::AssetLoadBehavior::PreLoad)
{
return false;
}
for (auto& dependency : overrides.m_dependencies)
{
if (!IsPreloadBehaviorEnforced(dependency))
{
return false;
}
}
return true;
}
void RuntimeDataOverrides::EnforcePreloadBehavior()
{
m_runtimeAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
for (auto& dependency : m_dependencies)
{
dependency.EnforcePreloadBehavior();
}
}
void RuntimeDataOverrides::Reflect(AZ::ReflectContext* context)
{
RuntimeVariable::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<RuntimeDataOverrides>()
->Version(static_cast<unsigned int>(ScriptCanvasRuntimeAssetCpp::RuntimeDataOverridesVersion::Current))
->Field("runtimeAsset", &RuntimeDataOverrides::m_runtimeAsset)
->Field("variables", &RuntimeDataOverrides::m_variables)
->Field("variableIndices", &RuntimeDataOverrides::m_variableIndices)
->Field("entityIds", &RuntimeDataOverrides::m_entityIds)
->Field("dependencies", &RuntimeDataOverrides::m_dependencies)
;
}
}
RuntimeVariable::RuntimeVariable(const AZStd::any& source)
: value(source)
{
}
RuntimeVariable::RuntimeVariable(AZStd::any&& source)
: value(AZStd::move(source))
{
}
void RuntimeVariable::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<RuntimeVariable>()
->Field("value", &RuntimeVariable::value)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<RuntimeVariable>("RuntimeVariable", "RuntimeVariable")
->DataElement(AZ::Edit::UIHandlers::Default, &RuntimeVariable::value, "value", "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, true)
;
}
}
}
////////////////////////
// SubgraphInterfaceData
@@ -118,7 +203,7 @@ namespace ScriptCanvas
{
*this = AZStd::move(other);
}
SubgraphInterfaceData& SubgraphInterfaceData::operator=(SubgraphInterfaceData&& other)
{
if (this != &other)
@@ -1,6 +1,6 @@
/*
* 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
*
*/
@@ -10,6 +10,7 @@
#include <AzCore/Script/ScriptAsset.h>
#include <ScriptCanvas/Asset/AssetDescription.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Core/SubgraphInterface.h>
#include <ScriptCanvas/Core/GraphData.h>
#include <ScriptCanvas/Grammar/DebugMap.h>
@@ -21,6 +22,7 @@
namespace ScriptCanvas
{
class RuntimeAsset;
struct RuntimeVariable;
class RuntimeAssetDescription : public AssetDescription
{
@@ -41,7 +43,7 @@ namespace ScriptCanvas
"Script Canvas Runtime",
"Script Canvas Runtime",
"Icons/ScriptCanvas/Viewport/ScriptCanvas.png",
AZ::Color(1.0f,0.0f,0.0f,1.0f),
AZ::Color(1.0f, 0.0f, 0.0f, 1.0f),
false
)
{}
@@ -82,6 +84,24 @@ namespace ScriptCanvas
bool static RequiresDependencyConstructionParametersRecurse(const RuntimeData& data);
};
struct RuntimeDataOverrides
{
AZ_TYPE_INFO(RuntimeDataOverrides, "{CE3C0AE6-4EBA-43B2-B2D5-7AC24A194E63}");
AZ_CLASS_ALLOCATOR(RuntimeDataOverrides, AZ::SystemAllocator, 0);
static bool IsPreloadBehaviorEnforced(const RuntimeDataOverrides& overrides);
static void Reflect(AZ::ReflectContext* reflectContext);
AZ::Data::Asset<RuntimeAsset> m_runtimeAsset;
AZStd::vector<RuntimeVariable> m_variables;
AZStd::vector<bool> m_variableIndices;
AZStd::vector<AZ::EntityId> m_entityIds;
AZStd::vector<RuntimeDataOverrides> m_dependencies;
void EnforcePreloadBehavior();
};
class RuntimeAssetBase
: public AZ::Data::AssetData
{
@@ -94,7 +114,6 @@ namespace ScriptCanvas
{
}
};
template <typename DataType>
class RuntimeAssetTyped
@@ -165,7 +184,7 @@ namespace ScriptCanvas
"Script Canvas Function Interface",
"Script Canvas Function Interface",
"Icons/ScriptCanvas/Viewport/ScriptCanvas_Function.png",
AZ::Color(1.0f,0.0f,0.0f,1.0f),
AZ::Color(1.0f, 0.0f, 0.0f, 1.0f),
false
)
{}
@@ -207,6 +226,6 @@ namespace ScriptCanvas
static const char* GetFileExtension() { return "scriptcanvas_fn_compiled"; }
static const char* GetFileFilter() { return "*.scriptcanvas_fn_compiled"; }
friend class SubgraphInterfaceAssetHandler;
friend class SubgraphInterfaceAssetHandler;
};
}
@@ -1,12 +1,12 @@
/*
* 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 <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/RTTI/AttributeReader.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Serialization/SerializeContext.h>
@@ -17,6 +17,33 @@
namespace ScriptCanvas
{
ScopedAuxiliaryEntityHandler::ScopedAuxiliaryEntityHandler(AZ::Entity* buildEntity)
: m_buildEntity(buildEntity)
, m_wasAdded(false)
{
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RemoveEntity(buildEntity);
}
if (buildEntity->GetState() == AZ::Entity::State::Constructed)
{
buildEntity->Init();
m_wasAdded = true;
}
}
ScopedAuxiliaryEntityHandler::~ScopedAuxiliaryEntityHandler()
{
if (!m_wasAdded)
{
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->AddEntity(m_buildEntity);
}
}
}
bool IsNamespacePathEqual(const NamespacePath& lhs, const NamespacePath& rhs)
{
if (lhs.size() != rhs.size())
@@ -128,4 +155,3 @@ namespace ScriptCanvas
runtimeVersion = RuntimeVersion::Current;
}
}
@@ -1,6 +1,6 @@
/*
* 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
*
*/
@@ -15,6 +15,7 @@
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/any.h>
#include <AzCore/std/hash.h>
#include <AzCore/Component/EntityUtils.h>
#include <AzCore/Component/NamedEntityId.h>
@@ -26,7 +27,7 @@ namespace AZ
{
class Entity;
class ReflectContext;
template<typename t_Attribute, typename t_Container>
bool ReadAttribute(t_Attribute& resultOut, AttributeId id, const t_Container& attributes)
{
@@ -41,7 +42,7 @@ namespace ScriptCanvas
// The actual value in each location initialized to GraphOwnerId is populated with the owning entity at editor-time, Asset Processor-time, or runtime, as soon as the owning entity is known.
using GraphOwnerIdType = AZ::EntityId;
static const GraphOwnerIdType GraphOwnerId = AZ::EntityId(0xacedc0de);
// A place holder identifier for unique runtime graph on Entity that is running more than one instance of the same graph.
// This allows multiple instances of the same graph to be addressed individually on the same entity.
// The actual value in each location initialized to UniqueId is populated at run-time.
@@ -52,7 +53,7 @@ namespace ScriptCanvas
constexpr const char* k_OnVariableWriteEventName = "OnVariableValueChanged";
constexpr const char* k_OnVariableWriteEbusName = "VariableNotification";
class Node;
class Edge;
@@ -195,7 +196,7 @@ namespace ScriptCanvas
using PropertyFields = AZStd::vector<AZStd::pair<AZStd::string_view, SlotId>>;
using NamedActiveEntityId = AZ::NamedEntityId;
using NamedActiveEntityId = AZ::NamedEntityId;
using NamedNodeId = NamedId<AZ::EntityId>;
using NamedSlotId = NamedId<SlotId>;
@@ -204,7 +205,26 @@ namespace ScriptCanvas
using EBusBusId = AZ::Crc32;
using ScriptCanvasId = AZ::EntityId;
enum class AzEventIdentifier : size_t {};
struct RuntimeVariable
{
AZ_TYPE_INFO(RuntimeVariable, "{6E969359-5AF5-4ECA-BE89-A96AB30A624E}");
AZ_CLASS_ALLOCATOR(RuntimeVariable, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* reflectContext);
AZStd::any value;
RuntimeVariable() = default;
RuntimeVariable(const RuntimeVariable&) = default;
RuntimeVariable(RuntimeVariable&&) = default;
explicit RuntimeVariable(const AZStd::any& source);
explicit RuntimeVariable(AZStd::any&& source);
RuntimeVariable& operator=(const RuntimeVariable&) = default;
RuntimeVariable& operator=(RuntimeVariable&&) = default;
};
struct NamespacePathHasher
{
AZ_FORCE_INLINE size_t operator()(const NamespacePath& path) const
@@ -245,6 +265,17 @@ namespace ScriptCanvas
};
using ScriptCanvasSettingsRequestBus = AZ::EBus<ScriptCanvasSettingsRequests>;
class ScopedAuxiliaryEntityHandler
{
public:
ScopedAuxiliaryEntityHandler(AZ::Entity* buildEntity);
~ScopedAuxiliaryEntityHandler();
private:
bool m_wasAdded = false;
AZ::Entity* m_buildEntity = nullptr;
};
}
namespace AZStd
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
/*
* 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
*
*/
@@ -9,8 +9,8 @@
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/any.h>
#include <AzCore/std/string/string_view.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Data/Data.h>
#include <ScriptCanvas/Data/DataTrait.h>
#include <ScriptCanvas/Data/BehaviorContextObject.h>
@@ -59,7 +59,7 @@ namespace ScriptCanvas
Datum(BehaviorContextResultTag, const AZ::BehaviorParameter& resultType);
Datum(const AZStd::string& behaviorClassName, eOriginality originality);
Datum(const AZ::BehaviorValueParameter& value);
void ReconfigureDatumTo(Datum&& object);
void ReconfigureDatumTo(const Datum& object);
@@ -204,18 +204,18 @@ namespace ScriptCanvas
{
static_assert(!AZStd::is_pointer<t_Value>::value, "no pointer types in the Datum::GetAsHelper<t_Value, false>");
if (datum.m_storage.empty())
if (datum.m_storage.value.empty())
{
// rare, but can be caused by removals or problems with reflection to BehaviorContext, so must be checked
return nullptr;
}
else if (datum.m_type.GetType() == Data::eType::BehaviorContextObject)
{
return (*AZStd::any_cast<BehaviorContextObjectPtr>(&datum.m_storage))->CastConst<t_Value>();
return (*AZStd::any_cast<BehaviorContextObjectPtr>(&datum.m_storage.value))->CastConst<t_Value>();
}
else
{
return AZStd::any_cast<const t_Value>(&datum.m_storage);
return AZStd::any_cast<const t_Value>(&datum.m_storage.value);
}
}
};
@@ -253,12 +253,12 @@ namespace ScriptCanvas
// eOriginality records the graph source of the object
eOriginality m_originality = eOriginality::Copy;
// storage for the datum, regardless of ScriptCanvas::Data::Type
AZStd::any m_storage;
RuntimeVariable m_storage;
// This contains the editor label for m_storage.
// This contains the editor label for m_storage.value.
AZStd::string m_datumLabel;
// This contains the editor visibility for m_storage.
// This contains the editor visibility for m_storage.value.
AZ::Crc32 m_visibility{ AZ::Edit::PropertyVisibility::ShowChildrenOnly };
// storage for implicit conversions, when needed
AZStd::any m_conversionStorage;
@@ -304,7 +304,7 @@ namespace ScriptCanvas
bool InitializeCRC(const void* source);
bool InitializeEntityID(const void* source);
bool InitializeNamedEntityID(const void* source);
bool InitializeMatrix3x3(const void* source);
@@ -384,7 +384,7 @@ namespace ScriptCanvas
bool Datum::Empty() const
{
return m_storage.empty() || GetValueAddress() == nullptr;
return m_storage.value.empty() || GetValueAddress() == nullptr;
}
template<typename t_Value>
@@ -492,7 +492,7 @@ namespace ScriptCanvas
{
if (Data::IsValueType(m_type))
{
m_storage = value;
m_storage.value = value;
return true;
}
else
@@ -1,6 +1,6 @@
/*
* 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
*
*/
@@ -136,10 +136,7 @@ namespace ScriptCanvas
{
if (nodeEntity)
{
if (nodeEntity->GetState() == AZ::Entity::State::Constructed)
{
nodeEntity->Init();
}
ScriptCanvas::ScopedAuxiliaryEntityHandler entityHandler(nodeEntity);
if (auto* node = AZ::EntityUtils::FindFirstDerivedComponent<Node>(nodeEntity))
{
@@ -155,10 +152,7 @@ namespace ScriptCanvas
{
if (connectionEntity)
{
if (connectionEntity->GetState() == AZ::Entity::State::Constructed)
{
connectionEntity->Init();
}
ScriptCanvas::ScopedAuxiliaryEntityHandler entityHandler(connectionEntity);
}
}
@@ -169,7 +163,7 @@ namespace ScriptCanvas
{
if (m_isFunctionGraph)
{
return true;
return true;
}
return false;
@@ -418,7 +412,7 @@ namespace ScriptCanvas
void Graph::ValidateVariables(ValidationResults& validationResults)
{
const VariableData* variableData = GetVariableData();
if (!variableData)
{
return;
@@ -440,7 +434,7 @@ namespace ScriptCanvas
{
errorDescription = AZStd::string::format("Variable %s has an invalid type %s.", GetVariableName(variableId).data(), variableType.GetAZType().ToString<AZStd::string>().c_str());
}
}
}
else if (variableType == Data::Type::Invalid())
{
errorDescription = AZStd::string::format("Variable %s has an invalid type.", GetVariableName(variableId).data());
@@ -502,7 +496,7 @@ namespace ScriptCanvas
{
m_graphData.m_nodes.emplace(nodeEntity);
m_nodeMapping[nodeId] = node;
node->SetOwningScriptCanvasId(m_scriptCanvasId);
node->Configure();
GraphNotificationBus::Event(m_scriptCanvasId, &GraphNotifications::OnNodeAdded, nodeId);
@@ -523,17 +517,17 @@ namespace ScriptCanvas
if (node)
{
auto entry = m_graphData.m_nodes.find(node->GetEntity());
if (entry != m_graphData.m_nodes.end())
{
m_nodeMapping.erase(nodeId);
m_graphData.m_nodes.erase(entry);
GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnNodeRemoved, nodeId);
if (entry != m_graphData.m_nodes.end())
{
m_nodeMapping.erase(nodeId);
m_graphData.m_nodes.erase(entry);
GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnNodeRemoved, nodeId);
RemoveDependentAsset(nodeId);
return true;
RemoveDependentAsset(nodeId);
return true;
}
}
}
}
return false;
}
@@ -1036,17 +1030,17 @@ namespace ScriptCanvas
}
}
// for (auto connectionId : removableConnections)
// {
// DisconnectById(connectionId);
// }
// for (auto connectionId : removableConnections)
// {
// DisconnectById(connectionId);
// }
if (!removableConnections.empty())
{
// RefreshConnectionValidity(warnOnRemoval);
}
}
void Graph::OnEntityActivated(const AZ::EntityId&)
{
}
@@ -1075,7 +1069,7 @@ namespace ScriptCanvas
AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(scriptEventNode->GetAssetId(), AZ::Data::AssetLoadBehavior::Default);
}
}
m_batchAddingData = false;
GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnBatchAddComplete);
@@ -79,6 +79,7 @@ namespace ScriptCanvas
behaviorContext->Class<Nodeable>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::Script::Attributes::UseClassIndexAllowNil, AZ::AttributeIsValid::IfPresent)
->Constructor<ExecutionStateWeakPtr>()
->Method("Deactivate", &Nodeable::Deactivate)
->Method("InitializeExecutionState", &Nodeable::InitializeExecutionState)
@@ -756,10 +756,9 @@ namespace ScriptCanvas
{
auto runtimeComponent = (*graphIter);
if (graphIdentifier.m_assetId.m_guid == runtimeComponent->GetAsset().GetId().m_guid)
if (graphIdentifier.m_assetId.m_guid == runtimeComponent->GetRuntimeDataOverrides().m_runtimeAsset.GetId().m_guid)
{
// TODO: Gate on ComponentId
// \todo chcurran restore this functionality
// runtimeComponent->SetIsGraphObserved(observedState);
runtimeComponents.erase(graphIter);
break;

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