From e0d0bbfdaed37487b74cb02cd0156bd43b203347 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Tue, 3 Aug 2021 13:12:37 -0700 Subject: [PATCH 001/101] Changes to desync debug output to make it less stressful on bandwidth and the server, as well as some fixes to corrections on the local client Signed-off-by: kberg-amzn --- .../Serialization/StringifySerializer.cpp | 18 +- .../Serialization/StringifySerializer.h | 12 +- Gems/Multiplayer/Code/CMakeLists.txt | 2 +- .../LocalPredictionPlayerInputComponent.h | 13 +- .../Multiplayer/Components/NetBindComponent.h | 19 +- .../Multiplayer/NetworkTime/INetworkTime.h | 5 + .../NetworkTime/RewindableObject.inl | 2 +- ...tionPlayerInputComponent.AutoComponent.xml | 1 - .../LocalPredictionPlayerInputComponent.cpp | 176 ++++++++---------- .../Source/Components/NetBindComponent.cpp | 15 ++ .../Source/MultiplayerSystemComponent.cpp | 4 +- .../EntityReplicationManager.cpp | 14 +- .../EntityReplicationManager.h | 1 + .../Code/Source/NetworkTime/NetworkTime.cpp | 9 + .../Code/Source/NetworkTime/NetworkTime.h | 1 + 15 files changed, 154 insertions(+), 138 deletions(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp index b35b01d45c..df018cb6ce 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp @@ -23,9 +23,9 @@ namespace AzNetworking return m_string; } - const StringifySerializer::StringMap& StringifySerializer::GetValueMap() const + const StringifySerializer::ValueMap& StringifySerializer::GetValueMap() const { - return m_map; + return m_valueMap; } SerializerMode StringifySerializer::GetSerializerMode() const @@ -137,22 +137,22 @@ namespace AzNetworking template bool StringifySerializer::ProcessData(const char* name, const T& value) { - // Only add delimeters after we have processed at least one element + const AZStd::string keyString = m_prefix + name; + if (!m_string.empty()) { + // Only add delimeters after we have processed at least one element m_string += m_delimeter; } if (m_outputFieldNames) { - m_string += m_prefix; - m_string += name; - m_string += m_separator; + m_string += keyString; } - AZ::CVarFixedString string = AZ::ConsoleTypeHelpers::ValueToString(value); - m_string += string.c_str(); - m_map[m_prefix + name] = string.c_str(); + AZ::CVarFixedString valueString = AZ::ConsoleTypeHelpers::ValueToString(value); + m_valueMap[keyString] = valueString.c_str(); + return true; } } diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h index d93f08822b..379b5198c7 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h @@ -20,17 +20,15 @@ namespace AzNetworking { public: - using StringMap = AZStd::map; + using ValueMap = AZStd::map; StringifySerializer(char delimeter = ' ', bool outputFieldNames = true, const AZStd::string& seperator = "="); - // GetString - // After serializing objects, get the serialized values as a single string + //! After serializing objects, get the serialized values as a single string. const AZStd::string& GetString() const; - // GetValueMap - // After serializing objects, get the serialized values as key value pairs - const StringMap& GetValueMap() const; + //! After serializing objects, get the serialized values as a map of key/value pairs. + const ValueMap& GetValueMap() const; // ISerializer interfaces SerializerMode GetSerializerMode() const override; @@ -67,7 +65,7 @@ namespace AzNetworking char m_delimeter; bool m_outputFieldNames = true; - StringMap m_map; + ValueMap m_valueMap; AZStd::string m_string; AZStd::string m_prefix; AZStd::string m_separator; diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index 96527fbfc4..e8b38c8799 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -79,7 +79,7 @@ ly_add_target( # The "Multiplayer" target is used by clients and servers, Debug is used only on clients. ly_create_alias(NAME Multiplayer.Clients NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) -ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer) +ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h index fbb7131f76..4e5d7f2d49 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h @@ -10,6 +10,7 @@ #include #include +#include namespace Multiplayer { @@ -41,8 +42,7 @@ namespace Multiplayer ( AzNetworking::IConnection* invokingConnection, const Multiplayer::NetworkInputArray& inputArray, - const AZ::HashValue32& stateHash, - const AzNetworking::PacketEncodingBuffer& clientState + const AZ::HashValue32& stateHash ) override; void HandleSendMigrateClientInput @@ -58,11 +58,6 @@ namespace Multiplayer const AzNetworking::PacketEncodingBuffer& correction ) override; - //! Return true if we're currently replaying inputs after a correction. - //! If this value returns true, effects, audio, and other cosmetic triggers should be suppressed - //! @return true if we're within correction scope and replaying inputs - bool IsReplayingInput() const; - //! Return true if we're currently migrating from one host to another. //! @return boolean true if we're currently migrating from one host to another bool IsMigrating() const; @@ -79,6 +74,9 @@ namespace Multiplayer void UpdateAutonomous(AZ::TimeMs deltaTimeMs); void UpdateBankedTime(AZ::TimeMs deltaTimeMs); + using StateHistoryItem = AZStd::unique_ptr; + AZStd::map m_predictiveStateHistory; + // Implicitly sorted player input history, back() is the input that corresponds to the latest client input Id NetworkInputHistory m_inputHistory; @@ -104,7 +102,6 @@ namespace Multiplayer ClientInputId m_lastMigratedInputId = ClientInputId{ 0 }; // Used to resend inputs that were queued during a migration event HostFrameId m_serverMigrateFrameId = InvalidHostFrameId; - bool m_replayingInput = false; // True if we're replaying inputs under a correction event (use this to suppress effects or audio) bool m_allowMigrateClientInput = false; // True if this component was migrated, we will allow the client to send us migrated inputs (one time only) }; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index e0574e23a3..c050495f1f 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -87,9 +87,19 @@ namespace Multiplayer AzNetworking::ConnectionId GetOwningConnectionId() const; void SetAllowAutonomy(bool value); MultiplayerComponentInputVector AllocateComponentInputs(); + + //! Return true if we're currently processing inputs. + //! @return true if we're within ProcessInput scope and writing to predictive state bool IsProcessingInput() const; + + //! Return true if we're currently replaying inputs after a correction. + //! If this value returns true, effects, audio, and other cosmetic triggers should be suppressed + //! @return true if we're within correction scope and replaying inputs + bool IsReprocessingInput() const; + void CreateInput(NetworkInput& networkInput, float deltaTime); void ProcessInput(NetworkInput& networkInput, float deltaTime); + void ReprocessInput(NetworkInput& networkInput, float deltaTime); bool HandleRpcMessage(AzNetworking::IConnection* invokingConnection, NetEntityRole remoteRole, NetworkEntityRpcMessage& message); bool HandlePropertyChangeMessage(AzNetworking::ISerializer& serializer, bool notifyChanges = true); @@ -177,10 +187,11 @@ namespace Multiplayer AzNetworking::ConnectionId m_owningConnectionId = AzNetworking::InvalidConnectionId; - bool m_isProcessingInput = false; - bool m_isMigrationDataValid = false; - bool m_needsToBeStopped = false; - bool m_allowAutonomy = false; // Set to true for the hosts controlled entity + bool m_isProcessingInput = false; // Set to true when we are processing input + bool m_isReprocessingInput = false; // Set to true when we are reprocessing input (during a correction) + bool m_isMigrationDataValid = false; + bool m_needsToBeStopped = false; + bool m_allowAutonomy = false; // Set to true for the hosts controlled entity friend class NetworkEntityManager; friend class EntityReplicationManager; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h index 35ea317f62..441ad9876a 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h @@ -54,6 +54,11 @@ namespace Multiplayer //! @return the HostFrameId taking into account the provided rewinding connectionId virtual HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const = 0; + //! Forcibly sets the current network time to the provided frameId and game time in milliseconds. + //! @param frameId the new HostFrameId to use + //! @param timeMs the new HostTimeMs to use + virtual void ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) = 0; + //! Alters the current HostFrameId and binds that alteration to the provided ConnectionId. //! @param frameId the new HostFrameId to use //! @param timeMs the new HostTimeMs to use diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl index b3a14e698b..496e87a7a2 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl @@ -72,7 +72,7 @@ namespace Multiplayer const HostFrameId frameTime = GetCurrentTimeForProperty(); if (frameTime < m_headTime) { - AZ_Assert(false, "Trying to mutate a rewindable in the past"); + AZ_Assert(false, "Trying to mutate a rewindable value in the past"); } else if (m_headTime < frameTime) { diff --git a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml index 0c799a7b3f..1a7496a77d 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml @@ -22,7 +22,6 @@ - diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index df0d84c427..58e8890672 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -21,9 +21,11 @@ namespace Multiplayer AZ_CVAR(AZ::TimeMs, cl_MaxRewindHistoryMs, AZ::TimeMs{ 2000 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum number of milliseconds to keep for server correction rewind and replay"); #ifndef AZ_RELEASE_BUILD AZ_CVAR(float, cl_DebugHackTimeMultiplier, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Scalar value used to simulate clock hacking cheats for validating bank time system and anticheat"); - AZ_CVAR(bool, cl_EnableDesyncDebugging, false, nullptr, AZ::ConsoleFunctorFlags::Null, "If enabled, debug logs will contain verbose information on detected state desyncs"); + AZ_CVAR(bool, cl_EnableDesyncDebugging, true, nullptr, AZ::ConsoleFunctorFlags::Null, "If enabled, debug logs will contain verbose information on detected state desyncs"); + AZ_CVAR(uint32_t, cl_PredictiveStateHistorySize, 120, nullptr, AZ::ConsoleFunctorFlags::Null, "Controls how many inputs of predictive state should be retained for debugging desyncs"); #endif + AZ_CVAR(bool, sv_ForceCorrections, false, nullptr, AZ::ConsoleFunctorFlags::Null, "If enabled, the server will force a correction for every input received for debugging"); AZ_CVAR(bool, sv_EnableCorrections, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Enables server corrections on autonomous proxy desyncs"); AZ_CVAR(double, sv_MaxBankTimeWindowSec, 0.2, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum bank time we allow before we start rejecting autonomous proxy move inputs due to anticheat kicking in"); AZ_CVAR(double, sv_BankTimeDecay, 0.025, nullptr, AZ::ConsoleFunctorFlags::Null, "Amount to decay bank time by, in case of more permanent shifts in client latency"); @@ -45,6 +47,40 @@ namespace Multiplayer return serializer.GetString(); } + void PrintCorrectionDifferences(const AzNetworking::StringifySerializer& client, const AzNetworking::StringifySerializer& server) + { + const auto& clientMap = client.GetValueMap(); + const auto& serverMap = server.GetValueMap(); + + AzNetworking::StringifySerializer::ValueMap differences = clientMap; + for (auto iter = server.GetValueMap().begin(); iter != server.GetValueMap().end(); ++iter) + { + auto serverValueIter = clientMap.find(iter->first); + if (iter->second == differences[iter->first]) + { + differences.erase(iter->first); + } + } + + if (differences.empty()) + { + AZLOG_ERROR("The hash mismatched, but no differences were found.") + } + + for (auto iter = differences.begin(); iter != differences.end(); ++iter) + { + auto clientValueIter = clientMap.find(iter->first); + auto serverValueIter = serverMap.find(iter->first); + if (clientValueIter == clientMap.end() || serverValueIter == serverMap.end()) + { + AZLOG_ERROR(" %s (Not found in server and/or client value map!)", iter->first.c_str()); + continue; + } + + AZLOG_ERROR(" %s Server=%s Client=%s", iter->first.c_str(), serverValueIter->second.c_str(), clientValueIter->second.c_str()); + } + } + void LocalPredictionPlayerInputComponent::LocalPredictionPlayerInputComponent::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); @@ -106,8 +142,7 @@ namespace Multiplayer ( AzNetworking::IConnection* invokingConnection, const Multiplayer::NetworkInputArray& inputArray, - const AZ::HashValue32& stateHash, - [[maybe_unused]] const AzNetworking::PacketEncodingBuffer& clientState + const AZ::HashValue32& stateHash ) { if (invokingConnection == nullptr) @@ -176,7 +211,7 @@ namespace Multiplayer } } - if (sv_EnableCorrections && (currentTimeMs - m_lastCorrectionSentTimeMs > sv_MinCorrectionTimeMs)) + if (sv_ForceCorrections || (sv_EnableCorrections && (currentTimeMs - m_lastCorrectionSentTimeMs > sv_MinCorrectionTimeMs))) { m_lastCorrectionSentTimeMs = currentTimeMs; @@ -210,69 +245,6 @@ namespace Multiplayer // Send correction SendClientInputCorrection(GetLastInputId(), correction); - -#ifndef AZ_RELEASE_BUILD - AZStd::string clientStateString; - AZStd::string serverStateString; - if (cl_EnableDesyncDebugging) - { - // In debug, show which states caused the correction - // Write in client state - AzNetworking::NetworkOutputSerializer clientStateSerializer(clientState.GetBuffer(), clientState.GetSize()); - GetNetBindComponent()->SerializeEntityCorrection(clientStateSerializer); - - // Read out state values - AzNetworking::StringifySerializer clientValues; - GetNetBindComponent()->SerializeEntityCorrection(clientValues); - - // Restore server state - AzNetworking::NetworkOutputSerializer serverStateSerializer(correction.GetBuffer(), correction.GetSize()); - GetNetBindComponent()->SerializeEntityCorrection(serverStateSerializer); - - // Read out state values - AzNetworking::StringifySerializer serverValues; - GetNetBindComponent()->SerializeEntityCorrection(serverValues); - - AZStd::map> mapComparison; - - // put the server value in the first part of the pair - for (const auto& pair : serverValues.GetValueMap()) - { - mapComparison[pair.first].first = pair.second; - } - - // put the client value in the second part of the pair - for (const auto& pair : clientValues.GetValueMap()) - { - mapComparison[pair.first].second = pair.second; - } - - bool firstIt = true; - for (const auto& mapPair : mapComparison) - { - if (mapPair.second.first != mapPair.second.second) - { - if (!firstIt) - { - clientStateString += ","; - serverStateString += ","; - } - firstIt = false; - - AZStd::string clientValue = mapPair.second.second.empty() ? "" : mapPair.second.second; - AZStd::string serverValue = mapPair.second.first.empty() ? "" : mapPair.second.first; - clientStateString += mapPair.first + "=" + clientValue; - serverStateString += mapPair.first + "=" + serverValue; - } - } - } - else - { - clientStateString = "available in debug only"; - serverStateString = "available in debug only"; - } - AZLOG_ERROR("** Autonomous proxy desync detected! ** clientState=[%s], serverState=[%s]", clientStateString.c_str(), serverStateString.c_str()); -#endif } } } @@ -331,7 +303,7 @@ namespace Multiplayer void LocalPredictionPlayerInputComponentController::HandleSendClientInputCorrection ( - AzNetworking::IConnection* invokingConnection, + [[maybe_unused]] AzNetworking::IConnection* invokingConnection, const Multiplayer::ClientInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction ) @@ -356,6 +328,25 @@ namespace Multiplayer GetNetBindComponent()->SerializeEntityCorrection(serializer); m_correctionEvent.Signal(); +#ifndef AZ_RELEASE_BUILD + if (cl_EnableDesyncDebugging) + { + AZLOG_INFO("** Autonomous Desync - Corrected clientInputId=%d ", aznumeric_cast(inputId)); + auto iter = m_predictiveStateHistory.find(inputId); + if (iter != m_predictiveStateHistory.end()) + { + // Read out state values + AzNetworking::StringifySerializer serverValues; + GetNetBindComponent()->SerializeEntityCorrection(serverValues); + PrintCorrectionDifferences(*iter->second, serverValues); + } + else + { + AZLOG_INFO("Received correction that is too old to diff, increase cl_PredictiveStateHistorySize"); + } + } +#endif + AZLOG ( NET_Prediction, @@ -370,29 +361,13 @@ namespace Multiplayer // If this correction is for a move outside our input history window, just start replaying from the oldest move we have available const uint32_t startReplayIndex = (inputHistorySize > historicalDelta) ? (inputHistorySize - historicalDelta) : 0; - // Flag that we are replaying inputs - struct ScopedReplayingInput - { - ScopedReplayingInput(LocalPredictionPlayerInputComponentController* instance) - : m_instance(instance) - { - m_instance->m_replayingInput = true; - } - ~ScopedReplayingInput() - { - m_instance->m_replayingInput = false; - } - LocalPredictionPlayerInputComponentController* m_instance; - }; - ScopedReplayingInput markReplayingInput(this); - const float clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; for (uint32_t replayIndex = startReplayIndex; replayIndex < inputHistorySize; ++replayIndex) { // Reprocess the input for this frame NetworkInput& input = m_inputHistory[replayIndex]; ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId()); - GetNetBindComponent()->ProcessInput(input, clientInputRateSec); + GetNetBindComponent()->ReprocessInput(input, clientInputRateSec); AZLOG ( @@ -405,11 +380,6 @@ namespace Multiplayer } } - bool LocalPredictionPlayerInputComponentController::IsReplayingInput() const - { - return m_replayingInput; - } - bool LocalPredictionPlayerInputComponentController::IsMigrating() const { return m_lastMigratedInputId != ClientInputId{ 0 }; @@ -519,17 +489,6 @@ namespace Multiplayer AzNetworking::HashSerializer hashSerializer; GetNetBindComponent()->SerializeEntityCorrection(hashSerializer); - // In debug, send the entire client output state to the server to make it easier to debug desync issues - AzNetworking::PacketEncodingBuffer processInputResult; -#ifndef AZ_RELEASE_BUILD - if (cl_EnableDesyncDebugging) - { - AzNetworking::NetworkInputSerializer processInputResultSerializer(processInputResult.GetBuffer(), processInputResult.GetCapacity()); - GetNetBindComponent()->SerializeEntityCorrection(processInputResultSerializer); - processInputResult.Resize(processInputResultSerializer.GetSize()); - } -#endif - // Save this input and discard move history outside our client rewind window m_inputHistory.PushBack(input); while (m_inputHistory.Size() > maxClientInputs) @@ -548,10 +507,23 @@ namespace Multiplayer inputArray[i] = m_inputHistory[historyIndex]; } +#ifndef AZ_RELEASE_BUILD + if (cl_EnableDesyncDebugging) + { + StateHistoryItem inputHistory = AZStd::make_unique(); + while (m_predictiveStateHistory.size() > cl_PredictiveStateHistorySize) + { + m_predictiveStateHistory.erase(m_predictiveStateHistory.begin()); + } + GetNetBindComponent()->SerializeEntityCorrection(*inputHistory); + m_predictiveStateHistory.emplace(m_clientInputId, AZStd::move(inputHistory)); + } +#endif + // Send the input to server (only when we are not migrating) if (!IsMigrating()) { - SendClientInput(inputArray, hashSerializer.GetHash(), processInputResult); + SendClientInput(inputArray, hashSerializer.GetHash()); } } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index e8da34fc7f..cbbbadeffa 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -267,6 +267,11 @@ namespace Multiplayer return m_isProcessingInput; } + bool NetBindComponent::IsReprocessingInput() const + { + return m_isReprocessingInput; + } + void NetBindComponent::CreateInput(NetworkInput& networkInput, float deltaTime) { // Only autonomous or authority runs this logic @@ -279,12 +284,21 @@ namespace Multiplayer void NetBindComponent::ProcessInput(NetworkInput& networkInput, float deltaTime) { + m_isProcessingInput = true; // Only autonomous and authority runs this logic AZ_Assert((NetworkRoleHasController(m_netEntityRole)), "Incorrect network role for input processing"); for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector) { multiplayerComponent->GetController()->ProcessInput(networkInput, deltaTime); } + m_isProcessingInput = false; + } + + void NetBindComponent::ReprocessInput(NetworkInput& networkInput, float deltaTime) + { + m_isReprocessingInput = true; + ProcessInput(networkInput, deltaTime); + m_isReprocessingInput = false; } bool NetBindComponent::HandleRpcMessage(AzNetworking::IConnection* invokingConnection, NetEntityRole remoteRole, NetworkEntityRpcMessage& message) @@ -649,6 +663,7 @@ namespace Multiplayer MultiplayerComponent* multiplayerComponent = azrtti_cast(component); if (multiplayerComponent != nullptr) { + multiplayerComponent->SetOwningConnectionId(m_owningConnectionId); m_multiplayerInputComponentVector.push_back(multiplayerComponent); } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 21c7ce80d6..16df4a629a 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -554,7 +554,7 @@ namespace Multiplayer m_tickFactor = 0.0f; m_lastReplicatedHostTimeMs = packet.GetHostTimeMs(); m_lastReplicatedHostFrameId = packet.GetHostFrameId(); - m_networkTime.AlterTime(m_lastReplicatedHostFrameId, m_lastReplicatedHostTimeMs, AzNetworking::InvalidConnectionId); + m_networkTime.ForceSetTime(m_lastReplicatedHostFrameId, m_lastReplicatedHostTimeMs); } for (AZStd::size_t i = 0; i < packet.GetEntityMessages().size(); ++i) @@ -856,7 +856,7 @@ namespace Multiplayer { m_tickFactor += deltaTime / serverRateSeconds; // Linear close to the origin, but asymptote at y = 1 - const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f); + const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, m_tickFactor); AZLOG ( NET_Blending, diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index b9e9a9a87e..78e90cc7fb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -524,6 +524,7 @@ namespace Multiplayer bool EntityReplicationManager::HandlePropertyChangeMessage ( + AzNetworking::IConnection* invokingConnection, EntityReplicator* entityReplicator, AzNetworking::PacketId packetId, NetEntityId netEntityId, @@ -558,6 +559,12 @@ namespace Multiplayer NetBindComponent* netBindComponent = replicatorEntity.GetNetBindComponent(); AZ_Assert(netBindComponent != nullptr, "No NetBindComponent"); + if (createEntity) + { + // Always set our invoking connectionId for any newly created entities, since this connection now 'owns' them from a rewind perspective + netBindComponent->SetOwningConnectionId(invokingConnection->GetConnectionId()); + } + const bool changeNetworkRole = (netBindComponent->GetNetEntityRole() != localNetworkRole); if (changeNetworkRole) { @@ -744,7 +751,7 @@ namespace Multiplayer bool EntityReplicationManager::HandleEntityUpdateMessage ( - [[maybe_unused]] AzNetworking::IConnection* invokingConnection, + AzNetworking::IConnection* invokingConnection, const AzNetworking::IPacketHeader& packetHeader, const NetworkEntityUpdateMessage& updateMessage ) @@ -794,7 +801,7 @@ namespace Multiplayer } // This may implicitly create a replicator for us - bool handled = HandlePropertyChangeMessage(entityReplicator, packetHeader.GetPacketId(), updateMessage.GetEntityId(), updateMessage.GetNetworkRole(), outputSerializer, prefabEntityId); + bool handled = HandlePropertyChangeMessage(invokingConnection, entityReplicator, packetHeader.GetPacketId(), updateMessage.GetEntityId(), updateMessage.GetNetworkRole(), outputSerializer, prefabEntityId); AZ_Assert(handled, "Failed to handle NetworkEntityUpdateMessage message"); return handled; @@ -1121,7 +1128,7 @@ namespace Multiplayer } } - bool EntityReplicationManager::HandleEntityMigration([[maybe_unused]] AzNetworking::IConnection* invokingConnection, EntityMigrationMessage& message) + bool EntityReplicationManager::HandleEntityMigration(AzNetworking::IConnection* invokingConnection, EntityMigrationMessage& message) { EntityReplicator* replicator = GetEntityReplicator(message.m_entityId); { @@ -1130,6 +1137,7 @@ namespace Multiplayer AzNetworking::TrackChangedSerializer outputSerializer(message.m_propertyUpdateData.GetBuffer(), message.m_propertyUpdateData.GetSize()); if (!HandlePropertyChangeMessage ( + invokingConnection, replicator, AzNetworking::InvalidPacketId, message.m_entityId, diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h index 9f5e743bbc..731a1a7556 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h @@ -136,6 +136,7 @@ namespace Multiplayer bool HandlePropertyChangeMessage ( + AzNetworking::IConnection* invokingConnection, EntityReplicator* entityReplicator, AzNetworking::PacketId packetId, NetEntityId netEntityId, diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index 645ce1fc00..5ae698e622 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -65,6 +65,15 @@ namespace Multiplayer return (IsTimeRewound() && (rewindConnectionId == m_rewindingConnectionId)) ? m_unalteredFrameId : m_hostFrameId; } + void NetworkTime::ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) + { + AZ_Assert(!IsTimeRewound(), "Forcibly setting network time is unsupported under a rewound time scope"); + m_unalteredFrameId = frameId; + m_hostFrameId = frameId; + m_hostTimeMs = timeMs; + m_rewindingConnectionId = AzNetworking::InvalidConnectionId; + } + void NetworkTime::AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) { m_hostFrameId = frameId; diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h index 4d568f40d9..4b94d3b6f2 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h @@ -32,6 +32,7 @@ namespace Multiplayer AZ::TimeMs GetHostTimeMs() const override; AzNetworking::ConnectionId GetRewindingConnectionId() const override; HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const override; + void ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) override; void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) override; void SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) override; void ClearRewoundEntities() override; From 699e8edb360da3916a8fa925735bb342627a564b Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Wed, 28 Jul 2021 12:31:19 -0700 Subject: [PATCH 002/101] Corrects math computing blend factors to interpolate state between received network updates Signed-off-by: kberg-amzn --- .../Source/MultiplayerSystemComponent.cpp | 37 +++++++++++++------ .../Code/Source/MultiplayerSystemComponent.h | 2 +- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 9a46bb10de..21c7ce80d6 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -69,19 +69,24 @@ namespace Multiplayer { using namespace AzNetworking; - AZ_CVAR(uint16_t, cl_clientport, 0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port to bind to for game traffic when connecting to a remote host, a value of 0 will select any available port"); - AZ_CVAR(AZ::CVarFixedString, cl_serveraddr, AZ::CVarFixedString(LocalHost), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The address of the remote server or host to connect to"); - AZ_CVAR(AZ::CVarFixedString, cl_serverpassword, "", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Optional server password"); + AZ_CVAR(uint16_t, cl_clientport, 0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The port to bind to for game traffic when connecting to a remote host, a value of 0 will select any available port"); + AZ_CVAR(AZ::CVarFixedString, cl_serveraddr, AZ::CVarFixedString(LocalHost), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The address of the remote server or host to connect to"); AZ_CVAR(uint16_t, cl_serverport, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port of the remote host to connect to for game traffic"); AZ_CVAR(uint16_t, sv_port, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that this multiplayer gem will bind to for game traffic"); AZ_CVAR(AZ::CVarFixedString, sv_map, "nolevel", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The map the server should load"); - AZ_CVAR(AZ::CVarFixedString, sv_gamerules, "norules", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "GameRules server works with"); AZ_CVAR(ProtocolType, sv_protocol, ProtocolType::Udp, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "This flag controls whether we use TCP or UDP for game networking"); AZ_CVAR(bool, sv_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server"); AZ_CVAR(bool, sv_isTransient, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether a dedicated server shuts down if all existing connections disconnect."); - AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything"); + AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "Max Ms to use to activate entities coming from the network, 0 means instantiate everything"); AZ_CVAR(AZ::TimeMs, sv_serverSendRateMs, AZ::TimeMs{ 50 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum number of milliseconds between each network update"); - AZ_CVAR(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset, "prefabs/player.network.spawnable", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The default spawnable to use when a new player connects"); + AZ_CVAR(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset, "prefabs/player.network.spawnable", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The default spawnable to use when a new player connects"); + AZ_CVAR(float, cl_renderTickBlendBase, 0.15f, nullptr, AZ::ConsoleFunctorFlags::Null, + "The base used for blending between network updates, 0.1 will be quite linear, 0.2 or 0.3 will " + "slow down quicker and may be better suited to connections with highly variable latency"); void MultiplayerSystemComponent::Reflect(AZ::ReflectContext* context) { @@ -546,7 +551,7 @@ namespace Multiplayer if ((GetAgentType() == MultiplayerAgentType::Client) && (packet.GetHostFrameId() > m_lastReplicatedHostFrameId)) { // Update client to latest server time - m_renderBlendFactor = 0.0f; + m_tickFactor = 0.0f; m_lastReplicatedHostTimeMs = packet.GetHostTimeMs(); m_lastReplicatedHostFrameId = packet.GetHostFrameId(); m_networkTime.AlterTime(m_lastReplicatedHostFrameId, m_lastReplicatedHostTimeMs, AzNetworking::InvalidConnectionId); @@ -849,10 +854,18 @@ namespace Multiplayer void MultiplayerSystemComponent::TickVisibleNetworkEntities(float deltaTime, float serverRateSeconds) { + m_tickFactor += deltaTime / serverRateSeconds; // Linear close to the origin, but asymptote at y = 1 - const float targetAdjustBlend = AZStd::clamp(deltaTime / serverRateSeconds, 0.0f, 1.0f); - m_renderBlendFactor = 1.0f - (std::pow(0.2f, m_renderBlendFactor + targetAdjustBlend)); - AZLOG(NET_Blending, "Computed blend factor of %0.2f using a frametime of %0.2f and a serverTickRate of %0.2f", m_renderBlendFactor, deltaTime, serverRateSeconds); + const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f); + AZLOG + ( + NET_Blending, + "Computed blend factor of %0.3f using a tick factor of %0.3f, a frametime of %0.3f and a serverTickRate of %0.3f", + renderBlendFactor, + m_tickFactor, + deltaTime, + serverRateSeconds + ); if (Camera::ActiveCameraRequestBus::HasHandlers()) { @@ -895,7 +908,7 @@ namespace Multiplayer for (NetBindComponent* netBindComponent : gatheredEntities) { - netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor); } } else @@ -907,7 +920,7 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor); } } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index 37e8138a71..ab37958962 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -155,7 +155,7 @@ namespace Multiplayer HostFrameId m_lastReplicatedHostFrameId = HostFrameId(0); double m_serverSendAccumulator = 0.0; - float m_renderBlendFactor = 0.0f; + float m_tickFactor = 0.0f; #if !defined(AZ_RELEASE_BUILD) MultiplayerEditorConnection m_editorConnectionListener; From 2f5927f1ac43c3f082cd3b3e69084d9d2c14554e Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Fri, 6 Aug 2021 17:45:54 -0700 Subject: [PATCH 003/101] [redcode/crythread-2nd-pass] remove dependency on cry threads in the remote console runtime Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../RemoteConsole/Core/RemoteConsoleCore.cpp | 88 +++++++++++-------- .../RemoteConsole/Core/RemoteConsoleCore.h | 42 ++++++--- 2 files changed, 84 insertions(+), 46 deletions(-) diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp index d4ef5b3ba8..94ae4cbfbf 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp @@ -93,40 +93,63 @@ bool RCON_IsRemoteAllowedToConnect(const AZ::AzSock::AzSocketAddress& connectee) ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// +void SRemoteThreadedObject::Start(const char* name) +{ + AZStd::thread_desc desc; + desc.m_name = name; + auto function = AZStd::bind(&SRemoteThreadedObject::ThreadFunction, this); + m_thread = AZStd::thread(function, &desc); +} + +void SRemoteThreadedObject::WaitForThread() +{ + if (m_thread.joinable()) + { + m_thread.join(); + } +} + +void SRemoteThreadedObject::ThreadFunction() +{ + Run(); + Terminate(); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::StartServer() { StopServer(); m_bAcceptClients = true; - Start(0, kServerThreadName); + Start(kServerThreadName); } ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::StopServer() { - Stop(); m_bAcceptClients = false; AZ::AzSock::CloseSocket(m_socket); m_socket = SOCKET_ERROR; - m_lock.Lock(); - for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { - it->pClient->StopClient(); + AZStd::lock_guard lock(m_mutex); + for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) + { + it->pClient->StopClient(); + } } - m_lock.Unlock(); - m_stopEvent.Wait(); - m_stopEvent.Set(); -} + AZStd::unique_lock lock(m_mutex); + m_stopCondition.wait(lock, [this] { return m_clients.empty(); });} ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::ClientDone(SRemoteClient* pClient) { - m_lock.Lock(); + AZStd::lock_guard lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { if (it->pClient == pClient) { - it->pClient->Stop(); delete it->pClient; delete it->pEvents; m_clients.erase(it); @@ -136,9 +159,8 @@ void SRemoteServer::ClientDone(SRemoteClient* pClient) if (m_clients.empty()) { - m_stopEvent.Set(); + m_stopCondition.notify_all(); } - m_lock.Unlock(); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -149,7 +171,6 @@ void SRemoteServer::Terminate() ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::Run() { - SetName(kServerThreadName); AZ_TRAIT_REMOTECONSOLE_SET_THREAD_AFFINITY AZSOCKET sClient; @@ -232,12 +253,10 @@ void SRemoteServer::Run() continue; } - m_lock.Lock(); - m_stopEvent.Reset(); + AZStd::lock_guard lock(m_mutex); SRemoteClient* pClient = new SRemoteClient(this); m_clients.push_back(SRemoteClientInfo(pClient)); pClient->StartClient(sClient); - m_lock.Unlock(); } AZ::AzSock::CloseSocket(m_socket); CryLog("Remote console terminating.\n"); @@ -247,43 +266,42 @@ void SRemoteServer::Run() ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::AddEvent(IRemoteEvent* pEvent) { - m_lock.Lock(); + AZStd::lock_guard lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { it->pEvents->push_back(pEvent->Clone()); } - m_lock.Unlock(); delete pEvent; } ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::GetEvents(TEventBuffer& buffer) { - m_lock.Lock(); + AZStd::lock_guard lock(m_mutex); buffer = m_eventBuffer; m_eventBuffer.clear(); - m_lock.Unlock(); } ///////////////////////////////////////////////////////////////////////////////////////////// bool SRemoteServer::WriteBuffer(SRemoteClient* pClient, char* buffer, int& size) { - m_lock.Lock(); IRemoteEvent* pEvent = nullptr; - for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { - if (it->pClient == pClient) + AZStd::lock_guard lock(m_mutex); + for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { - TEventBuffer* pEvents = it->pEvents; - if (!pEvents->empty()) + if (it->pClient == pClient) { - pEvent = pEvents->front(); - pEvents->pop_front(); + TEventBuffer* pEvents = it->pEvents; + if (!pEvents->empty()) + { + pEvent = pEvents->front(); + pEvents->pop_front(); + } + break; } - break; } } - m_lock.Unlock(); const bool res = (pEvent != nullptr); if (pEvent) { @@ -297,7 +315,7 @@ bool SRemoteServer::WriteBuffer(SRemoteClient* pClient, char* buffer, int& size bool SRemoteServer::ReadBuffer(const char* buffer, int data) { bool result = true; - + // Sometimes multiple events can come in a single buffer, so make sure we look // at the entire thing. int bytesRemaining = data; @@ -306,15 +324,14 @@ bool SRemoteServer::ReadBuffer(const char* buffer, int data) { // Create the event from the current sub string in the buffer. IRemoteEvent* event = SRemoteEventFactory::GetInst()->CreateEventFromBuffer(curBuffer, bytesRemaining); - + result &= (event != nullptr); if (event) { if (event->GetType() != eCET_Noop) { - m_lock.Lock(); + AZStd::lock_guard lock(m_mutex); m_eventBuffer.push_back(event); - m_lock.Unlock(); } else { @@ -337,7 +354,7 @@ bool SRemoteServer::ReadBuffer(const char* buffer, int data) void SRemoteClient::StartClient(AZSOCKET socket) { m_socket = socket; - Start(0, kClientThreadName); + Start(kClientThreadName); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -356,7 +373,6 @@ void SRemoteClient::Terminate() ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteClient::Run() { - SetName(kClientThreadName); AZ_TRAIT_REMOTECONSOLE_SET_THREAD_AFFINITY char szBuff[kDefaultBufferSize]; diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h index 45c3bf62d9..7e22be5735 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h @@ -11,9 +11,11 @@ #include #include #include +#include +#include +#include #include -#include extern const int defaultRemoteConsolePort; @@ -146,6 +148,30 @@ private: typedef AZStd::list TEventBuffer; + +///////////////////////////////////////////////////////////////////////////////////////////// +// SRemoteThreadedObject +// +// Simple runnable-like threaded object +// +///////////////////////////////////////////////////////////////////////////////////////////// +struct SRemoteThreadedObject +{ + virtual ~SRemoteThreadedObject() = default; + + void Start(const char* name); + + void WaitForThread(); + + virtual void Run() = 0; + virtual void Terminate() = 0; + +private: + void ThreadFunction(); + + AZStd::thread m_thread; +}; + ///////////////////////////////////////////////////////////////////////////////////////////// // SRemoteServer // @@ -154,10 +180,10 @@ typedef AZStd::list TEventBuffer; ///////////////////////////////////////////////////////////////////////////////////////////// struct SRemoteClient; struct SRemoteServer - : public CrySimpleThread<> + : public SRemoteThreadedObject { SRemoteServer() - : m_socket(AZ_SOCKET_INVALID) { m_stopEvent.Set(); } + : m_socket(AZ_SOCKET_INVALID) {} void StartServer(); void StopServer(); @@ -165,10 +191,8 @@ struct SRemoteServer void AddEvent(IRemoteEvent* pEvent); void GetEvents(TEventBuffer& buffer); - // CrySimpleThread void Terminate() override; void Run() override; - // ~CrySimpleThread private: bool WriteBuffer(SRemoteClient* pClient, char* buffer, int& size); @@ -189,9 +213,9 @@ private: typedef AZStd::vector TClients; TClients m_clients; AZSOCKET m_socket; - CryMutex m_lock; + AZStd::recursive_mutex m_mutex; TEventBuffer m_eventBuffer; - CryEvent m_stopEvent; + AZStd::condition_variable_any m_stopCondition; volatile bool m_bAcceptClients; friend struct SRemoteClient; }; @@ -204,7 +228,7 @@ private: // ///////////////////////////////////////////////////////////////////////////////////////////// struct SRemoteClient - : public CrySimpleThread<> + : public SRemoteThreadedObject { SRemoteClient(SRemoteServer* pServer) : m_pServer(pServer) @@ -213,10 +237,8 @@ struct SRemoteClient void StartClient(AZSOCKET socket); void StopClient(); - // CrySimpleThread void Terminate() override; void Run() override; - // ~CrySimpleThread private: bool RecvPackage(char* buffer, int& size); From 3e7d7d150e72015fb57b3c4f2ef15bf5b95a45aa Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Fri, 6 Aug 2021 18:22:28 -0700 Subject: [PATCH 004/101] [redcode/crythread-2nd-pass] removed CryThread_dummy.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/CryThread.h | 1 - Code/Legacy/CryCommon/CryThread_dummy.h | 152 -------------------- Code/Legacy/CryCommon/crycommon_files.cmake | 1 - 3 files changed, 154 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CryThread_dummy.h diff --git a/Code/Legacy/CryCommon/CryThread.h b/Code/Legacy/CryCommon/CryThread.h index 5929bed352..b7b6a3adfd 100644 --- a/Code/Legacy/CryCommon/CryThread.h +++ b/Code/Legacy/CryCommon/CryThread.h @@ -175,7 +175,6 @@ class CrySimpleThread; #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #else // Put other platform specific includes here! -#include #endif #if !defined _CRYTHREAD_CONDLOCK_GLITCH diff --git a/Code/Legacy/CryCommon/CryThread_dummy.h b/Code/Legacy/CryCommon/CryThread_dummy.h deleted file mode 100644 index d97b6c5b55..0000000000 --- a/Code/Legacy/CryCommon/CryThread_dummy.h +++ /dev/null @@ -1,152 +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 - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H -#define CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H -#pragma once - -#include - -////////////////////////////////////////////////////////////////////////// -CryEvent::CryEvent() {} -CryEvent::~CryEvent() {} -void CryEvent::Reset() {} -void CryEvent::Set() {} -void CryEvent::Wait() const {} -bool CryEvent::Wait(const uint32 timeoutMillis) const {} -typedef CryEvent CryEventTimed; - -////////////////////////////////////////////////////////////////////////// -class _DummyLock -{ -public: - _DummyLock(); - - void Lock(); - bool TryLock(); - void Unlock(); - -#if defined(AZ_DEBUG_BUILD) - bool IsLocked(); -#endif -}; - -template<> -class CryLock - : public _DummyLock -{ - CryLock(const CryLock&); - void operator = (const CryLock&); - -public: - CryLock(); -}; - -template<> -class CryLock - : public _DummyLock -{ - CryLock(const CryLock&); - void operator = (const CryLock&); - -public: - CryLock(); -}; - -template<> -class CryCondLock - : public CryLock -{ -}; - -template<> -class CryCondLock - : public CryLock -{ -}; - -template<> -class CryCond< CryLock > -{ - typedef CryLock LockT; - CryCond(const CryCond&); - void operator = (const CryCond&); - -public: - CryCond(); - - void Notify(); - void NotifySingle(); - void Wait(LockT&); - bool TimedWait(LockT &, uint32); -}; - -template<> -class CryCond< CryLock > -{ - typedef CryLock LockT; - CryCond(const CryCond&); - void operator = (const CryCond&); - -public: - CryCond(); - - void Notify(); - void NotifySingle(); - void Wait(LockT&); - bool TimedWait(LockT &, uint32); -}; - -class _DummyRWLock -{ -public: - _DummyRWLock() { } - - void RLock(); - bool TryRLock(); - void WLock(); - bool TryWLock(); - void Lock() { WLock(); } - bool TryLock() { return TryWLock(); } - void Unlock(); -}; - -template -class CrySimpleThread - : public CryRunnable -{ -public: - typedef void (* ThreadFunction)(void*); - - CrySimpleThread(); - virtual ~CrySimpleThread(); -#if !defined(NO_THREADINFO) - CryThreadInfo& GetInfo(); -#endif - const char* GetName(); - void SetName(const char*); - - virtual void Run(); - virtual void Cancel(); - virtual void Start(Runnable&, unsigned = 0, const char* = NULL); - virtual void Start(unsigned = 0, const char* = NULL); - void StartFunction(ThreadFunction, void* = NULL, unsigned = 0); - - void Exit(); - void Join(); - unsigned SetCpuMask(unsigned); - unsigned GetCpuMask(); - - void Stop(); - bool IsStarted() const; - bool IsRunning() const; -}; - -#endif // CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H - diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 0392f11c89..b4dac2ec08 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -160,7 +160,6 @@ set(FILES CryAssert_Mac.h CryLibrary.cpp CryLibrary.h - CryThread_dummy.h CryThread_pthreads.h CryThread_windows.h CryThreadImpl_pthreads.h From 4beb66c9caee9e9f1c3bce290c3ccc851ebe75d4 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Sun, 8 Aug 2021 23:37:54 -0700 Subject: [PATCH 005/101] Making pass files declare dependency on shader files (part 01) Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Code/Source/Editor/ShaderAssetBuilder.cpp | 3 +- .../Editor/ShaderVariantAssetBuilder.cpp | 2 +- .../Source/RPI.Builders/Pass/PassBuilder.cpp | 197 ++++++++++++++---- .../Source/RPI.Builders/Pass/PassBuilder.h | 1 - 4 files changed, 159 insertions(+), 44 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index b1a3de2794..606502fb22 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -139,8 +139,7 @@ namespace AZ AssetBuilderSDK::JobDescriptor jobDescriptor; jobDescriptor.m_priority = 2; - // [GFX TODO][ATOM-2830] Set 'm_critical' back to 'false' once proper fix for Atom startup issues are in - jobDescriptor.m_critical = true; + jobDescriptor.m_critical = false; jobDescriptor.m_jobKey = ShaderAssetBuilderJobKey; jobDescriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); jobDescriptor.m_jobParameters.emplace(ShaderAssetBuildTimestampParam, AZStd::to_string(shaderAssetBuildTimestamp)); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 1da4623774..ee02ae8452 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -321,7 +321,7 @@ namespace AZ AssetBuilderSDK::JobDescriptor jobDescriptor; jobDescriptor.m_priority = -5000; - jobDescriptor.m_critical = false; + jobDescriptor.m_critical = true; jobDescriptor.m_jobKey = ShaderVariantAssetBuilderJobKey; jobDescriptor.SetPlatformIdentifier(info.m_identifier.data()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index 652130dea2..f582f3ba04 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -37,7 +37,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc builder; builder.m_name = PassBuilderJobKey; - builder.m_version = 12; // ATOM-15472 + builder.m_version = 13; // antonmic: making .pass files declare dependency on shaders they reference builder.m_busId = azrtti_typeid(); builder.m_createJobFunction = AZStd::bind(&PassBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2); builder.m_processJobFunction = AZStd::bind(&PassBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2); @@ -65,35 +65,66 @@ namespace AZ m_isShuttingDown = true; } - void PassBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const + // --- Code related to dependency shader asset handling --- + + struct FindPassReferenceAssetParams { - if (m_isShuttingDown) + void* passAssetObject; + Uuid passAssetUuid; + SerializeContext* serializeContext; + AZStd::string_view passAssetSourceFile; // File path of the pass asset + AZStd::string_view dependencySourceFile; // File pass of the asset the pass asset depends on + const char* jobKey; // Job key for adding job dependency + }; + + //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. + //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. + //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back + //! to the AssetBuilderSDK::CreateJobsResponse. + void AddPossibleDependencies( + FindPassReferenceAssetParams& params, + AssetBuilderSDK::CreateJobsResponse& response, + AssetBuilderSDK::JobDescriptor& job) + { + bool dependencyFileFound = false; + + AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(params.passAssetSourceFile, params.dependencySourceFile); + for (auto& file : possibleDependencies) { - response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown; - return; + AssetBuilderSDK::SourceFileDependency sourceFileDependency; + sourceFileDependency.m_sourceFileDependencyPath = file; + response.m_sourceFileDependencyList.push_back(sourceFileDependency); + + // The first path found is the highest priority, and will have a job dependency, as this is the one + // the builder will actually use + if (!dependencyFileFound) + { + AZ::Data::AssetInfo sourceInfo; + AZStd::string watchFolder; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(dependencyFileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.c_str(), sourceInfo, watchFolder); + + if (dependencyFileFound) + { + AssetBuilderSDK::JobDependency jobDependency; + jobDependency.m_jobKey = params.jobKey; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; + job.m_jobDependencyList.push_back(jobDependency); + } + } } - - for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms) - { - AssetBuilderSDK::JobDescriptor job; - job.m_jobKey = PassBuilderJobKey; - job.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); - - // Passes are a critical part of the rendering system - job.m_critical = true; - - response.m_createJobOutputs.push_back(job); - } - - response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; } // Helper function to find all assetId's and object references - bool PassBuilder::FindPassReferencedAssets(void* objectPtr, Uuid passAssetUuid, SerializeContext* context, AZStd::unordered_set &referencedAssetList) const + bool FindPassReferencedAssets(FindPassReferenceAssetParams& params, + AZStd::unordered_set& referencedAssetList, + AssetBuilderSDK::CreateJobsResponse& response, + AssetBuilderSDK::JobDescriptor& job, + bool jobCreationPhase) { SerializeContext::ErrorHandler errorLogger; errorLogger.Reset(); - + bool foundProblems = false; // This callback will check whether the given element is an asset reference. If so, it will add it to the list of asset references @@ -103,26 +134,34 @@ namespace AZ if (classData->m_typeId == azrtti_typeid()) { AssetReference* assetReference = reinterpret_cast(ptr); - + // If the asset id isn't already provided, get it using the source file path if (!assetReference->m_assetId.IsValid() && !assetReference->m_filePath.empty()) { - AZStd::string path = assetReference->m_filePath; + const AZStd::string& path = assetReference->m_filePath; uint32_t subId = 0; - auto assetIdOutcome = AssetUtils::MakeAssetId(path, subId); - - if (assetIdOutcome) + if (jobCreationPhase) { - assetReference->m_assetId = assetIdOutcome.GetValue(); + params.dependencySourceFile = path; + AddPossibleDependencies(params, response, job); } - else + else // Process Job Phase { - AZ_Error(PassBuilderName, false, "Could not get AssetId for [%s]", assetReference->m_filePath.c_str()); - foundProblems = true; + auto assetIdOutcome = AssetUtils::MakeAssetId(path, subId); + + if (assetIdOutcome) + { + assetReference->m_assetId = assetIdOutcome.GetValue(); + } + else + { + AZ_Error(PassBuilderName, false, "Could not get AssetId for [%s]", assetReference->m_filePath.c_str()); + foundProblems = true; + } } } - + // If the asset ID is valid, add it as a dependency if (assetReference->m_assetId.IsValid()) { @@ -136,16 +175,16 @@ namespace AZ SerializeContext::EnumerateInstanceCallContext callContext( AZStd::move(beginCallback), nullptr, - context, + params.serializeContext, SerializeContext::ENUM_ACCESS_FOR_READ, &errorLogger ); // Recursively iterate over all elements in the object to find asset references with the above callback - context->EnumerateInstance( + params.serializeContext->EnumerateInstance( &callContext - , objectPtr - , passAssetUuid + , params.passAssetObject + , params.passAssetUuid , nullptr , nullptr ); @@ -153,6 +192,73 @@ namespace AZ return !foundProblems; } + // --- Code related to dependency shader asset handling --- + + void PassBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const + { + if (m_isShuttingDown) + { + response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown; + return; + } + + AssetBuilderSDK::JobDescriptor job; + + // Get serialization context + SerializeContext* serializeContext = nullptr; + ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext); + if (!serializeContext) + { + AZ_Assert(false, "No serialize context"); + return; + } + + // Load PassAsset + AZStd::string fullPath; + AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.c_str(), request.m_sourceFile.c_str(), fullPath, true); + + PassAsset passAsset; + AZ::Outcome loadResult = JsonSerializationUtils::LoadObjectFromFile(passAsset, fullPath); + + if (!loadResult.IsSuccess()) + { + AZ_Error(PassBuilderName, false, "Failed to load pass asset [%s]", request.m_sourceFile.c_str()); + AZ_Error(PassBuilderName, false, "Loading issues: %s", loadResult.GetError().data()); + return; + } + + // Find all Asset IDs we depend on + AZStd::unordered_set dependentList; + Uuid passAssetUuid = AzTypeInfo::Uuid(); + + FindPassReferenceAssetParams params; + params.passAssetObject = &passAsset; + params.passAssetSourceFile = request.m_sourceFile; + params.passAssetUuid = passAssetUuid; + params.serializeContext = serializeContext; + params.jobKey = "Shader Asset"; + + if (!FindPassReferencedAssets(params, dependentList, response, job, true)) + { + return; + } + + for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms) + { + job.m_jobKey = PassBuilderJobKey; + job.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); + + // Passes are a critical part of the rendering system + job.m_critical = true; + + response.m_createJobOutputs.push_back(job); + } + + response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; + } + + + void PassBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const { // Handle job cancellation and shutdown cases @@ -164,9 +270,9 @@ namespace AZ } // Get serialization context - SerializeContext* context = nullptr; - ComponentApplicationBus::BroadcastResult(context, &ComponentApplicationBus::Events::GetSerializeContext); - if (!context) + SerializeContext* serializeContext = nullptr; + ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext); + if (!serializeContext) { AZ_Assert(false, "No serialize context"); return; @@ -186,7 +292,18 @@ namespace AZ // Find all Asset IDs we depend on AZStd::unordered_set dependentList; Uuid passAssetUuid = AzTypeInfo::Uuid(); - if (!FindPassReferencedAssets(&passAsset, passAssetUuid, context, dependentList)) + + FindPassReferenceAssetParams params; + params.passAssetObject = &passAsset; + params.passAssetSourceFile = request.m_sourceFile; + params.passAssetUuid = passAssetUuid; + params.serializeContext = serializeContext; + params.jobKey = "Shader Asset"; + + AssetBuilderSDK::CreateJobsResponse dummyResponse; + AssetBuilderSDK::JobDescriptor dummyJob; + + if (!FindPassReferencedAssets(params, dependentList, dummyResponse, dummyJob, false)) { return; } @@ -198,7 +315,7 @@ namespace AZ AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), destFileName.c_str(), destPath, true); // Save the asset to binary format for production - bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, &passAsset, passAssetUuid, context); + bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, &passAsset, passAssetUuid, serializeContext); if (result == false) { AZ_Error(PassBuilderName, false, "Failed to save asset to %s", destPath.c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.h b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.h index 6130ae8edc..8c159efc56 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.h +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.h @@ -37,7 +37,6 @@ namespace AZ void RegisterBuilder(); private: - bool FindPassReferencedAssets(void* objectPtr, Uuid passAssetUuid, SerializeContext* context, AZStd::unordered_set &referencedAssetList) const; bool m_isShuttingDown = false; }; From 635b9686c6915803d472a56740b1c1cf028c417d Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:18:38 -0700 Subject: [PATCH 006/101] [redcode/crythread-2nd-pass] removed CrySimpleThread and related code Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/CryThread.h | 75 --- .../Legacy/CryCommon/CryThreadImpl_pthreads.h | 7 - Code/Legacy/CryCommon/CryThreadImpl_windows.h | 51 -- Code/Legacy/CryCommon/CryThread_pthreads.h | 440 ------------------ Code/Legacy/CryCommon/CryThread_windows.h | 206 -------- 5 files changed, 779 deletions(-) diff --git a/Code/Legacy/CryCommon/CryThread.h b/Code/Legacy/CryCommon/CryThread.h index b7b6a3adfd..fcd7be16ba 100644 --- a/Code/Legacy/CryCommon/CryThread.h +++ b/Code/Legacy/CryCommon/CryThread.h @@ -85,81 +85,6 @@ public: ////////////////////////////////////////////////////////////////////////// typedef CryAutoLock CryAutoCriticalSection; -///////////////////////////////////////////////////////////////////////////// -// -// Threads. - -// Base class for runnable objects. -// -// A runnable is an object with a Run() and a Cancel() method. The Run() -// method should perform the runnable's job. The Cancel() method may be -// called by another thread requesting early termination of the Run() method. -// The runnable may ignore the Cancel() call, the default implementation of -// Cancel() does nothing. -class CryRunnable -{ -public: - virtual ~CryRunnable() { } - virtual void Run() = 0; - virtual void Cancel() { } -}; - -// Class holding information about a thread. -// -// A reference to the thread information can be obtained by calling GetInfo() -// on the CrySimpleThread (or derived class) instance. -// -// NOTE: -// If the code is compiled with NO_THREADINFO defined, then the GetInfo() -// method will return a reference to a static dummy instance of this -// structure. It is currently undecided if NO_THREADINFO will be defined for -// release builds! - -struct CryThreadInfo -{ - // The symbolic name of the thread. - // - // You may set this name directly or through the SetName() method of - // CrySimpleThread (or derived class). - AZStd::string m_Name; - - - // A thread identification number. - // The number is unique but architecture specific. Do not assume anything - // about that number except for being unique. - // - // This field is filled when the thread is started (i.e. before the Run() - // method or thread routine is called). It is advised that you do not - // change this number manually. - uint32 m_ID; -}; - -// Simple thread class. -// -// CrySimpleThread is a simple wrapper around a system thread providing -// nothing but system-level functionality of a thread. There are two typical -// ways to use a simple thread: -// -// 1. Derive from the CrySimpleThread class and provide an implementation of -// the Run() (and optionally Cancel()) methods. -// 2. Specify a runnable object when the thread is started. The default -// runnable type is CryRunnable. -// -// The Runnable class specfied as the template argument must provide Run() -// and Cancel() methods compatible with the following signatures: -// -// void Runnable::Run(); -// void Runnable::Cancel(); -// -// If the Runnable does not support cancellation, then the Cancel() method -// should do nothing. -// -// The same instance of CrySimpleThread may be used for multiple thread -// executions /in sequence/, i.e. it is valid to re-start the thread by -// calling Start() after the thread has been joined by calling WaitForThread(). -template -class CrySimpleThread; - /////////////////////////////////////////////////////////////////////////////// // Include architecture specific code. #if AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS diff --git a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h index c94d4fca90..358d8f962f 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h @@ -14,13 +14,6 @@ #include "CryThread_pthreads.h" -#if PLATFORM_SUPPORTS_THREADLOCAL -THREADLOCAL CrySimpleThreadSelf -* CrySimpleThreadSelf::m_Self = NULL; -#else -TLS_DEFINE(CrySimpleThreadSelf*, g_CrySimpleThreadSelf) -#endif - ////////////////////////////////////////////////////////////////////////// // CryEvent(Timed) implementation diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h index 5cf970414d..9d636fd41a 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_windows.h @@ -12,16 +12,6 @@ #include #include // for CreateSemaphore -struct SThreadNameDesc -{ - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; -}; - -THREADLOCAL CrySimpleThreadSelf* CrySimpleThreadSelf::m_Self = NULL; - ////////////////////////////////////////////////////////////////////////// CryEvent::CryEvent() { @@ -302,44 +292,3 @@ void CryFastSemaphore::Release() m_Semaphore.Release(); } } - -////////////////////////////////////////////////////////////////////////// -CrySimpleThreadSelf::CrySimpleThreadSelf() - : m_thread(NULL) - , m_threadId(0) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CrySimpleThreadSelf::WaitForThread() -{ - assert(m_thread); - PREFAST_ASSUME(m_thread); - if (GetCurrentThreadId() != m_threadId) - { - WaitForSingleObject((HANDLE)m_thread, INFINITE); - } -} - -CrySimpleThreadSelf::~CrySimpleThreadSelf() -{ - if (m_thread) - { - CloseHandle(m_thread); - } -} - -void CrySimpleThreadSelf::StartThread(unsigned (__stdcall * func)(void*), void* argList) -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #include AZ_RESTRICTED_FILE(CryThreadImpl_windows_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - m_thread = (void*)_beginthreadex(NULL, 0, func, argList, CREATE_SUSPENDED, &m_threadId); -#endif - assert(m_thread); - PREFAST_ASSUME(m_thread); - ResumeThread((HANDLE)m_thread); -} diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h index 72b29344ec..9102c12c38 100644 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ b/Code/Legacy/CryCommon/CryThread_pthreads.h @@ -653,444 +653,4 @@ private: typedef CryEventTimed CryEvent; -#if !PLATFORM_SUPPORTS_THREADLOCAL -TLS_DECLARE(class CrySimpleThreadSelf*, g_CrySimpleThreadSelf); -#endif - -class CrySimpleThreadSelf -{ -protected: -#if PLATFORM_SUPPORTS_THREADLOCAL - - static CrySimpleThreadSelf* GetSelf() - { - return m_Self; - } - - static void SetSelf(CrySimpleThreadSelf* pSelf) - { - m_Self = pSelf; - } -private: - static THREADLOCAL CrySimpleThreadSelf* m_Self; - -#else - - static CrySimpleThreadSelf* GetSelf() - { - return TLS_GET(CrySimpleThreadSelf*, g_CrySimpleThreadSelf); - } - - static void SetSelf(CrySimpleThreadSelf* pSelf) - { - TLS_SET(g_CrySimpleThreadSelf, pSelf); - } - -#endif -}; - -template -class CrySimpleThread - : public CryRunnable - , protected CrySimpleThreadSelf -{ -public: - typedef void (* ThreadFunction)(void*); - typedef CryRunnable RunnableT; - - const volatile bool& GetStartedState() const { return m_bIsStarted; } - -private: -#if !defined(NO_THREADINFO) - CryThreadInfo m_Info; -#endif - pthread_t m_ThreadID; - unsigned m_CpuMask; - Runnable* m_Runnable; - struct - { - ThreadFunction m_ThreadFunction; - void* m_ThreadParameter; - } m_ThreadFunction; - volatile bool m_bIsStarted; - volatile bool m_bIsRunning; - -protected: - virtual void Terminate() - { - // This method must be empty. - // Derived classes overriding Terminate() are not required to call this - // method. - } - -private: -#if !defined(NO_THREADINFO) - static void SetThreadInfo(CrySimpleThread* self) - { - pthread_t thread = pthread_self(); - self->m_Info.m_ID = (uint32)(TRUNCATE_PTR)thread; -#if defined(APPLE) - pthread_setname_np(self->m_Info.m_Name.c_str()); -#endif - } -#else - static void SetThreadInfo(CrySimpleThread* self) { } -#endif - - static void* PthreadRunRunnable(void* thisPtr) - { - CrySimpleThread* const self = (CrySimpleThread*)thisPtr; - SetSelf(self); - self->m_bIsStarted = true; - self->m_bIsRunning = true; - SetThreadInfo(self); - self->m_Runnable->Run(); - self->m_bIsRunning = false; - self->Terminate(); - SetSelf(NULL); - return NULL; - } - - static void* PthreadRunThis(void* thisPtr) - { - CrySimpleThread* const self = (CrySimpleThread*)thisPtr; - SetSelf(self); - self->m_bIsStarted = true; - self->m_bIsRunning = true; - SetThreadInfo(self); - self->Run(); - self->m_bIsRunning = false; - self->Terminate(); - SetSelf(NULL); - return NULL; - } - - CrySimpleThread(const CrySimpleThread&); - void operator = (const CrySimpleThread&); - -public: - CrySimpleThread() - : m_CpuMask(0) - , m_bIsStarted(false) - , m_bIsRunning(false) - { - m_ThreadFunction.m_ThreadFunction = NULL; - m_ThreadFunction.m_ThreadParameter = NULL; -#if !defined(NO_THREADINFO) - m_Info.m_Name = ""; - m_Info.m_ID = 0; -#endif - memset(&m_ThreadID, 0, sizeof m_ThreadID); - m_Runnable = NULL; - } - - virtual ~CrySimpleThread() - { - if (IsStarted()) - { - // Note: We don't want to cache a pointer to ISystem and/or ILog to - // gain more freedom on when the threading classes are used (e.g. - // threads may be started very early in the initialization). - ISystem* pSystem = GetISystem(); - ILog* pLog = NULL; - if (pSystem != NULL) - { - pLog = pSystem->GetILog(); - } - if (pLog != NULL) - { - pLog->LogError("Runaway thread %s", GetName()); - } - Cancel(); - WaitForThread(); - } - } - -#if !defined(NO_THREADINFO) - CryThreadInfo& GetInfo() { return m_Info; } - const char* GetName() - { - return m_Info.m_Name.c_str(); - } - - // Set the name of the called thread. - // - // WIN32: - // If the thread is started, then the VC debugger is informed about the new - // thread name. If the thread is not started, then the VC debugger will be - // informed lated when the thread is started through one of the Start() - // methods. - // - // If the parameter Name is NULL, then the name of the thread is kept - // unchanged. This may be used to sent the current thread name to the VC - // debugger. - void SetName(const char* Name) - { - if (Name != NULL) - { - if (m_ThreadID) - { - RegisterThreadName(m_ThreadID, Name); - } - m_Info.m_Name = Name; - } -#if defined(WIN32) - if (IsStarted()) - { - // The VC debugger gets the information about a thread's name through - // the exception 0x406D1388. - struct - { - DWORD Type; - const char* Name; - DWORD ID; - DWORD Flags; - } Info = { 0x1000, NULL, 0, 0 }; - Info.ID = (DWORD)m_Info.m_ID; - __try - { - RaiseException( - 0x406D1388, 0, sizeof Info / sizeof(DWORD), (ULONG_PTR*)&Info); - } - __except (EXCEPTION_CONTINUE_EXECUTION) - { - } - } -#endif - } -#else -#if !defined(NO_THREADINFO) - CryThreadInfo& GetInfo() - { - static CryThreadInfo dummyInfo = { "", 0 }; - return dummyInfo; - } -#endif - const char* GetName() { return ""; } - void SetName(const char* Name) { } -#endif - - virtual void Run() - { - // This Run() implementation supports the void StartFunction() method. - // However, code using this class (or derived classes) should eventually - // be refactored to use one of the other Start() methods. This code will - // be removed some day and the default implementation of Run() will be - // empty. - if (m_ThreadFunction.m_ThreadFunction != NULL) - { - m_ThreadFunction.m_ThreadFunction(m_ThreadFunction.m_ThreadParameter); - } - } - - // Cancel the running thread. - // - // If the thread class is implemented as a derived class of CrySimpleThread, - // then the derived class should provide an appropriate implementation for - // this method. Calling the base class implementation is _not_ required. - // - // If the thread was started by specifying a Runnable (template argument), - // then the Cancel() call is passed on to the specified runnable. - // - // If the thread was started using the StartFunction() method, then the - // caller must find other means to inform the thread about the cancellation - // request. - virtual void Cancel() - { - if (IsStarted() && m_Runnable != NULL) - { - UnRegisterThreadName(m_ThreadID); - m_Runnable->Cancel(); - } - } - - virtual void Start(Runnable& runnable, unsigned cpuMask = 0, const char* name = NULL, int32 StackSize = (SIMPLE_THREAD_STACK_SIZE_KB * 1024)) - { -#if defined(LARGE_THREAD_STACK) - StackSize *= 4;//debug code needs a lot more than profile -#endif - assert(m_ThreadID == 0); - pthread_attr_t threadAttr; - pthread_attr_init(&threadAttr); - pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setstacksize(&threadAttr, StackSize); - if (name) - { - this->m_Info.m_Name = name; - } -#if CRYTHREAD_PTHREADS_H_TRAIT_SET_THREAD_NAME - threadAttr.name = (char*)name; -#endif - m_CpuMask = cpuMask; -#if defined(PTHREAD_NPTL) - if (cpuMask != ~0 && cpuMask != 0) - { - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - for (int cpu = 0; cpu < sizeof(cpuMask) * 8; ++cpu) - { - if (cpuMask & (1 << cpu)) - { - CPU_SET(cpu, &cpuSet); - } - } - pthread_attr_setaffinity_np(&threadAttr, sizeof cpuSet, &cpuSet); - } -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_START_RUNNABLE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - m_Runnable = &runnable; - int err = pthread_create( - &m_ThreadID, - &threadAttr, - PthreadRunRunnable, - this); - pthread_attr_destroy(&threadAttr); - RegisterThreadName(m_ThreadID, name); -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_START_RUNNABLE_CPUMASK_POSTCREATE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - assert(err == 0); - } - - virtual void Start(unsigned cpuMask = 0, const char* name = NULL, int32 Priority = THREAD_PRIORITY_NORMAL, int32 StackSize = (SIMPLE_THREAD_STACK_SIZE_KB * 1024)) - { -#if defined(LARGE_THREAD_STACK) - StackSize *= 4;//debug code needs a lot more than profile -#endif - assert(m_ThreadID == 0); - pthread_attr_t threadAttr; - sched_param schedParam; - pthread_attr_init(&threadAttr); - pthread_attr_getschedparam(&threadAttr, &schedParam); - schedParam.sched_priority = Priority; - pthread_attr_setschedparam(&threadAttr, &schedParam); - pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setstacksize(&threadAttr, StackSize); - if (name) - { - this->m_Info.m_Name = name; - } -#if CRYTHREAD_PTHREADS_H_TRAIT_SET_THREAD_NAME - threadAttr.name = (char*)name; -#endif - m_CpuMask = cpuMask; -#if defined(PTHREAD_NPTL) - if (cpuMask != ~0 && cpuMask != 0) - { - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - for (int cpu = 0; cpu < sizeof(cpuMask) * 8; ++cpu) - { - if (cpuMask & (1 << cpu)) - { - CPU_SET(cpu, &cpuSet); - } - } - pthread_attr_setaffinity_np(&threadAttr, sizeof cpuSet, &cpuSet); - } -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_START_CPUMASK - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - int err = pthread_create( - &m_ThreadID, - &threadAttr, - PthreadRunThis, - this); - pthread_attr_destroy(&threadAttr); - RegisterThreadName(m_ThreadID, name); -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_START_CPUMASK_POSTCREATE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - assert(err == 0); - } - - void StartFunction( - ThreadFunction threadFunction, - void* threadParameter = NULL, - unsigned cpuMask = 0 - ) - { - m_ThreadFunction.m_ThreadFunction = threadFunction; - m_ThreadFunction.m_ThreadParameter = threadParameter; - Start(cpuMask); - } - - static CrySimpleThread* Self() - { - return reinterpret_cast*>(GetSelf()); - } - - void Exit() - { - assert(m_ThreadID == pthread_self()); - m_bIsRunning = false; - Terminate(); - SetSelf(NULL); - pthread_exit(NULL); - UnRegisterThreadName(m_ThreadID); - } - - void WaitForThread() - { - if (pthread_self() != m_ThreadID) - { - int err = pthread_join(m_ThreadID, NULL); - assert(err == 0); - } - m_bIsStarted = false; - memset(&m_ThreadID, 0, sizeof m_ThreadID); - } - - unsigned SetCpuMask(unsigned cpuMask) - { - int oldCpuMask = m_CpuMask; - if (cpuMask == m_CpuMask) - { - return oldCpuMask; - } - m_CpuMask = cpuMask; -#if defined(PTHREAD_NPTL) - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - if (cpuMask != ~0 && cpuMask != 0) - { - for (int cpu = 0; cpu < sizeof(cpuMask) * 8; ++cpu) - { - if (cpuMask & (1 << cpu)) - { - CPU_SET(cpu, &cpuSet); - } - } - else - { - CPU_ZERO(&cpuSet); - for (int cpu = 0; i < sizeof(cpuSet) * 8; ++cpu) - { - CPU_SET(cpu, &cpuSet); - } - } - pthread_attr_setaffinity_np(&threadAttr, sizeof cpuSet, &cpuSet); -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SETCPUMASK - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - return oldCpuMask; - } - - unsigned GetCpuMask() { return m_CpuMask; } - - void Stop() - { - m_bIsStarted = false; - } - - bool IsStarted() const { return m_bIsStarted; } - bool IsRunning() const { return m_bIsRunning; } - }; - #include "MemoryAccess.h" diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h index cc09cc530b..87147549f7 100644 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ b/Code/Legacy/CryCommon/CryThread_windows.h @@ -179,209 +179,3 @@ private: CrySemaphore m_Semaphore; volatile int32 m_nCounter; }; - -////////////////////////////////////////////////////////////////////////// -class CrySimpleThreadSelf -{ -public: - CrySimpleThreadSelf(); - void WaitForThread(); - virtual ~CrySimpleThreadSelf(); -protected: - void StartThread(unsigned (__stdcall * func)(void*), void* argList); - static THREADLOCAL CrySimpleThreadSelf* m_Self; -private: - CrySimpleThreadSelf(const CrySimpleThreadSelf&); - CrySimpleThreadSelf& operator = (const CrySimpleThreadSelf&); -protected: - void* m_thread; - uint32 m_threadId; -}; - -template -class CrySimpleThread - : public CryRunnable - , public CrySimpleThreadSelf -{ -public: - typedef void (* ThreadFunction)(void*); - typedef CryRunnable RunnableT; - - void SetName(const char* Name) - { - m_name = Name; - } - const char* GetName() { return m_name; } - - const volatile bool& GetStartedState() const { return m_bIsStarted; } - -private: - Runnable* m_Runnable; - struct - { - ThreadFunction m_ThreadFunction; - void* m_ThreadParameter; - } m_ThreadFunction; - volatile bool m_bIsStarted; - volatile bool m_bIsRunning; - volatile bool m_bCreatedThread; - string m_name; - -protected: - virtual void Terminate() - { - // This method must be empty. - // Derived classes overriding Terminate() are not required to call this - // method. - } - -private: - static unsigned __stdcall RunRunnable(void* thisPtr) - { -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_WINDOWS_H_SECTION_1 - #include AZ_RESTRICTED_FILE(CryThread_windows_h) -#endif - CrySimpleThread* const self = (CrySimpleThread*)thisPtr; - self->m_bIsStarted = true; - self->m_bIsRunning = true; - - self->m_Runnable->Run(); - self->m_bIsRunning = false; - self->m_bCreatedThread = false; - self->Terminate(); - return 0; - } - - static unsigned __stdcall RunThis(void* thisPtr) - { -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_WINDOWS_H_SECTION_2 - #include AZ_RESTRICTED_FILE(CryThread_windows_h) -#endif - CrySimpleThread* const self = (CrySimpleThread*)thisPtr; - self->m_bIsStarted = true; - self->m_bIsRunning = true; - - self->Run(); - self->m_bIsRunning = false; - self->m_bCreatedThread = false; - self->Terminate(); - return 0; - } - - CrySimpleThread(const CrySimpleThread&); - void operator = (const CrySimpleThread&); - -public: - CrySimpleThread() - : m_bIsStarted(false) - , m_bIsRunning(false) - , m_bCreatedThread(false) - { - m_thread = NULL; - m_Runnable = NULL; - } - void* GetHandle() { return m_thread; } - - virtual ~CrySimpleThread() - { - if (IsStarted()) - { - if (gEnv && gEnv->pLog) - { - gEnv->pLog->LogError("Runaway thread %p '%s'", m_thread, m_name.c_str()); - } - } - - if (m_bCreatedThread) - { - Cancel(); - WaitForThread(); - } - } - - virtual void Run() - { - // This Run() implementation supports the void StartFunction() method. - // However, code using this class (or derived classes) should eventually - // be refactored to use one of the other Start() methods. This code will - // be removed some day and the default implementation of Run() will be - // empty. - if (m_ThreadFunction.m_ThreadFunction != NULL) - { - m_ThreadFunction.m_ThreadFunction(m_ThreadFunction.m_ThreadParameter); - } - } - - // Cancel the running thread. - // - // If the thread class is implemented as a derived class of CrySimpleThread, - // then the derived class should provide an appropriate implementation for - // this method. Calling the base class implementation is _not_ required. - // - // If the thread was started by specifying a Runnable (template argument), - // then the Cancel() call is passed on to the specified runnable. - // - // If the thread was started using the StartFunction() method, then the - // caller must find other means to inform the thread about the cancellation - // request. - virtual void Cancel() - { - if (IsStarted() && m_Runnable != NULL) - { - m_Runnable->Cancel(); - } - } - - virtual void Start(Runnable& runnable, [[maybe_unused]] unsigned cpuMask = 0, const char* = NULL, int32 = 0) - { - if (m_bCreatedThread) - { - // Don't start thread more than once! - return; - } - m_Runnable = &runnable; - m_bCreatedThread = true; - StartThread(RunRunnable, this); - } - - virtual void Start([[maybe_unused]] unsigned cpuMask = 0, const char* = NULL, int32 = 0, int32 = 0) - { - if (m_bCreatedThread) - { - // Don't start thread more than once! - return; - } - m_bCreatedThread = true; - StartThread(RunThis, this); - } - - void StartFunction( - ThreadFunction threadFunction, - void* threadParameter = NULL - ) - { - m_ThreadFunction.m_ThreadFunction = threadFunction; - m_ThreadFunction.m_ThreadParameter = threadParameter; - Start(); - } - - static CrySimpleThread* Self() - { - return reinterpret_cast*>(m_Self); - } - - void Exit() - { - assert(!"implemented"); - } - - void Stop() - { - m_bIsStarted = false; - } - - bool IsStarted() const { return m_bIsStarted; } - bool IsRunning() const { return m_bIsRunning; } -}; From 6a2d5cd370ae0e35c47188531a3a7eb6d2197e1f Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 12:22:03 -0700 Subject: [PATCH 007/101] [redcode/crythread-2nd-pass] removed Cry-TLS macros from platform.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/platform.h | 54 -------------------------------- 1 file changed, 54 deletions(-) diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 6aad8dd043..851da316e0 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -277,18 +277,6 @@ #define PRINTF_EMPTY_FORMAT "" #endif -#if defined(IOS) -#define USE_PTHREAD_TLS -#endif - -// Storage class modifier for thread local storage. -// THEADLOCAL should NOT be defined to empty because that creates some -// really hard to find issues. -#if !defined(USE_PTHREAD_TLS) -# define THREADLOCAL AZ_TRAIT_COMPILER_THREAD_LOCAL -#endif //!defined(USE_PTHREAD_TLS) - - ////////////////////////////////////////////////////////////////////////// // define Read Write Barrier macro needed for lockless programming @@ -735,48 +723,6 @@ enum ETriState #define _MS_ALIGN(num) AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") #endif -#if defined(WIN32) || defined(WIN64) -extern "C" { -__declspec(dllimport) unsigned long __stdcall TlsAlloc(); -__declspec(dllimport) void* __stdcall TlsGetValue(unsigned long dwTlsIndex); -__declspec(dllimport) int __stdcall TlsSetValue(unsigned long dwTlsIndex, void* lpTlsValue); -} - - #define TLS_DECLARE(type, var) extern int var##idx; - #define TLS_DEFINE(type, var) \ - int var##idx; \ - struct Init##var { \ - Init##var() { var##idx = TlsAlloc(); } \ - }; \ - Init##var g_init##var; - #define TLS_DEFINE_DEFAULT_VALUE(type, var, value) \ - int var##idx; \ - struct Init##var { \ - Init##var() { var##idx = TlsAlloc(); TlsSetValue(var##idx, reinterpret_cast(value)); } \ - }; \ - Init##var g_init##var; - #define TLS_GET(type, var) (type)TlsGetValue(var##idx) - #define TLS_SET(var, val) TlsSetValue(var##idx, reinterpret_cast(val)) -#elif defined(USE_PTHREAD_TLS) - #define TLS_DECLARE(_TYPE, _VAR) extern SCryPthreadTLS<_TYPE> _VAR##TLSKey; - #define TLS_DEFINE(_TYPE, _VAR) SCryPthreadTLS<_TYPE> _VAR##TLSKey; - #define TLS_DEFINE_DEFAULT_VALUE(_TYPE, _VAR, _DEFAULT) SCryPthreadTLS<_TYPE> _VAR##TLSKey = _DEFAULT; - #define TLS_GET(_TYPE, _VAR) _VAR##TLSKey.Get() - #define TLS_SET(_VAR, _VALUE) _VAR##TLSKey.Set(_VALUE) -#elif defined(THREADLOCAL) - #define TLS_DECLARE(type, var) extern THREADLOCAL type var; -#if defined(LINUX) || defined(MAC) - #define TLS_DEFINE(type, var) THREADLOCAL type var = 0; -#else - #define TLS_DEFINE(type, var) THREADLOCAL type var; -#endif // defined(LINUX) || defined(MAC) - #define TLS_DEFINE_DEFAULT_VALUE(type, var, value) THREADLOCAL type var = value; - #define TLS_GET(type, var) (var) - #define TLS_SET(var, val) (var = (val)) -#else // defined(THREADLOCAL) - #error "There's no support for thread local storage" -#endif - #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_13 #include AZ_RESTRICTED_FILE(platform_h) From 2e2bbe80b118e5481a8be0b275ec039cf4ee3a7e Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 13:19:41 -0700 Subject: [PATCH 008/101] [redcode/crythread-2nd-pass] removed CryEvent types Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../Legacy/CryCommon/CryThreadImpl_pthreads.h | 47 ------------------- Code/Legacy/CryCommon/CryThreadImpl_windows.h | 39 --------------- Code/Legacy/CryCommon/CryThread_pthreads.h | 34 -------------- Code/Legacy/CryCommon/CryThread_windows.h | 30 ------------ 4 files changed, 150 deletions(-) diff --git a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h index 358d8f962f..38838991a8 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h @@ -14,53 +14,6 @@ #include "CryThread_pthreads.h" - -////////////////////////////////////////////////////////////////////////// -// CryEvent(Timed) implementation -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -void CryEventTimed::Reset() -{ - m_lockNotify.Lock(); - m_flag = false; - m_lockNotify.Unlock(); -} - -////////////////////////////////////////////////////////////////////////// -void CryEventTimed::Set() -{ - m_lockNotify.Lock(); - m_flag = true; - m_cond.Notify(); - m_lockNotify.Unlock(); -} - -////////////////////////////////////////////////////////////////////////// -void CryEventTimed::Wait() -{ - m_lockNotify.Lock(); - if (!m_flag) - { - m_cond.Wait(m_lockNotify); - } - m_flag = false; - m_lockNotify.Unlock(); -} - -////////////////////////////////////////////////////////////////////////// -bool CryEventTimed::Wait(const uint32 timeoutMillis) -{ - bool bResult = true; - m_lockNotify.Lock(); - if (!m_flag) - { - bResult = m_cond.TimedWait(m_lockNotify, timeoutMillis); - } - m_flag = false; - m_lockNotify.Unlock(); - return bResult; -} - /////////////////////////////////////////////////////////////////////////////// // CryCriticalSection implementation /////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h index 9d636fd41a..d81f3b0689 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_windows.h @@ -12,45 +12,6 @@ #include #include // for CreateSemaphore -////////////////////////////////////////////////////////////////////////// -CryEvent::CryEvent() -{ - m_handle = (void*)CreateEvent(NULL, FALSE, FALSE, NULL); -} - -////////////////////////////////////////////////////////////////////////// -CryEvent::~CryEvent() -{ - CloseHandle(m_handle); -} - -////////////////////////////////////////////////////////////////////////// -void CryEvent::Reset() -{ - ResetEvent(m_handle); -} - -////////////////////////////////////////////////////////////////////////// -void CryEvent::Set() -{ - SetEvent(m_handle); -} - -////////////////////////////////////////////////////////////////////////// -void CryEvent::Wait() const -{ - WaitForSingleObject(m_handle, INFINITE); -} - -////////////////////////////////////////////////////////////////////////// -bool CryEvent::Wait(const uint32 timeoutMillis) const -{ - if (WaitForSingleObject(m_handle, timeoutMillis) == WAIT_TIMEOUT) - { - return false; - } - return true; -} ////////////////////////////////////////////////////////////////////////// // CryLock_WinMutex diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h index 9102c12c38..8dd4bfba6c 100644 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ b/Code/Legacy/CryCommon/CryThread_pthreads.h @@ -619,38 +619,4 @@ struct SCryPthreadTLS { }; - -////////////////////////////////////////////////////////////////////////// -// CryEvent(Timed) represent a synchronization event -////////////////////////////////////////////////////////////////////////// -class CryEventTimed -{ -public: - ILINE CryEventTimed(){m_flag = false; } - ILINE ~CryEventTimed(){} - - // Reset the event to the unsignalled state. - void Reset(); - // Set the event to the signalled state. - void Set(); - // Access a HANDLE to wait on. - void* GetHandle() const { return NULL; }; - // Wait indefinitely for the object to become signalled. - void Wait(); - // Wait, with a time limit, for the object to become signalled. - bool Wait(const uint32 timeoutMillis); - -private: - // Lock for synchronization of notifications. - CryCriticalSection m_lockNotify; -#if defined(LINUX) || defined(APPLE) - CryConditionVariableT< CryLockT > m_cond; -#else - CryConditionVariable m_cond; -#endif - volatile bool m_flag; -}; - -typedef CryEventTimed CryEvent; - #include "MemoryAccess.h" diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h index 87147549f7..68908ab34a 100644 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ b/Code/Legacy/CryCommon/CryThread_windows.h @@ -17,36 +17,6 @@ #define CRYTHREAD_WINDOWS_H_SECTION_2 2 #endif -////////////////////////////////////////////////////////////////////////// -// CryEvent represent a synchronization event -////////////////////////////////////////////////////////////////////////// -class CryEvent -{ -public: - CryEvent(); - ~CryEvent(); - - // Reset the event to the unsignalled state. - void Reset(); - // Set the event to the signalled state. - void Set(); - // Access a HANDLE to wait on. - void* GetHandle() const { return m_handle; }; - // Wait indefinitely for the object to become signalled. - void Wait() const; - // Wait, with a time limit, for the object to become signalled. - bool Wait(const uint32 timeoutMillis) const; - -private: - CryEvent(const CryEvent&); - CryEvent& operator = (const CryEvent&); - -private: - void* m_handle; -}; - -typedef CryEvent CryEventTimed; - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// From f47b8b534ba7abb2b24cd6cf29bb0a025c8ce2c3 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 14:03:42 -0700 Subject: [PATCH 009/101] [redcode/crythread-2nd-pass] removed unused CryConditionVariable in CryEdit Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index cd1dd4fe47..5a5b17f799 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -892,7 +892,6 @@ CCrySingleDocTemplate::Confidence CCrySingleDocTemplate::MatchDocType(LPCTSTR lp namespace { CryMutex g_splashScreenStateLock; - CryConditionVariable g_splashScreenStateChange; enum ESplashScreenState { eSplashScreenState_Init, eSplashScreenState_Started, eSplashScreenState_Destroy @@ -932,7 +931,6 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app) g_splashScreenState = eSplashScreenState_Started; g_splashScreenStateLock.Unlock(); - g_splashScreenStateChange.Notify(); splashScreen->show(); // Make sure the initial paint of the splash screen occurs so we dont get stuck with a blank window From 2408f7dc37acdb302026743d08ce13238e5ec3a8 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 14:49:29 -0700 Subject: [PATCH 010/101] [redcode/crythread-2nd-pass] removed more unused code from CryThread Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/CryThreadImpl_windows.h | 177 -------- Code/Legacy/CryCommon/CryThread_pthreads.h | 423 ------------------ Code/Legacy/CryCommon/CryThread_windows.h | 56 --- 3 files changed, 656 deletions(-) diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h index d81f3b0689..9157bde9bc 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_windows.h @@ -76,180 +76,3 @@ bool CryLock_CritSection::TryLock() { return TryEnterCriticalSection((CRITICAL_SECTION*)&m_cs) != FALSE; } - -////////////////////////////////////////////////////////////////////////// -// most of this is taken from http://www.cs.wustl.edu/~schmidt/win32-cv-1.html -////////////////////////////////////////////////////////////////////////// -CryConditionVariable::CryConditionVariable() -{ - m_waitersCount = 0; - m_wasBroadcast = 0; - m_sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); - InitializeCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL); -} - -////////////////////////////////////////////////////////////////////////// -CryConditionVariable::~CryConditionVariable() -{ - CloseHandle(m_sema); - DeleteCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - CloseHandle(m_waitersDone); -} - -////////////////////////////////////////////////////////////////////////// -void CryConditionVariable::Wait(LockType& lock) -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersCount++; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - - SignalObjectAndWait(lock._get_win32_handle(), m_sema, INFINITE, FALSE); - - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersCount--; - bool lastWaiter = m_wasBroadcast && m_waitersCount == 0; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - - if (lastWaiter) - { - SignalObjectAndWait(m_waitersDone, lock._get_win32_handle(), INFINITE, FALSE); - } - else - { - WaitForSingleObject(lock._get_win32_handle(), INFINITE); - } -} - -////////////////////////////////////////////////////////////////////////// -bool CryConditionVariable::TimedWait(LockType& lock, uint32 millis) -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersCount++; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - - bool ok = true; - if (WAIT_TIMEOUT == SignalObjectAndWait(lock._get_win32_handle(), m_sema, millis, FALSE)) - { - ok = false; - } - - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersCount--; - bool lastWaiter = m_wasBroadcast && m_waitersCount == 0; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - - if (lastWaiter) - { - SignalObjectAndWait(m_waitersDone, lock._get_win32_handle(), INFINITE, FALSE); - } - else - { - WaitForSingleObject(lock._get_win32_handle(), INFINITE); - } - - return ok; -} - -////////////////////////////////////////////////////////////////////////// -void CryConditionVariable::NotifySingle() -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - bool haveWaiters = m_waitersCount > 0; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - if (haveWaiters) - { - ReleaseSemaphore(m_sema, 1, 0); - } -} - -////////////////////////////////////////////////////////////////////////// -void CryConditionVariable::Notify() -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - bool haveWaiters = false; - if (m_waitersCount > 0) - { - m_wasBroadcast = 1; - haveWaiters = true; - } - if (haveWaiters) - { - ReleaseSemaphore(m_sema, m_waitersCount, 0); - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - WaitForSingleObject(m_waitersDone, INFINITE); - m_wasBroadcast = 0; - } - else - { - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - } -} - -////////////////////////////////////////////////////////////////////////// -CrySemaphore::CrySemaphore(int nMaximumCount, int nInitialCount) -{ - m_Semaphore = (void*)CreateSemaphore(NULL, nInitialCount, nMaximumCount, NULL); -} - -////////////////////////////////////////////////////////////////////////// -CrySemaphore::~CrySemaphore() -{ - CloseHandle((HANDLE)m_Semaphore); -} - -////////////////////////////////////////////////////////////////////////// -void CrySemaphore::Acquire() -{ - WaitForSingleObject((HANDLE)m_Semaphore, INFINITE); -} - -////////////////////////////////////////////////////////////////////////// -void CrySemaphore::Release() -{ - ReleaseSemaphore((HANDLE)m_Semaphore, 1, NULL); -} - -////////////////////////////////////////////////////////////////////////// -CryFastSemaphore::CryFastSemaphore(int nMaximumCount, int nInitialCount) - : m_Semaphore(nMaximumCount) - , m_nCounter(nInitialCount) -{ -} - -////////////////////////////////////////////////////////////////////////// -CryFastSemaphore::~CryFastSemaphore() -{ -} - -////////////////////////////////////////////////////////////////////////// -void CryFastSemaphore::Acquire() -{ - int nCount = ~0; - do - { - nCount = *const_cast(&m_nCounter); - } while (CryInterlockedCompareExchange(alias_cast(&m_nCounter), nCount - 1, nCount) != nCount); - - // if the count would have been 0 or below, go to kernel semaphore - if ((nCount - 1) < 0) - { - m_Semaphore.Acquire(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CryFastSemaphore::Release() -{ - int nCount = ~0; - do - { - nCount = *const_cast(&m_nCounter); - } while (CryInterlockedCompareExchange(alias_cast(&m_nCounter), nCount + 1, nCount) != nCount); - - // wake up kernel semaphore if we have waiter - if (nCount < 0) - { - m_Semaphore.Release(); - } -} diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h index 8dd4bfba6c..9e04784f3f 100644 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ b/Code/Legacy/CryCommon/CryThread_pthreads.h @@ -48,52 +48,12 @@ #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #endif -#if !defined(RegisterThreadName) - #define RegisterThreadName(id, name) - #define UnRegisterThreadName(id) -#endif - #if defined(APPLE) || defined(ANDROID) // PTHREAD_MUTEX_FAST_NP is only defined by Pthreads-w32, thus not on MAC #define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_NORMAL #endif -// Define LARGE_THREAD_STACK to use larger than normal per-thread stack -#if defined(_DEBUG) && (defined(MAC) || defined(LINUX) || defined(AZ_PLATFORM_IOS)) -#define LARGE_THREAD_STACK -#endif - -#if defined(LINUX) -#undef RegisterThreadName -ILINE void RegisterThreadName(pthread_t id, const char* name) -{ - if ((!name) || (!id)) - { - return; - } - int ret; - // pthread names on linux are limited to 16 char - if (strlen(name) >= 16) - { - char thread_name[16]; - memcpy(thread_name, name, 15); - thread_name[15] = 0; - ret = pthread_setname_np(id, thread_name); - } - else - { - ret = pthread_setname_np(id, name); - } - if (ret != 0) - { - CryLog("Failed to set thread name for %" PRI_THREADID ", name: %s", id, name); - } -} -#endif - #if !defined _CRYTHREAD_HAVE_LOCK -template -class _PthreadCond; template class _PthreadLockBase; @@ -130,8 +90,6 @@ template class _PthreadLock : public _PthreadLockBase { - friend class _PthreadCond; - //#if defined(_DEBUG) public: //#endif @@ -218,9 +176,6 @@ public: #if !defined(LINUX) && !defined(APPLE) #define CRYTHREAD_PTHREADS_H_TRAIT_DEFINE_CRYMUTEX 1 #endif -#if !defined(LINUX) && !defined(APPLE) -#define CRYTHREAD_PTHREADS_H_TRAIT_SET_THREAD_NAME 1 -#endif #endif #if CRYTHREAD_PTHREADS_H_TRAIT_DEFINE_CRYMUTEX @@ -237,386 +192,8 @@ class CryMutex #endif #endif // CRYTHREAD_PTHREADS_TRAIT_DEFINE_CRYMUTEX -template -class _PthreadCond -{ - pthread_cond_t m_Cond; - -public: - _PthreadCond() { pthread_cond_init(&m_Cond, NULL); } - ~_PthreadCond() { pthread_cond_destroy(&m_Cond); } - void Notify() { pthread_cond_broadcast(&m_Cond); } - void NotifySingle() { pthread_cond_signal(&m_Cond); } - void Wait(LockClass& Lock) { pthread_cond_wait(&m_Cond, &Lock.m_Lock); } - bool TimedWait(LockClass& Lock, uint32 milliseconds) - { - struct timeval now; - struct timespec timeout; - int err; - - gettimeofday(&now, NULL); - while (true) - { - timeout.tv_sec = now.tv_sec + milliseconds / 1000; - uint64 nsec = (uint64)now.tv_usec * 1000 + (uint64)milliseconds * 1000000; - if (nsec >= 1000000000) - { - timeout.tv_sec += (long)(nsec / 1000000000); - nsec %= 1000000000; - } - timeout.tv_nsec = (long)nsec; -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_PTHREADCOND - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - err = pthread_cond_timedwait(&m_Cond, &Lock.m_Lock, &timeout); - if (err == EINTR) - { - // Interrupted by a signal. - continue; - } - else if (err == ETIMEDOUT) - { - return false; - } -#endif - else - { - assert(err == 0); - } - break; - } - return true; - } - - // Get the POSIX pthread_cont_t. - // Warning: - // This method will not be available in the Win32 port of CryThread. - pthread_cond_t& Get_pthread_cond_t() { return m_Cond; } -}; - -#if AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS -template -class CryConditionVariableT - : public _PthreadCond -{ -}; - -#if defined CRYLOCK_HAVE_FASTTLOCK -template<> -class CryConditionVariableT< CryLockT > - : public _PthreadCond< CryLockT > -{ - typedef CryLockT LockClass; - CryConditionVariableT(const CryConditionVariableT&); - CryConditionVariableT& operator = (const CryConditionVariableT&); - -public: - CryConditionVariableT() { } -}; -#endif // CRYLOCK_HAVE_FASTLOCK - -template<> -class CryConditionVariableT< CryLockT > - : public _PthreadCond< CryLockT > -{ - typedef CryLockT LockClass; - CryConditionVariableT(const CryConditionVariableT&); - CryConditionVariableT& operator = (const CryConditionVariableT&); - -public: - CryConditionVariableT() { } -}; - -#if !defined(_CRYTHREAD_CONDLOCK_GLITCH) -typedef CryConditionVariableT< CryLockT > CryConditionVariable; -#else -typedef CryConditionVariableT< CryLockT > CryConditionVariable; -#endif - #define _CRYTHREAD_HAVE_LOCK 1 -#else // LINUX MAC - -#if defined CRYLOCK_HAVE_FASTLOCK -template<> -class CryConditionVariable - : public _PthreadCond< CryLockT > -{ - typedef CryLockT LockClass; - CryConditionVariable(const CryConditionVariable&); - CryConditionVariable& operator = (const CryConditionVariable&); - -public: - CryConditionVariable() { } -}; -#endif // CRYLOCK_HAVE_FASTLOCK - -template<> -class CryConditionVariable - : public _PthreadCond< CryLockT > -{ - typedef CryLockT LockClass; - CryConditionVariable(const CryConditionVariable&); - CryConditionVariable& operator = (const CryConditionVariable&); - -public: - CryConditionVariable() { } -}; - -#define _CRYTHREAD_HAVE_LOCK 1 - -#endif // LINUX MAC #endif // !defined _CRYTHREAD_HAVE_LOCK -////////////////////////////////////////////////////////////////////////// -// Platform independet wrapper for a counting semaphore -class CrySemaphore -{ -public: - CrySemaphore(int nMaximumCount, int nInitialCount = 0); - ~CrySemaphore(); - - void Acquire(); - void Release(); - -private: -#if defined(APPLE) - // Apple only supports named semaphores so have to use sem_open/unlink/sem_close instead - // of sem_open/sem_destroy, passing in this array for the name. - char m_semaphoreName[L_tmpnam]; -#endif - sem_t* m_Semaphore; -}; - -////////////////////////////////////////////////////////////////////////// -inline CrySemaphore::CrySemaphore(int nMaximumCount, int nInitialCount) -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_CONSTRUCT - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(APPLE) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - tmpnam(m_semaphoreName); -# pragma clang diagnostic pop - m_Semaphore = sem_open(m_semaphoreName, O_CREAT | O_EXCL, 0644, nInitialCount); -#else - m_Semaphore = new sem_t; - sem_init(m_Semaphore, 0, nInitialCount); -#endif -} - -////////////////////////////////////////////////////////////////////////// -inline CrySemaphore::~CrySemaphore() -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_DESTROY - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(APPLE) - sem_close(m_Semaphore); - sem_unlink(m_semaphoreName); -#else - sem_destroy(m_Semaphore); - delete m_Semaphore; -#endif -} - -////////////////////////////////////////////////////////////////////////// -inline void CrySemaphore::Acquire() -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_ACQUIRE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - while (sem_wait(m_Semaphore) != 0 && errno == EINTR) - { - ; - } -#endif -} - -////////////////////////////////////////////////////////////////////////// -inline void CrySemaphore::Release() -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_RELEASE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - sem_post(m_Semaphore); -#endif -} - -////////////////////////////////////////////////////////////////////////// -// Platform independet wrapper for a counting semaphore -// except that this version uses C-A-S only until a blocking call is needed -// -> No kernel call if there are object in the semaphore - -class CryFastSemaphore -{ -public: - CryFastSemaphore(int nMaximumCount, int nInitialCount = 0); - ~CryFastSemaphore(); - void Acquire(); - void Release(); - -private: - CrySemaphore m_Semaphore; - volatile int32 m_nCounter; -}; - -////////////////////////////////////////////////////////////////////////// -inline CryFastSemaphore::CryFastSemaphore(int nMaximumCount, int nInitialCount) - : m_Semaphore(nMaximumCount) - , m_nCounter(nInitialCount) -{ -} - -////////////////////////////////////////////////////////////////////////// -inline CryFastSemaphore::~CryFastSemaphore() -{ -} - -///////////////////////////////////////////////////////////////////////// -inline void CryFastSemaphore::Acquire() -{ - int nCount = ~0; - do - { - nCount = *const_cast(&m_nCounter); - } while (CryInterlockedCompareExchange(alias_cast(&m_nCounter), nCount - 1, nCount) != nCount); - - // if the count would have been 0 or below, go to kernel semaphore - if ((nCount - 1) < 0) - { - m_Semaphore.Acquire(); - } -} - -////////////////////////////////////////////////////////////////////////// -inline void CryFastSemaphore::Release() -{ - int nCount = ~0; - do - { - nCount = *const_cast(&m_nCounter); - } while (CryInterlockedCompareExchange(alias_cast(&m_nCounter), nCount + 1, nCount) != nCount); - - // wake up kernel semaphore if we have waiter - if (nCount < 0) - { - m_Semaphore.Release(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Provide TLS implementation using pthreads for those platforms without __thread -//////////////////////////////////////////////////////////////////////////////// - -struct SCryPthreadTLSBase -{ - SCryPthreadTLSBase(void (*pDestructor)(void*)) - { - pthread_key_create(&m_kKey, pDestructor); - } - - ~SCryPthreadTLSBase() - { - pthread_key_delete(m_kKey); - } - - void* GetSpecific() - { - return pthread_getspecific(m_kKey); - } - - void SetSpecific(const void* pValue) - { - pthread_setspecific(m_kKey, pValue); - } - - pthread_key_t m_kKey; -}; - -template -struct SCryPthreadTLSImpl{}; - -template -struct SCryPthreadTLSImpl - : private SCryPthreadTLSBase -{ - SCryPthreadTLSImpl() - : SCryPthreadTLSBase(NULL) - { - } - - T Get() - { - void* pSpecific(GetSpecific()); - return *reinterpret_cast(&pSpecific); - } - - void Set(const T& kValue) - { - SetSpecific(*reinterpret_cast(&kValue)); - } -}; - -template -struct SCryPthreadTLSImpl - : private SCryPthreadTLSBase -{ - SCryPthreadTLSImpl() - : SCryPthreadTLSBase(&Destroy) - { - } - - T* GetPtr() - { - T* pPtr(static_cast(GetSpecific())); - if (pPtr == NULL) - { - pPtr = new T(); - SetSpecific(pPtr); - } - return pPtr; - } - - static void Destroy(void* pPointer) - { - delete static_cast(pPointer); - } - - const T& Get() - { - return *GetPtr(); - } - - void Set(const T& kValue) - { - *GetPtr() = kValue; - } -}; - -template -struct SCryPthreadTLS - : SCryPthreadTLSImpl -{ -}; - #include "MemoryAccess.h" diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h index 68908ab34a..5f83aa48e0 100644 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ b/Code/Legacy/CryCommon/CryThread_windows.h @@ -93,59 +93,3 @@ class CryMutex { }; #define _CRYTHREAD_CONDLOCK_GLITCH 1 - -////////////////////////////////////////////////////////////////////////// -class CryConditionVariable -{ -public: - typedef CryMutex LockType; - - CryConditionVariable(); - ~CryConditionVariable(); - void Wait(LockType& lock); - bool TimedWait(LockType& lock, uint32 millis); - void NotifySingle(); - void Notify(); - -private: - CryConditionVariable(const CryConditionVariable&); - CryConditionVariable& operator = (const CryConditionVariable&); - -private: - int m_waitersCount; - CRY_CRITICAL_SECTION m_waitersCountLock; - void* m_sema; - void* m_waitersDone; - size_t m_wasBroadcast; -}; - -////////////////////////////////////////////////////////////////////////// -// Platform independet wrapper for a counting semaphore -class CrySemaphore -{ -public: - CrySemaphore(int nMaximumCount, int nInitialCount = 0); - ~CrySemaphore(); - void Acquire(); - void Release(); - -private: - void* m_Semaphore; -}; - -////////////////////////////////////////////////////////////////////////// -// Platform independet wrapper for a counting semaphore -// except that this version uses C-A-S only until a blocking call is needed -// -> No kernel call if there are object in the semaphore -class CryFastSemaphore -{ -public: - CryFastSemaphore(int nMaximumCount, int nInitialCount = 0); - ~CryFastSemaphore(); - void Acquire(); - void Release(); - -private: - CrySemaphore m_Semaphore; - volatile int32 m_nCounter; -}; From f85e8124a9ee10e2e337877d2f67e9033fa8eff4 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Mon, 9 Aug 2021 16:17:23 -0700 Subject: [PATCH 011/101] Fixes and cleanup for recent correction changes Signed-off-by: kberg-amzn --- .../Serialization/StringifySerializer.cpp | 26 -------- .../Serialization/StringifySerializer.h | 12 +--- .../LocalPredictionPlayerInputComponent.h | 5 -- .../Multiplayer/Components/NetBindComponent.h | 4 ++ .../Components/NetworkTransformComponent.h | 2 + .../LocalPredictionPlayerInputComponent.cpp | 66 ++----------------- .../Source/Components/NetBindComponent.cpp | 10 +++ .../Components/NetworkTransformComponent.cpp | 14 ++++ 8 files changed, 36 insertions(+), 103 deletions(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp index df018cb6ce..4f31dd0f33 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp @@ -10,19 +10,6 @@ namespace AzNetworking { - StringifySerializer::StringifySerializer(char delimeter, bool outputFieldNames, const AZStd::string& seperator) - : m_delimeter(delimeter) - , m_outputFieldNames(outputFieldNames) - , m_separator(seperator) - { - ; - } - - const AZStd::string& StringifySerializer::GetString() const - { - return m_string; - } - const StringifySerializer::ValueMap& StringifySerializer::GetValueMap() const { return m_valueMap; @@ -138,21 +125,8 @@ namespace AzNetworking bool StringifySerializer::ProcessData(const char* name, const T& value) { const AZStd::string keyString = m_prefix + name; - - if (!m_string.empty()) - { - // Only add delimeters after we have processed at least one element - m_string += m_delimeter; - } - - if (m_outputFieldNames) - { - m_string += keyString; - } - AZ::CVarFixedString valueString = AZ::ConsoleTypeHelpers::ValueToString(value); m_valueMap[keyString] = valueString.c_str(); - return true; } } diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h index 379b5198c7..3ea0bfa412 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h @@ -22,10 +22,7 @@ namespace AzNetworking using ValueMap = AZStd::map; - StringifySerializer(char delimeter = ' ', bool outputFieldNames = true, const AZStd::string& seperator = "="); - - //! After serializing objects, get the serialized values as a single string. - const AZStd::string& GetString() const; + StringifySerializer() = default; //! After serializing objects, get the serialized values as a map of key/value pairs. const ValueMap& GetValueMap() const; @@ -60,15 +57,8 @@ namespace AzNetworking template bool ProcessData(const char* name, const T& value); - private: - - char m_delimeter; - bool m_outputFieldNames = true; - ValueMap m_valueMap; - AZStd::string m_string; AZStd::string m_prefix; - AZStd::string m_separator; AZStd::deque m_prefixSizeStack; }; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h index 4e5d7f2d49..f26f043b85 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h @@ -14,8 +14,6 @@ namespace Multiplayer { - using CorrectionEvent = AZ::Event<>; - class LocalPredictionPlayerInputComponent : public LocalPredictionPlayerInputComponentBase { @@ -65,8 +63,6 @@ namespace Multiplayer ClientInputId GetLastInputId() const; HostFrameId GetInputFrameId(const NetworkInput& input) const; - void CorrectionEventAddHandle(CorrectionEvent::Handler& handler); - private: void OnMigrateStart(ClientInputId migratedInputId); @@ -86,7 +82,6 @@ namespace Multiplayer AZ::ScheduledEvent m_autonomousUpdateEvent; // Drives autonomous input collection AZ::ScheduledEvent m_updateBankedTimeEvent; // Drives authority bank time updates - CorrectionEvent m_correctionEvent; EntityMigrationStartEvent::Handler m_migrateStartHandler; EntityMigrationEndEvent::Handler m_migrateEndHandler; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index c050495f1f..65bac09726 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -36,6 +36,7 @@ namespace Multiplayer using EntityMigrationEndEvent = AZ::Event<>; using EntityServerMigrationEvent = AZ::Event; using EntityPreRenderEvent = AZ::Event; + using EntityCorrectionEvent = AZ::Event<>; //! @class NetBindComponent //! @brief Component that provides net-binding to a networked entity. @@ -118,6 +119,7 @@ namespace Multiplayer void NotifyMigrationEnd(); void NotifyServerMigration(HostId hostId, AzNetworking::ConnectionId connectionId); void NotifyPreRender(float deltaTime, float blendFactor); + void NotifyCorrection(); void AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler); void AddEntityDirtiedEventHandler(EntityDirtiedEvent::Handler& eventHandler); @@ -126,6 +128,7 @@ namespace Multiplayer void AddEntityMigrationEndEventHandler(EntityMigrationEndEvent::Handler& eventHandler); void AddEntityServerMigrationEventHandler(EntityServerMigrationEvent::Handler& eventHandler); void AddEntityPreRenderEventHandler(EntityPreRenderEvent::Handler& eventHandler); + void AddEntityCorrectionEventHandler(EntityCorrectionEvent::Handler& handler); bool SerializeEntityCorrection(AzNetworking::ISerializer& serializer); @@ -175,6 +178,7 @@ namespace Multiplayer EntityMigrationEndEvent m_entityMigrationEndEvent; EntityServerMigrationEvent m_entityServerMigrationEvent; EntityPreRenderEvent m_entityPreRenderEvent; + EntityCorrectionEvent m_entityCorrectionEvent; AZ::Event<> m_onRemove; RpcSendEvent::Handler m_handleLocalServerRpcMessageEventHandle; AZ::Event<>::Handler m_handleMarkedDirty; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h index 16aa8157aa..914aeaadd3 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h @@ -30,6 +30,7 @@ namespace Multiplayer private: void OnPreRender(float deltaTime, float blendFactor); + void OnCorrection(); void OnRotationChangedEvent(const AZ::Quaternion& rotation); void OnTranslationChangedEvent(const AZ::Vector3& translation); @@ -47,6 +48,7 @@ namespace Multiplayer AZ::Event::Handler m_resetCountEventHandler; EntityPreRenderEvent::Handler m_entityPreRenderEventHandler; + EntityCorrectionEvent::Handler m_entityCorrectionEventHandler; Multiplayer::HostFrameId m_targetHostFrameId = HostFrameId(0); }; diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 4185b01798..5b6b93a3aa 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -32,21 +32,6 @@ namespace Multiplayer AZ_CVAR(AZ::TimeMs, sv_MinCorrectionTimeMs, AZ::TimeMs{ 100 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum time to wait between sending out corrections in order to avoid flooding corrections on high-latency connections"); AZ_CVAR(AZ::TimeMs, sv_InputUpdateTimeMs, AZ::TimeMs{ 5 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum time between component updates"); - // Debug helper functions - AZStd::string GetInputString(NetworkInput& input) - { - AzNetworking::StringifySerializer serializer(',', false); - input.Serialize(serializer); - return serializer.GetString(); - } - - AZStd::string GetCorrectionDataString(NetBindComponent* netBindComponent) - { - AzNetworking::StringifySerializer serializer(',', false); - netBindComponent->SerializeEntityCorrection(serializer); - return serializer.GetString(); - } - void PrintCorrectionDifferences(const AzNetworking::StringifySerializer& client, const AzNetworking::StringifySerializer& server) { const auto& clientMap = client.GetValueMap(); @@ -289,14 +274,7 @@ namespace Multiplayer ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, clientInputRateSec); - AZLOG - ( - NET_Prediction, - "Migrated InputId=%d - i=[%s] o=[%s]", - aznumeric_cast(input.GetClientInputId()), - GetInputString(input).c_str(), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); + AZLOG(NET_Prediction, "Migrated InputId=%d", aznumeric_cast(input.GetClientInputId())); // Don't bother checking for corrections here, the next regular input will trigger any corrections if necessary // Also don't bother with any cheat detection here, because the input array is limited in size and at most and can only be sent once @@ -329,7 +307,7 @@ namespace Multiplayer // Apply the correction AzNetworking::TrackChangedSerializer serializer(correction.GetBuffer(), correction.GetSize()); GetNetBindComponent()->SerializeEntityCorrection(serializer); - m_correctionEvent.Signal(); + GetNetBindComponent()->NotifyCorrection(); #ifndef AZ_RELEASE_BUILD if (cl_EnableDesyncDebugging) @@ -350,14 +328,6 @@ namespace Multiplayer } #endif - AZLOG - ( - NET_Prediction, - "Corrected InputId=%d - o=[%s]", - aznumeric_cast(m_lastCorrectionInputId), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); - const uint32_t inputHistorySize = m_inputHistory.Size(); const uint32_t historicalDelta = aznumeric_cast(m_clientInputId - inputId); // Do not replay the move we just corrected, that was already processed by the server @@ -372,14 +342,7 @@ namespace Multiplayer ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ReprocessInput(input, clientInputRateSec); - AZLOG - ( - NET_Prediction, - "Replayed InputId=%d - i=[%s] o=[%s]", - aznumeric_cast(input.GetClientInputId()), - GetInputString(input).c_str(), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); + AZLOG(NET_Prediction, "Replayed InputId=%d", aznumeric_cast(input.GetClientInputId())); } } @@ -402,11 +365,6 @@ namespace Multiplayer return (input.GetHostFrameId() == InvalidHostFrameId) ? m_serverMigrateFrameId : input.GetHostFrameId(); } - void LocalPredictionPlayerInputComponentController::CorrectionEventAddHandle(CorrectionEvent::Handler& handler) - { - handler.Connect(m_correctionEvent); - } - void LocalPredictionPlayerInputComponentController::OnMigrateStart(ClientInputId migratedInputId) { m_lastMigratedInputId = migratedInputId; @@ -480,14 +438,7 @@ namespace Multiplayer // Process the input for this frame GetNetBindComponent()->ProcessInput(input, inputRate); - AZLOG - ( - NET_Prediction, - "Processed InutId=%d - i=[%s] o=[%s]", - aznumeric_cast(m_clientInputId), - GetInputString(input).c_str(), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); + AZLOG(NET_Prediction, "Processed InputId=%d", aznumeric_cast(m_clientInputId)); // Generate a hash based on the current client predicted states AzNetworking::HashSerializer hashSerializer; @@ -553,14 +504,7 @@ namespace Multiplayer GetNetBindComponent()->ProcessInput(input, inputRate); } - AZLOG - ( - NET_Prediction, - "Forced InputId=%d - i=[%s] o=[%s]", - aznumeric_cast(input.GetClientInputId()), - GetInputString(input).c_str(), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); + AZLOG(NET_Prediction, "Forced InputId=%d", aznumeric_cast(input.GetClientInputId())); } // Decay our bank time window, in case the remote endpoint has suffered a more persistent shift in latency, this should cause the client to eventually recover diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index cbbbadeffa..070655e768 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -408,6 +408,11 @@ namespace Multiplayer m_entityPreRenderEvent.Signal(deltaTime, blendFactor); } + void NetBindComponent::NotifyCorrection() + { + m_entityCorrectionEvent.Signal(); + } + void NetBindComponent::AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler) { eventHandler.Connect(m_entityStopEvent); @@ -443,6 +448,11 @@ namespace Multiplayer eventHandler.Connect(m_entityPreRenderEvent); } + void NetBindComponent::AddEntityCorrectionEventHandler(EntityCorrectionEvent::Handler& eventHandler) + { + eventHandler.Connect(m_entityCorrectionEvent); + } + bool NetBindComponent::SerializeEntityCorrection(AzNetworking::ISerializer& serializer) { m_predictableRecord.ResetConsumedBits(); diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index df4d7618fa..fa08794c4d 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -31,6 +31,7 @@ namespace Multiplayer , m_scaleEventHandler([this](float scale) { OnScaleChangedEvent(scale); }) , m_resetCountEventHandler([this](const uint8_t&) { OnResetCountChangedEvent(); }) , m_entityPreRenderEventHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); }) + , m_entityCorrectionEventHandler([this]() { OnCorrection(); }) { ; } @@ -47,6 +48,7 @@ namespace Multiplayer ScaleAddEvent(m_scaleEventHandler); ResetCountAddEvent(m_resetCountEventHandler); GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler); + GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler); // When coming into relevance, reset all blending factors so we don't interpolate to our start position OnResetCountChangedEvent(); @@ -119,6 +121,18 @@ namespace Multiplayer } } + void NetworkTransformComponent::OnCorrection() + { + // Snap to latest + OnResetCountChangedEvent(); + + // Hard set the entities transform + if (!GetTransformComponent()->GetWorldTM().IsClose(m_targetTransform)) + { + GetTransformComponent()->SetWorldTM(m_targetTransform); + } + } + NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) From 18709dad7a1afd2469d0cfbafa0ff10197cfb1b6 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Mon, 9 Aug 2021 16:44:31 -0700 Subject: [PATCH 012/101] Removing imgui debug module from server target Signed-off-by: kberg-amzn --- Gems/Multiplayer/Code/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index e8b38c8799..96527fbfc4 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -79,7 +79,7 @@ ly_add_target( # The "Multiplayer" target is used by clients and servers, Debug is used only on clients. ly_create_alias(NAME Multiplayer.Clients NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) -ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) +ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer) if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( From 3bf4caf7d234ed86524e454b2d6c1e4b8462ac70 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 20:07:04 -0700 Subject: [PATCH 013/101] [redcode/crythread-2nd-pass] removed Cry*CriticalSection functions Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/CryThreadImpl.h | 2 +- .../Legacy/CryCommon/CryThreadImpl_pthreads.h | 56 ------------------- Code/Legacy/CryCommon/MultiThread.h | 8 --- Code/Legacy/CryCommon/crycommon_files.cmake | 1 - Code/Legacy/CryCommon/platform_impl.cpp | 53 ------------------ 5 files changed, 1 insertion(+), 119 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CryThreadImpl_pthreads.h diff --git a/Code/Legacy/CryCommon/CryThreadImpl.h b/Code/Legacy/CryCommon/CryThreadImpl.h index 0226b73716..4ff2cc6438 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl.h +++ b/Code/Legacy/CryCommon/CryThreadImpl.h @@ -14,7 +14,7 @@ // Include architecture specific code. #if defined(LINUX) || defined(APPLE) -#include +// noting to include #define AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(WIN32) || defined(WIN64) #include diff --git a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h deleted file mode 100644 index 38838991a8..0000000000 --- a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h +++ /dev/null @@ -1,56 +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 - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H -#define CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H -#pragma once - - -#include "CryThread_pthreads.h" - -/////////////////////////////////////////////////////////////////////////////// -// CryCriticalSection implementation -/////////////////////////////////////////////////////////////////////////////// -typedef CryLockT TCritSecType; - -void CryDeleteCriticalSection(void* cs) -{ - delete ((TCritSecType*)cs); -} - -void CryEnterCriticalSection(void* cs) -{ - ((TCritSecType*)cs)->Lock(); -} - -bool CryTryCriticalSection(void* cs) -{ - return false; -} - -void CryLeaveCriticalSection(void* cs) -{ - ((TCritSecType*)cs)->Unlock(); -} - -void CryCreateCriticalSectionInplace(void* pCS) -{ - new (pCS) TCritSecType; -} - -void CryDeleteCriticalSectionInplace(void*) -{ -} - -void* CryCreateCriticalSection() -{ - return (void*) new TCritSecType; -} - -#endif // CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H diff --git a/Code/Legacy/CryCommon/MultiThread.h b/Code/Legacy/CryCommon/MultiThread.h index 2b224c4743..c3aa892d14 100644 --- a/Code/Legacy/CryCommon/MultiThread.h +++ b/Code/Legacy/CryCommon/MultiThread.h @@ -48,14 +48,6 @@ LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG c void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand); void* CryInterlockedExchangePointer (void* volatile* dst, void* exchange); -void* CryCreateCriticalSection(); -void CryCreateCriticalSectionInplace(void*); -void CryDeleteCriticalSection(void* cs); -void CryDeleteCriticalSectionInplace(void* cs); -void CryEnterCriticalSection(void* cs); -bool CryTryCriticalSection(void* cs); -void CryLeaveCriticalSection(void* cs); - #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_DEFINE_CRYINTERLOCKEXCHANGE #include AZ_RESTRICTED_FILE(MultiThread_h) diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index b4dac2ec08..487d08b13c 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -162,7 +162,6 @@ set(FILES CryLibrary.h CryThread_pthreads.h CryThread_windows.h - CryThreadImpl_pthreads.h CryThreadImpl_windows.h CryWindows.h Linux32Specific.h diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index a677ba30b6..09d7493ae7 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -364,59 +364,6 @@ void CryInterlockedAdd(volatile size_t* pVal, ptrdiff_t iAdd) assert((iAdd == 0) || (iAdd < 0 && v < v - (size_t)iAdd) || (iAdd > 0 && v > v - (size_t)iAdd)); } -////////////////////////////////////////////////////////////////////////// -void* CryCreateCriticalSection() -{ - CRITICAL_SECTION* pCS = new CRITICAL_SECTION; - InitializeCriticalSection(pCS); - return pCS; -} - -void CryCreateCriticalSectionInplace(void* pCS) -{ - InitializeCriticalSection((CRITICAL_SECTION*)pCS); -} -////////////////////////////////////////////////////////////////////////// -void CryDeleteCriticalSection(void* cs) -{ - CRITICAL_SECTION* pCS = (CRITICAL_SECTION*)cs; - if (pCS->LockCount >= 0) - { - CryFatalError("Critical Section hanging lock"); - } - DeleteCriticalSection(pCS); - delete pCS; -} - -////////////////////////////////////////////////////////////////////////// -void CryDeleteCriticalSectionInplace(void* cs) -{ - CRITICAL_SECTION* pCS = (CRITICAL_SECTION*)cs; - if (pCS->LockCount >= 0) - { - CryFatalError("Critical Section hanging lock"); - } - DeleteCriticalSection(pCS); -} - -////////////////////////////////////////////////////////////////////////// -void CryEnterCriticalSection(void* cs) -{ - EnterCriticalSection((CRITICAL_SECTION*)cs); -} - -////////////////////////////////////////////////////////////////////////// -bool CryTryCriticalSection(void* cs) -{ - return TryEnterCriticalSection((CRITICAL_SECTION*)cs) != 0; -} - -////////////////////////////////////////////////////////////////////////// -void CryLeaveCriticalSection(void* cs) -{ - LeaveCriticalSection((CRITICAL_SECTION*)cs); -} - ////////////////////////////////////////////////////////////////////////// uint32 CryGetFileAttributes(const char* lpFileName) { From a70a106fd2e2f5b7b83739ab37355b06689afe33 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 14:48:33 -0700 Subject: [PATCH 014/101] Test code to add merge detection on Settings Registry keys Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzCore/Component/ComponentApplication.cpp | 1 + .../AzCore/AzCore/Settings/SettingsRegistry.h | 44 ++++++++ .../AzCore/Settings/SettingsRegistryImpl.cpp | 49 +++++++++ .../AzCore/Settings/SettingsRegistryImpl.h | 9 ++ .../Settings/EditorSettingsOriginTracker.cpp | 103 ++++++++++++++++++ .../Settings/EditorSettingsOriginTracker.h | 39 +++++++ .../aztoolsframework_files.cmake | 2 + 7 files changed, 247 insertions(+) create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index c68fce6f4d..7b1060a10f 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -728,6 +728,7 @@ namespace AZ DestroyReflectionManager(); static_cast(m_settingsRegistry.get())->ClearNotifiers(); + static_cast(m_settingsRegistry.get())->ClearMergeEvents(); // Uninit and unload any dynamic modules. m_moduleManager->UnloadModules(); diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h index 3bcf0ae89b..e27e4452ee 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h @@ -123,6 +123,36 @@ namespace AZ using NotifyEvent = AZ::Event; using NotifyEventHandler = typename NotifyEvent::Handler; + using PreMergeEventCallback = AZStd::function; + using PostMergeEventCallback = AZStd::function; + using PreMergeEvent = AZ::Event; + using PostMergeEvent = AZ::Event; + using PreMergeEventHandler = typename PreMergeEvent::Handler; + using PostMergeEventHandler = typename PostMergeEvent::Handler; + + struct ScopedMergeEvent + { + ScopedMergeEvent( + PreMergeEvent& preMergeEvent, PostMergeEvent& postMergeEvent, AZStd::string_view filePath, AZStd::string_view rootKey) + : m_preMergeEvent{ preMergeEvent } + , m_postMergeEvent{ postMergeEvent } + , m_filePath{ filePath } + , m_rootKey{ rootKey } + { + preMergeEvent.Signal(m_filePath, m_rootKey); + } + + ~ScopedMergeEvent() + { + m_postMergeEvent.Signal(m_filePath, m_rootKey); + } + + PreMergeEvent& m_preMergeEvent; + PostMergeEvent& m_postMergeEvent; + AZStd::string_view m_filePath; + AZStd::string_view m_rootKey; + }; + using VisitorCallback = AZStd::function; //! Base class for the visitor class during traversal over the Settings Registry. The type-agnostic function is always @@ -169,6 +199,20 @@ namespace AZ //! @callback The function to call when an entry gets a new/updated value. [[nodiscard]] virtual NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) = 0; + //! Register a callback that will be called before an entry is merged. + //! @callback The function to call when an entry gets a new/updated value. + [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0; + //! Register a callback that will be called before an entry is merged. + //! @callback The function to call when an entry gets a new/updated value. + [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent (PreMergeEventCallback&& callback) = 0; + + //! Register a callback that will be called after an entry is merged. + //! @callback The function to call when an entry gets a new/updated value. + [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0; + //! Register a callback that will be called after an entry is merged. + //! @callback The function to call when an entry gets a new/updated value. + [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent (PostMergeEventCallback&& callback) = 0; + //! Gets the boolean value at the provided path. //! @param result The target to write the result to. //! @param path The path to the value. diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp index 0882e1b7f2..4a7b4183f3 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp @@ -229,6 +229,53 @@ namespace AZ m_notifiers.DisconnectAllHandlers(); } + auto SettingsRegistryImpl::RegisterPreMergeEvent(const PreMergeEventCallback& callback) -> PreMergeEventHandler + { + PreMergeEventHandler preMergeHandler{ callback }; + { + AZStd::scoped_lock lock(m_settingMutex); + preMergeHandler.Connect(m_preMergeEvent); + } + return preMergeHandler; + } + + auto SettingsRegistryImpl::RegisterPreMergeEvent(PreMergeEventCallback&& callback) -> PreMergeEventHandler + { + PreMergeEventHandler preMergeHandler{ AZStd::move(callback) }; + { + AZStd::scoped_lock lock(m_settingMutex); + preMergeHandler.Connect(m_preMergeEvent); + } + return preMergeHandler; + } + + auto SettingsRegistryImpl::RegisterPostMergeEvent(const PostMergeEventCallback& callback) -> PostMergeEventHandler + { + PostMergeEventHandler postMergeHandler{ callback }; + { + AZStd::scoped_lock lock(m_settingMutex); + postMergeHandler.Connect(m_postMergeEvent); + } + return postMergeHandler; + } + + auto SettingsRegistryImpl::RegisterPostMergeEvent(PostMergeEventCallback&& callback) -> PostMergeEventHandler + { + PostMergeEventHandler postMergeHandler{ AZStd::move(callback) }; + { + AZStd::scoped_lock lock(m_settingMutex); + postMergeHandler.Connect(m_postMergeEvent); + } + return postMergeHandler; + } + + void SettingsRegistryImpl::ClearMergeEvents() + { + AZStd::scoped_lock lock(m_settingMutex); + m_preMergeEvent.DisconnectAllHandlers(); + m_postMergeEvent.DisconnectAllHandlers(); + } + SettingsRegistryInterface::Type SettingsRegistryImpl::GetType(AZStd::string_view path) const { if (path.empty()) @@ -1115,6 +1162,8 @@ namespace AZ return false; } + ScopedMergeEvent(m_preMergeEvent, m_postMergeEvent, path, rootKey); + JsonSerializationResult::ResultCode mergeResult(JsonSerializationResult::Tasks::Merge); if (rootKey.empty()) { diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h index 41a628cf22..babcafe701 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h @@ -48,6 +48,12 @@ namespace AZ [[nodiscard]] NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) override; void ClearNotifiers(); + [[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) override; + [[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback&& callback) override; + [[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) override; + [[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback&& callback) override; + void ClearMergeEvents(); + bool Get(bool& result, AZStd::string_view path) const override; bool Get(s64& result, AZStd::string_view path) const override; bool Get(u64& result, AZStd::string_view path) const override; @@ -103,6 +109,9 @@ namespace AZ mutable AZStd::recursive_mutex m_settingMutex; NotifyEvent m_notifiers; + PreMergeEvent m_preMergeEvent; + PostMergeEvent m_postMergeEvent; + rapidjson::Document m_settings; JsonSerializerSettings m_serializationSettings; JsonDeserializerSettings m_deserializationSettings; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp new file mode 100644 index 0000000000..13a0610f5c --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp @@ -0,0 +1,103 @@ +/* + * 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 + +#include +#include + +namespace AzToolsFramework +{ + EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::SettingsNotificationHandler( + AZ::SettingsRegistryInterface& registry) + : m_settingsRegistry(registry) + { + AZ::JsonApplyPatchSettings applyPatchSettings; + m_settingsRegistry.GetApplyPatchSettings(applyPatchSettings); + // Wrap any existing callbacks into the reporting callback, so that both this struct + // reporting callbacks and the existing callbacks can be invoked + m_prevReportingCallback = applyPatchSettings.m_reporting; + applyPatchSettings.m_reporting = [this]( + AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, + AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode + { + m_prevReportingCallback(message, result, path); + (*this)(message, result, path); + return result; + }; + m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); + } + + EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::~SettingsNotificationHandler() + { + // Restore previous reporting callback + AZ::JsonApplyPatchSettings applyPatchSettings; + m_settingsRegistry.GetApplyPatchSettings(applyPatchSettings); + applyPatchSettings.m_reporting = m_prevReportingCallback; + m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); + } + + // Use the Json Serialization Issue Callback system + // to determine when a merge option modifies a value + AZ::JsonSerializationResult::ResultCode EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::operator()( + AZStd::string_view /*message*/, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path) + { + using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; + + AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; + AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; + + // Delegate to the Notifier Handler callable below + if (result.GetTask() == AZ::JsonSerializationResult::Tasks::Merge && + result.GetProcessing() == AZ::JsonSerializationResult::Processing::Completed && inputKey.IsRelativeTo(preferencesRootKey)) + { + if (auto type = m_settingsRegistry.GetType(path); type != AZ::SettingsRegistryInterface::Type::NoType) + { + operator()(path, type); + } + } + + return result; + } + + void EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::operator()( + AZStd::string_view path, AZ::SettingsRegistryInterface::Type /*type*/) + { + constexpr AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; + AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; + if (inputKey.IsRelativeTo(preferencesRootKey)) + { + // Do stuff with key + } + } + + EditorPreferencesSettingsOriginTracker::EditorPreferencesSettingsOriginTracker(AZ::SettingsRegistryInterface& registry) + : m_settingsRegistry(registry) + { + auto PreMergeEvent = [this](AZStd::string_view filePath, AZStd::string_view /*rootKey*/) + { + AZ::IO::FixedMaxPath editorPreferencesPath = AZ::Utils::GetProjectPath(); + editorPreferencesPath = editorPreferencesPath / "user" / "Registry" / "editorpreferences.setreg"; + + if (AZ::IO::PathView(filePath) == editorPreferencesPath) + { + m_notifyHandler = m_settingsRegistry.RegisterNotifier(SettingsNotificationHandler(m_settingsRegistry)); + } + }; + + auto PostMergeEvent = [this](AZStd::string_view /*filePath*/, AZStd::string_view /*rootKey*/) + { + // Clear the notification handler so that it goes out of scope + // and this tracker instance no handles settings updates + m_notifyHandler = {}; + }; + + m_preMergeEventHandler = m_settingsRegistry.RegisterPreMergeEvent(PreMergeEvent); + m_postMergeEventHandler = m_settingsRegistry.RegisterPostMergeEvent(PostMergeEvent); + } +} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h new file mode 100644 index 0000000000..63249a8ecd --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h @@ -0,0 +1,39 @@ +/* + * 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 +#include +#include + +namespace AzToolsFramework +{ + struct EditorPreferencesSettingsOriginTracker + { + explicit EditorPreferencesSettingsOriginTracker(AZ::SettingsRegistryInterface& registry); + + struct SettingsNotificationHandler + { + SettingsNotificationHandler(AZ::SettingsRegistryInterface& registry); + ~SettingsNotificationHandler(); + + AZ::JsonSerializationResult::ResultCode operator()( + AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path); + void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type type); + + private: + AZ::SettingsRegistryInterface& m_settingsRegistry; + AZ::JsonSerializationResult::JsonIssueCallback m_prevReportingCallback; + }; + + private: + AZ::SettingsRegistryInterface& m_settingsRegistry; + AZ::SettingsRegistryInterface::PreMergeEventHandler m_preMergeEventHandler; + AZ::SettingsRegistryInterface::PostMergeEventHandler m_postMergeEventHandler; + AZ::SettingsRegistryInterface::NotifyEventHandler m_notifyHandler; + }; +} // namespace AZ diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 53173f83af..6e7446d74d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -113,6 +113,8 @@ set(FILES Component/EditorLevelComponentAPIComponent.h Editor/EditorContextMenuBus.h Editor/EditorSettingsAPIBus.h + Editor/Settings/EditorSettingsOriginTracker.cpp + Editor/Settings/EditorSettingsOriginTracker.h Entity/EditorEntityStartStatus.h Entity/EditorEntityAPIBus.h Entity/EditorEntityContextComponent.cpp From 6f6b88ec2f785ff3ef8c2e56b6c4134df54d345a Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 15:27:01 -0700 Subject: [PATCH 015/101] Rename EditorSettingsOriginTracker Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Editor/Settings/EditorSettingsOriginTracker.cpp | 10 +++++----- .../Editor/Settings/EditorSettingsOriginTracker.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp index 13a0610f5c..bdeb4e41b4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp @@ -13,7 +13,7 @@ namespace AzToolsFramework { - EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::SettingsNotificationHandler( + EditorSettingsOriginTracker::SettingsNotificationHandler::SettingsNotificationHandler( AZ::SettingsRegistryInterface& registry) : m_settingsRegistry(registry) { @@ -33,7 +33,7 @@ namespace AzToolsFramework m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); } - EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::~SettingsNotificationHandler() + EditorSettingsOriginTracker::SettingsNotificationHandler::~SettingsNotificationHandler() { // Restore previous reporting callback AZ::JsonApplyPatchSettings applyPatchSettings; @@ -44,7 +44,7 @@ namespace AzToolsFramework // Use the Json Serialization Issue Callback system // to determine when a merge option modifies a value - AZ::JsonSerializationResult::ResultCode EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::operator()( + AZ::JsonSerializationResult::ResultCode EditorSettingsOriginTracker::SettingsNotificationHandler::operator()( AZStd::string_view /*message*/, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path) { using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; @@ -65,7 +65,7 @@ namespace AzToolsFramework return result; } - void EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::operator()( + void EditorSettingsOriginTracker::SettingsNotificationHandler::operator()( AZStd::string_view path, AZ::SettingsRegistryInterface::Type /*type*/) { constexpr AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; @@ -76,7 +76,7 @@ namespace AzToolsFramework } } - EditorPreferencesSettingsOriginTracker::EditorPreferencesSettingsOriginTracker(AZ::SettingsRegistryInterface& registry) + EditorSettingsOriginTracker::EditorSettingsOriginTracker(AZ::SettingsRegistryInterface& registry) : m_settingsRegistry(registry) { auto PreMergeEvent = [this](AZStd::string_view filePath, AZStd::string_view /*rootKey*/) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h index 63249a8ecd..3ef3f141a2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h @@ -12,9 +12,9 @@ namespace AzToolsFramework { - struct EditorPreferencesSettingsOriginTracker + struct EditorSettingsOriginTracker { - explicit EditorPreferencesSettingsOriginTracker(AZ::SettingsRegistryInterface& registry); + explicit EditorSettingsOriginTracker(AZ::SettingsRegistryInterface& registry); struct SettingsNotificationHandler { From 88762b2b69992b6d28e37e94a163cf7e4691040c Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 15:33:24 -0700 Subject: [PATCH 016/101] Add #pragma once to EditorSettingsOriginTracker to make it build :) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Editor/Settings/EditorSettingsOriginTracker.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h index 3ef3f141a2..fbfdc1af25 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h @@ -6,6 +6,8 @@ * */ +#pragma once + #include #include #include From f3fe8439a71a15fdfab6af58b384315efe8b9698 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 17:29:27 -0700 Subject: [PATCH 017/101] Fix local variable declaration. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp index 4a7b4183f3..8b10013408 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp @@ -1162,7 +1162,7 @@ namespace AZ return false; } - ScopedMergeEvent(m_preMergeEvent, m_postMergeEvent, path, rootKey); + ScopedMergeEvent scopedMergeEvent(m_preMergeEvent, m_postMergeEvent, path, rootKey); JsonSerializationResult::ResultCode mergeResult(JsonSerializationResult::Tasks::Merge); if (rootKey.empty()) From 6db547302ea047479af2649db8f80da535412a8e Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 17:32:39 -0700 Subject: [PATCH 018/101] Remove EditorSettingsOriginTracker (moved to prototype branch) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Settings/EditorSettingsOriginTracker.cpp | 103 ------------------ .../Settings/EditorSettingsOriginTracker.h | 41 ------- .../aztoolsframework_files.cmake | 2 - 3 files changed, 146 deletions(-) delete mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp delete mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp deleted file mode 100644 index bdeb4e41b4..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp +++ /dev/null @@ -1,103 +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 - -#include -#include - -namespace AzToolsFramework -{ - EditorSettingsOriginTracker::SettingsNotificationHandler::SettingsNotificationHandler( - AZ::SettingsRegistryInterface& registry) - : m_settingsRegistry(registry) - { - AZ::JsonApplyPatchSettings applyPatchSettings; - m_settingsRegistry.GetApplyPatchSettings(applyPatchSettings); - // Wrap any existing callbacks into the reporting callback, so that both this struct - // reporting callbacks and the existing callbacks can be invoked - m_prevReportingCallback = applyPatchSettings.m_reporting; - applyPatchSettings.m_reporting = [this]( - AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, - AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode - { - m_prevReportingCallback(message, result, path); - (*this)(message, result, path); - return result; - }; - m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); - } - - EditorSettingsOriginTracker::SettingsNotificationHandler::~SettingsNotificationHandler() - { - // Restore previous reporting callback - AZ::JsonApplyPatchSettings applyPatchSettings; - m_settingsRegistry.GetApplyPatchSettings(applyPatchSettings); - applyPatchSettings.m_reporting = m_prevReportingCallback; - m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); - } - - // Use the Json Serialization Issue Callback system - // to determine when a merge option modifies a value - AZ::JsonSerializationResult::ResultCode EditorSettingsOriginTracker::SettingsNotificationHandler::operator()( - AZStd::string_view /*message*/, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path) - { - using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; - - AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; - AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; - - // Delegate to the Notifier Handler callable below - if (result.GetTask() == AZ::JsonSerializationResult::Tasks::Merge && - result.GetProcessing() == AZ::JsonSerializationResult::Processing::Completed && inputKey.IsRelativeTo(preferencesRootKey)) - { - if (auto type = m_settingsRegistry.GetType(path); type != AZ::SettingsRegistryInterface::Type::NoType) - { - operator()(path, type); - } - } - - return result; - } - - void EditorSettingsOriginTracker::SettingsNotificationHandler::operator()( - AZStd::string_view path, AZ::SettingsRegistryInterface::Type /*type*/) - { - constexpr AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; - AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; - if (inputKey.IsRelativeTo(preferencesRootKey)) - { - // Do stuff with key - } - } - - EditorSettingsOriginTracker::EditorSettingsOriginTracker(AZ::SettingsRegistryInterface& registry) - : m_settingsRegistry(registry) - { - auto PreMergeEvent = [this](AZStd::string_view filePath, AZStd::string_view /*rootKey*/) - { - AZ::IO::FixedMaxPath editorPreferencesPath = AZ::Utils::GetProjectPath(); - editorPreferencesPath = editorPreferencesPath / "user" / "Registry" / "editorpreferences.setreg"; - - if (AZ::IO::PathView(filePath) == editorPreferencesPath) - { - m_notifyHandler = m_settingsRegistry.RegisterNotifier(SettingsNotificationHandler(m_settingsRegistry)); - } - }; - - auto PostMergeEvent = [this](AZStd::string_view /*filePath*/, AZStd::string_view /*rootKey*/) - { - // Clear the notification handler so that it goes out of scope - // and this tracker instance no handles settings updates - m_notifyHandler = {}; - }; - - m_preMergeEventHandler = m_settingsRegistry.RegisterPreMergeEvent(PreMergeEvent); - m_postMergeEventHandler = m_settingsRegistry.RegisterPostMergeEvent(PostMergeEvent); - } -} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h deleted file mode 100644 index fbfdc1af25..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h +++ /dev/null @@ -1,41 +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 - -#include -#include -#include - -namespace AzToolsFramework -{ - struct EditorSettingsOriginTracker - { - explicit EditorSettingsOriginTracker(AZ::SettingsRegistryInterface& registry); - - struct SettingsNotificationHandler - { - SettingsNotificationHandler(AZ::SettingsRegistryInterface& registry); - ~SettingsNotificationHandler(); - - AZ::JsonSerializationResult::ResultCode operator()( - AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path); - void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type type); - - private: - AZ::SettingsRegistryInterface& m_settingsRegistry; - AZ::JsonSerializationResult::JsonIssueCallback m_prevReportingCallback; - }; - - private: - AZ::SettingsRegistryInterface& m_settingsRegistry; - AZ::SettingsRegistryInterface::PreMergeEventHandler m_preMergeEventHandler; - AZ::SettingsRegistryInterface::PostMergeEventHandler m_postMergeEventHandler; - AZ::SettingsRegistryInterface::NotifyEventHandler m_notifyHandler; - }; -} // namespace AZ diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 6e7446d74d..53173f83af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -113,8 +113,6 @@ set(FILES Component/EditorLevelComponentAPIComponent.h Editor/EditorContextMenuBus.h Editor/EditorSettingsAPIBus.h - Editor/Settings/EditorSettingsOriginTracker.cpp - Editor/Settings/EditorSettingsOriginTracker.h Entity/EditorEntityStartStatus.h Entity/EditorEntityAPIBus.h Entity/EditorEntityContextComponent.cpp From 737cf3093791efb073ad226cbe7703e840c958d5 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 17:36:43 -0700 Subject: [PATCH 019/101] Fix documentation comments to be more accurate. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzCore/AzCore/Settings/SettingsRegistry.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h index e27e4452ee..106e232904 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h @@ -199,18 +199,18 @@ namespace AZ //! @callback The function to call when an entry gets a new/updated value. [[nodiscard]] virtual NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) = 0; - //! Register a callback that will be called before an entry is merged. - //! @callback The function to call when an entry gets a new/updated value. + //! Register a function that will be called before a file is merged. + //! @callback The function to call before a file is merged. [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0; - //! Register a callback that will be called before an entry is merged. - //! @callback The function to call when an entry gets a new/updated value. + //! Register a function that will be called before a file is merged. + //! @callback The function to call before a file is merged. [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent (PreMergeEventCallback&& callback) = 0; - //! Register a callback that will be called after an entry is merged. - //! @callback The function to call when an entry gets a new/updated value. + //! Register a function that will be called after a file is merged. + //! @callback The function to call after a file is merged. [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0; - //! Register a callback that will be called after an entry is merged. - //! @callback The function to call when an entry gets a new/updated value. + //! Register a function that will be called after a file is merged. + //! @callback The function to call after a file is merged. [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent (PostMergeEventCallback&& callback) = 0; //! Gets the boolean value at the provided path. From f99f1f00f4de5696275db77cbbca5ee168891dab Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Tue, 10 Aug 2021 20:35:55 -0700 Subject: [PATCH 020/101] [redcode/crythread-2nd-pass] removed or replaced remaining CryMutex/CryLock usage with equivalent AZStd version Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 18 +++++++++--------- Code/Editor/GameEngine.h | 4 ++-- Code/Editor/GameExporter.cpp | 2 +- Code/Editor/IEditorImpl.cpp | 6 +++--- Code/Editor/IEditorImpl.h | 2 +- .../PerforcePlugin/PerforceSourceControl.cpp | 8 ++++---- Code/Legacy/CryCommon/CryAssert_Linux.h | 4 ++-- Code/Legacy/CryCommon/CryAssert_Mac.h | 2 -- Code/Legacy/CryCommon/IMaterial.h | 2 -- .../Legacy/CryCommon/MultiThread_Containers.h | 6 +++--- .../Legacy/CrySystem/LocalizedStringManager.h | 4 ++-- Code/Legacy/CrySystem/Log.cpp | 19 ++++--------------- Code/Legacy/CrySystem/Log.h | 4 +--- .../CrySystem/SystemEventDispatcher.cpp | 12 ++++++------ Code/Legacy/CrySystem/SystemEventDispatcher.h | 2 +- 15 files changed, 39 insertions(+), 56 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 5a5b17f799..fdde069e6f 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -891,7 +891,7 @@ CCrySingleDocTemplate::Confidence CCrySingleDocTemplate::MatchDocType(LPCTSTR lp ///////////////////////////////////////////////////////////////////////////// namespace { - CryMutex g_splashScreenStateLock; + AZStd::mutex g_splashScreenStateLock; enum ESplashScreenState { eSplashScreenState_Init, eSplashScreenState_Started, eSplashScreenState_Destroy @@ -922,7 +922,7 @@ QString FormatRichTextCopyrightNotice() ///////////////////////////////////////////////////////////////////////////// void CCryEditApp::ShowSplashScreen(CCryEditApp* app) { - g_splashScreenStateLock.Lock(); + g_splashScreenStateLock.lock(); CStartupLogoDialog* splashScreen = new CStartupLogoDialog(FormatVersion(app->m_pEditor->GetFileVersion()), FormatRichTextCopyrightNotice()); @@ -930,7 +930,7 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app) g_splashScreen = splashScreen; g_splashScreenState = eSplashScreenState_Started; - g_splashScreenStateLock.Unlock(); + g_splashScreenStateLock.unlock(); splashScreen->show(); // Make sure the initial paint of the splash screen occurs so we dont get stuck with a blank window @@ -938,10 +938,10 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app) QObject::connect(splashScreen, &QObject::destroyed, splashScreen, [=] { - g_splashScreenStateLock.Lock(); + g_splashScreenStateLock.lock(); g_pInitializeUIInfo = nullptr; g_splashScreen = nullptr; - g_splashScreenStateLock.Unlock(); + g_splashScreenStateLock.unlock(); }); } @@ -971,9 +971,9 @@ void CCryEditApp::CloseSplashScreen() if (CStartupLogoDialog::instance()) { delete CStartupLogoDialog::instance(); - g_splashScreenStateLock.Lock(); + g_splashScreenStateLock.lock(); g_splashScreenState = eSplashScreenState_Destroy; - g_splashScreenStateLock.Unlock(); + g_splashScreenStateLock.unlock(); } GetIEditor()->Notify(eNotify_OnSplashScreenDestroyed); @@ -982,12 +982,12 @@ void CCryEditApp::CloseSplashScreen() ///////////////////////////////////////////////////////////////////////////// void CCryEditApp::OutputStartupMessage(QString str) { - g_splashScreenStateLock.Lock(); + g_splashScreenStateLock.lock(); if (g_pInitializeUIInfo) { g_pInitializeUIInfo->SetInfoText(str.toUtf8().data()); } - g_splashScreenStateLock.Unlock(); + g_splashScreenStateLock.unlock(); } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/GameEngine.h b/Code/Editor/GameEngine.h index 84df8bf002..4d183cc38e 100644 --- a/Code/Editor/GameEngine.h +++ b/Code/Editor/GameEngine.h @@ -116,11 +116,11 @@ public: //! mutex used by other threads to lock up the PAK modification, //! so only one thread can modify the PAK at once - static CryMutex& GetPakModifyMutex() + static AZStd::recursive_mutex& GetPakModifyMutex() { //! mutex used to halt copy process while the export to game //! or other pak operation is done in the main thread - static CryMutex s_pakModifyMutex; + static AZStd::recursive_mutex s_pakModifyMutex; return s_pakModifyMutex; } diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 006eb9189c..d2a16ccc30 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -136,7 +136,7 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE m_settings.SetHiQuality(); } - CryAutoLock autoLock(CGameEngine::GetPakModifyMutex()); + AZStd::lock_guard autoLock(CGameEngine::GetPakModifyMutex()); // Close this pak file. if (!CloseLevelPack(m_levelPak, true)) diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index c09c0a8e62..3c166fbca2 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -251,7 +251,7 @@ void CEditorImpl::Uninitialize() void CEditorImpl::UnloadPlugins() { - CryAutoLock lock(m_pluginMutex); + AZStd::lock_guard lock(m_pluginMutex); // Flush core buses. We're about to unload DLLs and need to ensure we don't have module-owned functions left behind. AZ::Data::AssetBus::ExecuteQueuedEvents(); @@ -272,7 +272,7 @@ void CEditorImpl::UnloadPlugins() void CEditorImpl::LoadPlugins() { - CryAutoLock lock(m_pluginMutex); + AZStd::lock_guard lock(m_pluginMutex); static const QString editor_plugins_folder("EditorPlugins"); @@ -1457,7 +1457,7 @@ void CEditorImpl::UnregisterNotifyListener(IEditorNotifyListener* listener) ISourceControl* CEditorImpl::GetSourceControl() { - CryAutoLock lock(m_pluginMutex); + AZStd::lock_guard lock(m_pluginMutex); if (m_pSourceControl) { diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h index 65389a212e..275214bc57 100644 --- a/Code/Editor/IEditorImpl.h +++ b/Code/Editor/IEditorImpl.h @@ -401,7 +401,7 @@ protected: IImageUtil* m_pImageUtil; // Vladimir@conffx ILogFile* m_pLogFile; // Vladimir@conffx - CryMutex m_pluginMutex; // protect any pointers that come from plugins, such as the source control cached pointer. + AZStd::mutex m_pluginMutex; // protect any pointers that come from plugins, such as the source control cached pointer. static const char* m_crashLogFileName; }; diff --git a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp index 581f9a576d..34514b8ef1 100644 --- a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp +++ b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp @@ -22,7 +22,7 @@ namespace { - CryCriticalSection g_cPerforceValues; + AZStd::mutex g_cPerforceValues; } //////////////////////////////////////////////////////////// @@ -30,9 +30,9 @@ ULONG STDMETHODCALLTYPE CPerforceSourceControl::Release() { if ((--m_ref) == 0) { - g_cPerforceValues.Lock(); + g_cPerforceValues.lock(); delete this; - g_cPerforceValues.Unlock(); + g_cPerforceValues.unlock(); return 0; } else @@ -56,7 +56,7 @@ void CPerforceSourceControl::ShowSettings() void CPerforceSourceControl::SetSourceControlState(SourceControlState state) { - CryAutoLock lock(g_cPerforceValues); + AZStd::lock_guard lock(g_cPerforceValues); switch (state) { diff --git a/Code/Legacy/CryCommon/CryAssert_Linux.h b/Code/Legacy/CryCommon/CryAssert_Linux.h index 3debe2bd5d..355194caba 100644 --- a/Code/Legacy/CryCommon/CryAssert_Linux.h +++ b/Code/Legacy/CryCommon/CryAssert_Linux.h @@ -72,7 +72,7 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b static const int max_len = 4096; static char gs_command_str[4096]; - static CryLockT lock; + static AZStd::recursive_mutex lock; gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line); @@ -80,7 +80,7 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts) { - CryAutoLock< CryLockT > lk (lock); + AZStd::lock_guard lk (lock); snprintf(gs_command_str, max_len, "xterm -geometry 100x20 -n 'Assert Dialog [Linux Launcher]' -T 'Assert Dialog [Linux Launcher]' -e 'BinLinux/assert_term \"%s\" \"%s\" %d \"%s\"; echo \"$?\" > .assert_return'", szCondition, (file_len > 60) ? szFile + (file_len - 61) : szFile, line, gs_szMessage); int ret = system(gs_command_str); diff --git a/Code/Legacy/CryCommon/CryAssert_Mac.h b/Code/Legacy/CryCommon/CryAssert_Mac.h index ce65b352ab..f0a893630e 100644 --- a/Code/Legacy/CryCommon/CryAssert_Mac.h +++ b/Code/Legacy/CryCommon/CryAssert_Mac.h @@ -70,8 +70,6 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b static const int max_len = 4096; static char gs_command_str[4096]; - static CryLockT lock; - gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line); size_t file_len = strlen(szFile); diff --git a/Code/Legacy/CryCommon/IMaterial.h b/Code/Legacy/CryCommon/IMaterial.h index 1faee0eef9..97a5100018 100644 --- a/Code/Legacy/CryCommon/IMaterial.h +++ b/Code/Legacy/CryCommon/IMaterial.h @@ -432,8 +432,6 @@ struct IMaterial virtual uint32 GetDccMaterialHash() const = 0; virtual void SetDccMaterialHash(uint32 hash) = 0; - virtual CryCriticalSection& GetSubMaterialResizeLock() = 0; - virtual void UpdateShaderItems() = 0; // diff --git a/Code/Legacy/CryCommon/MultiThread_Containers.h b/Code/Legacy/CryCommon/MultiThread_Containers.h index 23f7cd1e0c..8a60adfa6b 100644 --- a/Code/Legacy/CryCommon/MultiThread_Containers.h +++ b/Code/Legacy/CryCommon/MultiThread_Containers.h @@ -34,7 +34,7 @@ namespace CryMT public: typedef T value_type; typedef std::vector container_type; - typedef CryAutoCriticalSection AutoLock; + typedef AZStd::lock_guard AutoLock; ////////////////////////////////////////////////////////////////////////// // std::queue interface @@ -46,7 +46,7 @@ namespace CryMT // classic pop function of queue should not be used for thread safety, use try_pop instead //void pop() { AutoLock lock(m_cs); return v.erase(v.begin()); }; - CryCriticalSection& get_lock() const { return m_cs; } + AZStd::recursive_mutex& get_lock() const { return m_cs; } bool empty() const { AutoLock lock(m_cs); return v.empty(); } int size() const { AutoLock lock(m_cs); return v.size(); } @@ -92,7 +92,7 @@ namespace CryMT } private: container_type v; - mutable CryCriticalSection m_cs; + mutable AZStd::recursive_mutex m_cs; }; }; // namespace CryMT diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.h b/Code/Legacy/CrySystem/LocalizedStringManager.h index 581a657c81..6916dee3c3 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.h +++ b/Code/Legacy/CrySystem/LocalizedStringManager.h @@ -309,8 +309,8 @@ private: TLocalizationBitfield m_availableLocalizations; //Lock for - mutable CryCriticalSection m_cs; - typedef CryAutoCriticalSection AutoLock; + mutable AZStd::mutex m_cs; + typedef AZStd::lock_guard AutoLock; }; diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index 96bc29b58a..e7ba8f5ba7 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -32,17 +32,6 @@ #include #endif - -// Only accept logging from the main thread. -#ifdef WIN32 - -#define THREAD_SAFE_LOG -//#define THREAD_SAFE_LOG CryAutoCriticalSection scope_lock(m_logCriticalSection); - -#else -#define THREAD_SAFE_LOG -#endif //WIN32 - #define LOG_BACKUP_PATH "@log@/LogBackups" #if defined(IOS) @@ -822,13 +811,13 @@ void CLog::PushAssetScopeName(const char* sAssetType, const char* sName) SAssetScopeInfo as; as.sType = sAssetType; as.sName = sName; - CryAutoCriticalSection scope_lock(m_assetScopeQueueLock); + AZStd::lock_guard scope_lock(m_assetScopeQueueLock); m_assetScopeQueue.push_back(as); } void CLog::PopAssetScopeName() { - CryAutoCriticalSection scope_lock(m_assetScopeQueueLock); + AZStd::lock_guard scope_lock(m_assetScopeQueueLock); assert(!m_assetScopeQueue.empty()); if (!m_assetScopeQueue.empty()) { @@ -839,7 +828,7 @@ void CLog::PopAssetScopeName() ////////////////////////////////////////////////////////////////////////// const char* CLog::GetAssetScopeString() { - CryAutoCriticalSection scope_lock(m_assetScopeQueueLock); + AZStd::lock_guard scope_lock(m_assetScopeQueueLock); m_assetScopeString.clear(); for (size_t i = 0; i < m_assetScopeQueue.size(); i++) @@ -1470,7 +1459,7 @@ void CLog::Update() { if (!m_threadSafeMsgQueue.empty()) { - CryAutoCriticalSection lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it) + AZStd::lock_guard lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it) // Must be called from main thread SLogMsg msg; while (m_threadSafeMsgQueue.try_pop(msg)) diff --git a/Code/Legacy/CrySystem/Log.h b/Code/Legacy/CrySystem/Log.h index 5b1956b12f..d6b6dcea3e 100644 --- a/Code/Legacy/CrySystem/Log.h +++ b/Code/Legacy/CrySystem/Log.h @@ -168,7 +168,7 @@ private: // ------------------------------------------------------------------- }; std::vector m_assetScopeQueue; - CryCriticalSection m_assetScopeQueueLock; + AZStd::mutex m_assetScopeQueueLock; string m_assetScopeString; #endif @@ -176,8 +176,6 @@ private: // ------------------------------------------------------------------- IConsole* m_pConsole; // - CryCriticalSection m_logCriticalSection; - struct SLogHistoryItem { char str[MAX_WARNING_LENGTH]; diff --git a/Code/Legacy/CrySystem/SystemEventDispatcher.cpp b/Code/Legacy/CrySystem/SystemEventDispatcher.cpp index eb8113c501..525bf1a005 100644 --- a/Code/Legacy/CrySystem/SystemEventDispatcher.cpp +++ b/Code/Legacy/CrySystem/SystemEventDispatcher.cpp @@ -17,17 +17,17 @@ CSystemEventDispatcher::CSystemEventDispatcher() bool CSystemEventDispatcher::RegisterListener(ISystemEventListener* pListener) { - m_listenerRegistrationLock.Lock(); + m_listenerRegistrationLock.lock(); bool ret = m_listeners.Add(pListener); - m_listenerRegistrationLock.Unlock(); + m_listenerRegistrationLock.unlock(); return ret; } bool CSystemEventDispatcher::RemoveListener(ISystemEventListener* pListener) { - m_listenerRegistrationLock.Lock(); + m_listenerRegistrationLock.lock(); m_listeners.Remove(pListener); - m_listenerRegistrationLock.Unlock(); + m_listenerRegistrationLock.unlock(); return true; } @@ -35,12 +35,12 @@ bool CSystemEventDispatcher::RemoveListener(ISystemEventListener* pListener) ////////////////////////////////////////////////////////////////////////// void CSystemEventDispatcher::OnSystemEventAnyThread(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) { - m_listenerRegistrationLock.Lock(); + m_listenerRegistrationLock.lock(); for (TSystemEventListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next()) { notifier->OnSystemEventAnyThread(event, wparam, lparam); } - m_listenerRegistrationLock.Unlock(); + m_listenerRegistrationLock.unlock(); } diff --git a/Code/Legacy/CrySystem/SystemEventDispatcher.h b/Code/Legacy/CrySystem/SystemEventDispatcher.h index 37ce170abd..a5d33b2542 100644 --- a/Code/Legacy/CrySystem/SystemEventDispatcher.h +++ b/Code/Legacy/CrySystem/SystemEventDispatcher.h @@ -46,7 +46,7 @@ private: typedef CryMT::queue TSystemEventQueue; TSystemEventQueue m_systemEventQueue; - CryCriticalSection m_listenerRegistrationLock; + AZStd::recursive_mutex m_listenerRegistrationLock; }; #endif // CRYINCLUDE_CRYSYSTEM_SYSTEMEVENTDISPATCHER_H From 6f2b7baae8032203e5466384c255e1e3ea5bbda3 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:27:22 -0700 Subject: [PATCH 021/101] [redcode/crythread-2nd-pass] removed CryThread*.h files Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/Include/IObjectManager.h | 1 + Code/Editor/Objects/ObjectLoader.h | 2 + Code/Editor/QtUtil.h | 1 + Code/Editor/Util/FileUtil.h | 1 - Code/Editor/Util/Variable.h | 2 + Code/Legacy/CryCommon/CryThread.h | 110 ---------- Code/Legacy/CryCommon/CryThreadImpl.h | 29 --- Code/Legacy/CryCommon/CryThreadImpl_windows.h | 78 ------- Code/Legacy/CryCommon/CryThread_pthreads.h | 199 ------------------ Code/Legacy/CryCommon/CryThread_windows.h | 95 --------- Code/Legacy/CryCommon/Synchronization.h | 1 - Code/Legacy/CryCommon/crycommon_files.cmake | 5 - Code/Legacy/CryCommon/platform.h | 1 - Code/Legacy/CryCommon/platform_impl.cpp | 4 - Code/Legacy/CrySystem/Log.h | 1 - Code/Legacy/CrySystem/SystemEventDispatcher.h | 1 + 16 files changed, 7 insertions(+), 524 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CryThread.h delete mode 100644 Code/Legacy/CryCommon/CryThreadImpl.h delete mode 100644 Code/Legacy/CryCommon/CryThreadImpl_windows.h delete mode 100644 Code/Legacy/CryCommon/CryThread_pthreads.h delete mode 100644 Code/Legacy/CryCommon/CryThread_windows.h diff --git a/Code/Editor/Include/IObjectManager.h b/Code/Editor/Include/IObjectManager.h index ce9d69681b..efc1955a56 100644 --- a/Code/Editor/Include/IObjectManager.h +++ b/Code/Editor/Include/IObjectManager.h @@ -14,6 +14,7 @@ #include #include #include +#include // forward declarations. class CEntityObject; diff --git a/Code/Editor/Objects/ObjectLoader.h b/Code/Editor/Objects/ObjectLoader.h index ccfaeb78f0..fc526970dd 100644 --- a/Code/Editor/Objects/ObjectLoader.h +++ b/Code/Editor/Objects/ObjectLoader.h @@ -15,6 +15,8 @@ #include "Util/GuidUtil.h" #include "ErrorReport.h" +#include + class CPakFile; class CErrorRecord; struct IObjectManager; diff --git a/Code/Editor/QtUtil.h b/Code/Editor/QtUtil.h index bb1f8ba427..69fe03baa1 100644 --- a/Code/Editor/QtUtil.h +++ b/Code/Editor/QtUtil.h @@ -12,6 +12,7 @@ #include #include #include "UnicodeFunctions.h" +#include #include #include diff --git a/Code/Editor/Util/FileUtil.h b/Code/Editor/Util/FileUtil.h index 3be66d6e96..6b2800dd27 100644 --- a/Code/Editor/Util/FileUtil.h +++ b/Code/Editor/Util/FileUtil.h @@ -9,7 +9,6 @@ #pragma once -#include "CryThread.h" #include "StringUtils.h" #include "../Include/SandboxAPI.h" #include diff --git a/Code/Editor/Util/Variable.h b/Code/Editor/Util/Variable.h index 83afee0924..ecd54e42ae 100644 --- a/Code/Editor/Util/Variable.h +++ b/Code/Editor/Util/Variable.h @@ -22,6 +22,8 @@ AZ_PUSH_DISABLE_WARNING(4458, "-Wunknown-warning-option") AZ_POP_DISABLE_WARNING #include +#include + inline const char* to_c_str(const char* str) { return str; } #define MAX_VAR_STRING_LENGTH 4096 diff --git a/Code/Legacy/CryCommon/CryThread.h b/Code/Legacy/CryCommon/CryThread.h deleted file mode 100644 index fcd7be16ba..0000000000 --- a/Code/Legacy/CryCommon/CryThread.h +++ /dev/null @@ -1,110 +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 - * - */ - - -// Description : Public include file for the multi-threading API. - - -#pragma once - - -// Include basic multithread primitives. -#include "MultiThread.h" -#include "BitFiddling.h" -#include -////////////////////////////////////////////////////////////////////////// -// Lock types: -// -// CRYLOCK_FAST -// A fast potentially (non-recursive) mutex. -// CRYLOCK_RECURSIVE -// A recursive mutex. -////////////////////////////////////////////////////////////////////////// -enum CryLockType -{ - CRYLOCK_FAST = 1, - CRYLOCK_RECURSIVE = 2, -}; - -#define CRYLOCK_HAVE_FASTLOCK 1 - -///////////////////////////////////////////////////////////////////////////// -// -// Primitive locks and conditions. -// -// Primitive locks are represented by instance of class CryLockT -// -// -template -class CryLockT -{ - /* Unsupported lock type. */ -}; - -////////////////////////////////////////////////////////////////////////// -// Typedefs. -////////////////////////////////////////////////////////////////////////// -typedef CryLockT CryCriticalSection; -typedef CryLockT CryCriticalSectionNonRecursive; -////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////// -// -// CryAutoCriticalSection implements a helper class to automatically -// lock critical section in constructor and release on destructor. -// -////////////////////////////////////////////////////////////////////////// -template -class CryAutoLock -{ -private: - LockClass* m_pLock; - - CryAutoLock(); - CryAutoLock(const CryAutoLock&); - CryAutoLock& operator = (const CryAutoLock&); - -public: - CryAutoLock(LockClass& Lock) - : m_pLock(&Lock) { m_pLock->Lock(); } - CryAutoLock(const LockClass& Lock) - : m_pLock(const_cast(&Lock)) { m_pLock->Lock(); } - ~CryAutoLock() { m_pLock->Unlock(); } -}; - -////////////////////////////////////////////////////////////////////////// -// -// Auto critical section is the most commonly used type of auto lock. -// -////////////////////////////////////////////////////////////////////////// -typedef CryAutoLock CryAutoCriticalSection; - -/////////////////////////////////////////////////////////////////////////////// -// Include architecture specific code. -#if AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS -#include -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(WIN32) || defined(WIN64) -#include -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) - #include AZ_RESTRICTED_FILE(CryThread_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else -// Put other platform specific includes here! -#endif - -#if !defined _CRYTHREAD_CONDLOCK_GLITCH -typedef CryLockT CryMutex; -#endif // !_CRYTHREAD_CONDLOCK_GLITCH - -// Include all multithreading containers. -#include "MultiThread_Containers.h" diff --git a/Code/Legacy/CryCommon/CryThreadImpl.h b/Code/Legacy/CryCommon/CryThreadImpl.h deleted file mode 100644 index 4ff2cc6438..0000000000 --- a/Code/Legacy/CryCommon/CryThreadImpl.h +++ /dev/null @@ -1,29 +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 - - -#include - -// Include architecture specific code. -#if defined(LINUX) || defined(APPLE) -// noting to include -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(WIN32) || defined(WIN64) -#include -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) - #include AZ_RESTRICTED_FILE(CryThreadImpl_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else -// Put other platform specific includes here! -#endif diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h deleted file mode 100644 index 9157bde9bc..0000000000 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ /dev/null @@ -1,78 +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 - -#include -#include // for CreateSemaphore - - -////////////////////////////////////////////////////////////////////////// -// CryLock_WinMutex -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -CryLock_WinMutex::CryLock_WinMutex() - : m_hdl(CreateMutex(NULL, FALSE, NULL)) {} -CryLock_WinMutex::~CryLock_WinMutex() -{ - CloseHandle(m_hdl); -} - -////////////////////////////////////////////////////////////////////////// -void CryLock_WinMutex::Lock() -{ - WaitForSingleObject(m_hdl, INFINITE); -} - -////////////////////////////////////////////////////////////////////////// -void CryLock_WinMutex::Unlock() -{ - ReleaseMutex(m_hdl); -} - -////////////////////////////////////////////////////////////////////////// -bool CryLock_WinMutex::TryLock() -{ - return WaitForSingleObject(m_hdl, 0) != WAIT_TIMEOUT; -} - -////////////////////////////////////////////////////////////////////////// -// CryLock_CritSection -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -CryLock_CritSection::CryLock_CritSection() -{ - InitializeCriticalSection((CRITICAL_SECTION*)&m_cs); -} - -////////////////////////////////////////////////////////////////////////// -CryLock_CritSection::~CryLock_CritSection() -{ - DeleteCriticalSection((CRITICAL_SECTION*)&m_cs); -} - -////////////////////////////////////////////////////////////////////////// -void CryLock_CritSection::Lock() -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_cs); -} - -////////////////////////////////////////////////////////////////////////// -void CryLock_CritSection::Unlock() -{ - LeaveCriticalSection((CRITICAL_SECTION*)&m_cs); -} - -////////////////////////////////////////////////////////////////////////// -bool CryLock_CritSection::TryLock() -{ - return TryEnterCriticalSection((CRITICAL_SECTION*)&m_cs) != FALSE; -} diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h deleted file mode 100644 index 9e04784f3f..0000000000 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ /dev/null @@ -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 - * - */ - - -#pragma once - -#include - - -#include -#include -#include -#include -#include - -#include -#include -#include - -// Section dictionary -#if defined(AZ_RESTRICTED_PLATFORM) -#define CRYTHREAD_PTHREADS_H_SECTION_REGISTER_THREAD 1 -#define CRYTHREAD_PTHREADS_H_SECTION_TRAITS 2 -#define CRYTHREAD_PTHREADS_H_SECTION_PTHREADCOND 3 -#define CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_CONSTRUCT 4 -#define CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_DESTROY 5 -#define CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_ACQUIRE 6 -#define CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_RELEASE 7 -#define CRYTHREAD_PTHREADS_H_SECTION_TRY_RLOCK 8 -#define CRYTHREAD_PTHREADS_H_SECTION_TRY_WLOCK 9 -#define CRYTHREAD_PTHREADS_H_SECTION_START_RUNNABLE 10 -#define CRYTHREAD_PTHREADS_H_SECTION_START_CPUMASK 11 -#define CRYTHREAD_PTHREADS_H_SECTION_START_CPUMASK_POSTCREATE 12 -#define CRYTHREAD_PTHREADS_H_SECTION_SETCPUMASK 13 -#define CRYTHREAD_PTHREADS_H_SECTION_START_RUNNABLE_CPUMASK_POSTCREATE 14 -#endif - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_REGISTER_THREAD - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#endif - -#if defined(APPLE) || defined(ANDROID) -// PTHREAD_MUTEX_FAST_NP is only defined by Pthreads-w32, thus not on MAC - #define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_NORMAL -#endif - -#if !defined _CRYTHREAD_HAVE_LOCK -template -class _PthreadLockBase; - -template -class _PthreadLockAttr -{ - friend class _PthreadLockBase; - -protected: - _PthreadLockAttr() - { - pthread_mutexattr_init(&m_Attr); - pthread_mutexattr_settype(&m_Attr, PthreadMutexType); - } - ~_PthreadLockAttr() - { - pthread_mutexattr_destroy(&m_Attr); - } - pthread_mutexattr_t m_Attr; -}; - -template -class _PthreadLockBase -{ -protected: - static pthread_mutexattr_t& GetAttr() - { - static _PthreadLockAttr m_Attr; - return m_Attr.m_Attr; - } -}; - -template -class _PthreadLock - : public _PthreadLockBase -{ - //#if defined(_DEBUG) -public: - //#endif - pthread_mutex_t m_Lock; - -public: - _PthreadLock() - : LockCount(0) - { - pthread_mutex_init( - &m_Lock, - &_PthreadLockBase::GetAttr()); - } - ~_PthreadLock() { pthread_mutex_destroy(&m_Lock); } - - void Lock() { pthread_mutex_lock(&m_Lock); CryInterlockedIncrement(&LockCount); } - - bool TryLock() - { - const int rc = pthread_mutex_trylock(&m_Lock); - if (0 == rc) - { - CryInterlockedIncrement(&LockCount); - return true; - } - return false; - } - - void Unlock() { CryInterlockedDecrement(&LockCount); pthread_mutex_unlock(&m_Lock); } - - // Get the POSIX pthread_mutex_t. - // Warning: - // This method will not be available in the Win32 port of CryThread. - pthread_mutex_t& Get_pthread_mutex_t() { return m_Lock; } - - bool IsLocked() - { -#if defined(LINUX) || defined(APPLE) - // implementation taken from CrysisWars - return LockCount > 0; -#else - return true; -#endif - } - -private: - volatile int LockCount; -}; - -#if defined CRYLOCK_HAVE_FASTLOCK - #if defined(_DEBUG) && defined(PTHREAD_MUTEX_ERRORCHECK_NP) -template<> -class CryLockT - : public _PthreadLock, PTHREAD_MUTEX_ERRORCHECK_NP> - #else -template<> -class CryLockT - : public _PthreadLock, PTHREAD_MUTEX_FAST_NP> - #endif -{ - CryLockT(const CryLockT&); - void operator = (const CryLockT&); - -public: - CryLockT() { } -}; -#endif // CRYLOCK_HAVE_FASTLOCK - -template<> -class CryLockT - : public _PthreadLock, PTHREAD_MUTEX_RECURSIVE> -{ - CryLockT(const CryLockT&); - void operator = (const CryLockT&); - -public: - CryLockT() { } -}; - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_TRAITS - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#else -#if !defined(LINUX) && !defined(APPLE) -#define CRYTHREAD_PTHREADS_H_TRAIT_DEFINE_CRYMUTEX 1 -#endif -#endif - -#if CRYTHREAD_PTHREADS_H_TRAIT_DEFINE_CRYMUTEX -#if defined CRYLOCK_HAVE_FASTLOCK -class CryMutex - : public CryLockT -{ -}; -#else -class CryMutex - : public CryLockT -{ -}; -#endif -#endif // CRYTHREAD_PTHREADS_TRAIT_DEFINE_CRYMUTEX - -#define _CRYTHREAD_HAVE_LOCK 1 - -#endif // !defined _CRYTHREAD_HAVE_LOCK - -#include "MemoryAccess.h" diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h deleted file mode 100644 index 5f83aa48e0..0000000000 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ /dev/null @@ -1,95 +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 - -#include - -#if defined(AZ_RESTRICTED_PLATFORM) -#undef AZ_RESTRICTED_SECTION -#define CRYTHREAD_WINDOWS_H_SECTION_1 1 -#define CRYTHREAD_WINDOWS_H_SECTION_2 2 -#endif - -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -// from winnt.h -struct CRY_CRITICAL_SECTION -{ - void* DebugInfo; - long LockCount; - long RecursionCount; - threadID OwningThread; - void* LockSemaphore; - unsigned long* SpinCount; // force size on 64-bit systems when packed -}; - -////////////////////////////////////////////////////////////////////////// - -// kernel mutex - don't use... use CryMutex instead -class CryLock_WinMutex -{ -public: - CryLock_WinMutex(); - ~CryLock_WinMutex(); - - void Lock(); - void Unlock(); - bool TryLock(); - - void* _get_win32_handle() { return m_hdl; } - -private: - CryLock_WinMutex(const CryLock_WinMutex&); - CryLock_WinMutex& operator = (const CryLock_WinMutex&); - -private: - void* m_hdl; -}; - -// critical section... don't use... use CryCriticalSection instead -class CryLock_CritSection -{ -public: - CryLock_CritSection(); - ~CryLock_CritSection(); - - void Lock(); - void Unlock(); - bool TryLock(); - - bool IsLocked() - { - return m_cs.RecursionCount > 0 && m_cs.OwningThread == CryGetCurrentThreadId(); - } - -private: - CryLock_CritSection(const CryLock_CritSection&); - CryLock_CritSection& operator = (const CryLock_CritSection&); - -private: - CRY_CRITICAL_SECTION m_cs; -}; - -template <> -class CryLockT - : public CryLock_CritSection -{ -}; -template <> -class CryLockT - : public CryLock_CritSection -{ -}; -class CryMutex - : public CryLock_WinMutex -{ -}; -#define _CRYTHREAD_CONDLOCK_GLITCH 1 diff --git a/Code/Legacy/CryCommon/Synchronization.h b/Code/Legacy/CryCommon/Synchronization.h index 4caa466cb8..3bac215998 100644 --- a/Code/Legacy/CryCommon/Synchronization.h +++ b/Code/Legacy/CryCommon/Synchronization.h @@ -22,7 +22,6 @@ //--------------------------------------------------------------------------- #include "MultiThread.h" -#include "CryThread.h" namespace stl { diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 487d08b13c..d9d4493632 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -89,8 +89,6 @@ set(FILES CrySizer.h CryString.h CrySystemBus.h - CryThread.h - CryThreadImpl.h CryTypeInfo.h CryVersion.h FrameProfiler.h @@ -160,9 +158,6 @@ set(FILES CryAssert_Mac.h CryLibrary.cpp CryLibrary.h - CryThread_pthreads.h - CryThread_windows.h - CryThreadImpl_windows.h CryWindows.h Linux32Specific.h Linux64Specific.h diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 851da316e0..9f6e8b212d 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -732,7 +732,6 @@ typedef int socklen_t; // Include MultiThreading support. -#include "CryThread.h" #include "MultiThread.h" // In RELEASE disable printf and fprintf diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index 09d7493ae7..e16b18bc06 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -38,10 +38,6 @@ struct SSystemGlobalEnvironment* gEnv = nullptr; #include AZ_RESTRICTED_FILE(platform_impl_h) #endif -////////////////////////////////////////////////////////////////////////// -// If not in static library. -#include - #if defined(WIN32) || defined(WIN64) void CryPureCallHandler() { diff --git a/Code/Legacy/CrySystem/Log.h b/Code/Legacy/CrySystem/Log.h index d6b6dcea3e..447186e613 100644 --- a/Code/Legacy/CrySystem/Log.h +++ b/Code/Legacy/CrySystem/Log.h @@ -10,7 +10,6 @@ #pragma once #include -#include #include #include diff --git a/Code/Legacy/CrySystem/SystemEventDispatcher.h b/Code/Legacy/CrySystem/SystemEventDispatcher.h index a5d33b2542..550292add7 100644 --- a/Code/Legacy/CrySystem/SystemEventDispatcher.h +++ b/Code/Legacy/CrySystem/SystemEventDispatcher.h @@ -14,6 +14,7 @@ #include #include +#include class CSystemEventDispatcher : public ISystemEventDispatcher From adf7a34ef58196fac2863509d35077efb19a050e Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Tue, 10 Aug 2021 23:07:23 -0700 Subject: [PATCH 022/101] Got PassBuilder shader dependency working and removed critical flag from shader builder Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Editor/ShaderVariantAssetBuilder.cpp | 2 +- .../AuxGeom/DynamicPrimitiveProcessor.cpp | 2 +- .../Source/AuxGeom/FixedShapeProcessor.cpp | 4 +- .../DiffuseProbeGridBlendDistancePass.cpp | 2 +- .../DiffuseProbeGridBlendIrradiancePass.cpp | 2 +- .../DiffuseProbeGridBorderUpdatePass.cpp | 2 +- .../DiffuseProbeGridClassificationPass.cpp | 2 +- .../DiffuseProbeGridFeatureProcessor.cpp | 2 +- .../DiffuseProbeGridRayTracingPass.cpp | 6 +- .../DiffuseProbeGridRelocationPass.cpp | 2 +- .../DiffuseProbeGridRenderPass.cpp | 2 +- .../Common/Code/Source/ImGui/ImGuiPass.cpp | 2 +- .../ReflectionProbeFeatureProcessor.cpp | 2 +- .../ReflectionScreenSpaceBlurPass.cpp | 4 +- .../Code/Include/Atom/RPI.Public/RPIUtils.h | 4 +- .../Source/RPI.Builders/Pass/PassBuilder.cpp | 127 +++++++----------- .../RPI.Public/Pass/AttachmentReadback.cpp | 2 +- .../RPI/Code/Source/RPI.Public/RPIUtils.cpp | 28 +++- Gems/LyShine/Code/Source/Draw2d.cpp | 2 +- Gems/LyShine/Code/Source/UiRenderer.cpp | 2 +- 20 files changed, 103 insertions(+), 98 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index ee02ae8452..1da4623774 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -321,7 +321,7 @@ namespace AZ AssetBuilderSDK::JobDescriptor jobDescriptor; jobDescriptor.m_priority = -5000; - jobDescriptor.m_critical = true; + jobDescriptor.m_critical = false; jobDescriptor.m_jobKey = ShaderVariantAssetBuilderJobKey; jobDescriptor.SetPlatformIdentifier(info.m_identifier.data()); diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp index ea726dd914..3a7d50d2a9 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp @@ -322,7 +322,7 @@ namespace AZ { const char* auxGeomWorldShaderFilePath = "Shaders/auxgeom/auxgeomworld.azshader"; - m_shader = RPI::LoadShader(auxGeomWorldShaderFilePath); + m_shader = RPI::LoadCriticalShader(auxGeomWorldShaderFilePath); if (!m_shader) { AZ_Error("DynamicPrimitiveProcessor", false, "Failed to get shader"); diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp index 63feee115d..f2b3a93a53 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp @@ -1385,9 +1385,9 @@ namespace AZ const char* litObjectShaderFilePath = "Shaders/auxgeom/auxgeomobjectlit.azshader"; // constant color shader - m_unlitShader = RPI::LoadShader(unlitObjectShaderFilePath); + m_unlitShader = RPI::LoadCriticalShader(unlitObjectShaderFilePath); // direction light shader - m_litShader = RPI::LoadShader(litObjectShaderFilePath); + m_litShader = RPI::LoadCriticalShader(litObjectShaderFilePath); if (m_unlitShader.get() == nullptr || m_litShader == nullptr) { diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp index 5fe472c7f8..a3927b802d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp @@ -38,7 +38,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistance.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp index c1b6653024..6ff8bdd867 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp @@ -38,7 +38,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiance.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp index 0d47b3bd54..ddfe0f11b1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp @@ -51,7 +51,7 @@ namespace AZ { // load shader // Note: the shader may not be available on all platforms - shader = RPI::LoadShader(shaderFilePath); + shader = RPI::LoadCriticalShader(shaderFilePath); if (shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp index bb7f87cc61..4c6b07d780 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp @@ -42,7 +42,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridClassification.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp index f4df4f126a..378e1923f7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp @@ -74,7 +74,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms - Data::Instance shader = RPI::LoadShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader"); + Data::Instance shader = RPI::LoadCriticalShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader"); if (shader) { m_probeGridRenderData.m_drawListTag = shader->GetDrawListTag(); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp index dd8985935f..958823ef91 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp @@ -52,7 +52,7 @@ namespace AZ // load the ray tracing shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracing.azshader"; - m_rayTracingShader = RPI::LoadShader(shaderFilePath); + m_rayTracingShader = RPI::LoadCriticalShader(shaderFilePath); if (m_rayTracingShader == nullptr) { return; @@ -64,7 +64,7 @@ namespace AZ // closest hit shader AZStd::string closestHitShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingClosestHit.azshader"; - m_closestHitShader = RPI::LoadShader(closestHitShaderFilePath); + m_closestHitShader = RPI::LoadCriticalShader(closestHitShaderFilePath); auto closestHitShaderVariant = m_closestHitShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); RHI::PipelineStateDescriptorForRayTracing closestHitShaderDescriptor; @@ -72,7 +72,7 @@ namespace AZ // miss shader AZStd::string missShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingMiss.azshader"; - m_missShader = RPI::LoadShader(missShaderFilePath); + m_missShader = RPI::LoadCriticalShader(missShaderFilePath); auto missShaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp index 56ae50069e..54cf9783cd 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp @@ -42,7 +42,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRelocation.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp index 55d8ca5cba..a4cc101222 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp @@ -30,7 +30,7 @@ namespace AZ // create the shader resource group // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp index 821b9c52b4..cd781390a3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp @@ -446,7 +446,7 @@ namespace AZ } { - m_shader = RPI::LoadShader(ImguiShaderFilePath); + m_shader = RPI::LoadCriticalShader(ImguiShaderFilePath); m_pipelineState = aznew RPI::PipelineStateForDraw; m_pipelineState->Init(m_shader); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index a9078e1dd8..c0e25e3da9 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -487,7 +487,7 @@ namespace AZ RHI::DrawListTag& drawListTag) { // load shader - shader = RPI::LoadShader(filePath); + shader = RPI::LoadCriticalShader(filePath); AZ_Error("ReflectionProbeFeatureProcessor", shader, "Failed to find asset for shader [%s]", filePath); // store drawlist tag diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp index f0f947ba03..4f5caca108 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp @@ -52,7 +52,7 @@ namespace AZ // load shaders AZStd::string verticalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurVertical.azshader"; - Data::Instance verticalBlurShader = RPI::LoadShader(verticalBlurShaderFilePath); + Data::Instance verticalBlurShader = RPI::LoadCriticalShader(verticalBlurShaderFilePath); if (verticalBlurShader == nullptr) { AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), verticalBlurShaderFilePath.c_str()); @@ -60,7 +60,7 @@ namespace AZ } AZStd::string horizontalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.azshader"; - Data::Instance horizontalBlurShader = RPI::LoadShader(horizontalBlurShaderFilePath); + Data::Instance horizontalBlurShader = RPI::LoadCriticalShader(horizontalBlurShaderFilePath); if (horizontalBlurShader == nullptr) { AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), horizontalBlurShaderFilePath.c_str()); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h index e6d2bdad82..a2972ff0fd 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h @@ -22,19 +22,21 @@ namespace AZ class Shader; //! Get the asset ID for a given shader file path - Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath); + Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath, bool isCritical = false); //! Finds a shader asset for the given shader asset ID. Optional shaderFilePath param for debugging. Data::Asset FindShaderAsset(Data::AssetId shaderAssetId, const AZStd::string& shaderFilePath = ""); //! Finds a shader asset for the given shader file path Data::Asset FindShaderAsset(const AZStd::string& shaderFilePath); + Data::Asset FindCriticalShaderAsset(const AZStd::string& shaderFilePath); //! Loads a shader for the given shader asset ID. Optional shaderFilePath param for debugging. Data::Instance LoadShader(Data::AssetId shaderAssetId, const AZStd::string& shaderFilePath = ""); //! Loads a shader for the given shader file path Data::Instance LoadShader(const AZStd::string& shaderFilePath); + Data::Instance LoadCriticalShader(const AZStd::string& shaderFilePath); //! Loads a streaming image asset for the given file path Data::Instance LoadStreamingTexture(AZStd::string_view path); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index f582f3ba04..a803ecf31a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -67,6 +67,7 @@ namespace AZ // --- Code related to dependency shader asset handling --- + // Helper class to pass parameters to the AddDependency and FindReferencedAssets functions below struct FindPassReferenceAssetParams { void* passAssetObject; @@ -77,50 +78,28 @@ namespace AZ const char* jobKey; // Job key for adding job dependency }; - //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. - //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. - //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back - //! to the AssetBuilderSDK::CreateJobsResponse. - void AddPossibleDependencies( - FindPassReferenceAssetParams& params, - AssetBuilderSDK::CreateJobsResponse& response, - AssetBuilderSDK::JobDescriptor& job) + // Helper function to get a file reference and create a corresponding job dependency + void AddDependency(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) { - bool dependencyFileFound = false; + AZStd::string_view& file = params.dependencySourceFile; + AZ::Data::AssetInfo sourceInfo; + AZStd::string watchFolder; + bool fileFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.data(), sourceInfo, watchFolder); - AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(params.passAssetSourceFile, params.dependencySourceFile); - for (auto& file : possibleDependencies) + if (fileFound) { - AssetBuilderSDK::SourceFileDependency sourceFileDependency; - sourceFileDependency.m_sourceFileDependencyPath = file; - response.m_sourceFileDependencyList.push_back(sourceFileDependency); - - // The first path found is the highest priority, and will have a job dependency, as this is the one - // the builder will actually use - if (!dependencyFileFound) - { - AZ::Data::AssetInfo sourceInfo; - AZStd::string watchFolder; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(dependencyFileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.c_str(), sourceInfo, watchFolder); - - if (dependencyFileFound) - { - AssetBuilderSDK::JobDependency jobDependency; - jobDependency.m_jobKey = params.jobKey; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; - jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; - job.m_jobDependencyList.push_back(jobDependency); - } - } + AssetBuilderSDK::JobDependency jobDependency; + jobDependency.m_jobKey = params.jobKey; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; + job->m_jobDependencyList.push_back(jobDependency); + AZ_TracePrintf(PassBuilderName, "Creating job dependency on file [%s] \n", file.data()); } } // Helper function to find all assetId's and object references - bool FindPassReferencedAssets(FindPassReferenceAssetParams& params, - AZStd::unordered_set& referencedAssetList, - AssetBuilderSDK::CreateJobsResponse& response, - AssetBuilderSDK::JobDescriptor& job, - bool jobCreationPhase) + bool FindReferencedAssets(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) { SerializeContext::ErrorHandler errorLogger; errorLogger.Reset(); @@ -141,10 +120,10 @@ namespace AZ const AZStd::string& path = assetReference->m_filePath; uint32_t subId = 0; - if (jobCreationPhase) + if (job != nullptr) // Create Job Phase { params.dependencySourceFile = path; - AddPossibleDependencies(params, response, job); + AddDependency(params, job); } else // Process Job Phase { @@ -161,12 +140,6 @@ namespace AZ } } } - - // If the asset ID is valid, add it as a dependency - if (assetReference->m_assetId.IsValid()) - { - referencedAssetList.insert(assetReference->m_assetId); - } } return true; }; @@ -196,15 +169,16 @@ namespace AZ void PassBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const { + // --- Handle shutdown case --- + if (m_isShuttingDown) { response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown; return; } - AssetBuilderSDK::JobDescriptor job; + // --- Get serialization context --- - // Get serialization context SerializeContext* serializeContext = nullptr; ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext); if (!serializeContext) @@ -213,7 +187,8 @@ namespace AZ return; } - // Load PassAsset + // --- Load PassAsset --- + AZStd::string fullPath; AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.c_str(), request.m_sourceFile.c_str(), fullPath, true); @@ -227,7 +202,12 @@ namespace AZ return; } - // Find all Asset IDs we depend on + AssetBuilderSDK::JobDescriptor job; + job.m_jobKey = PassBuilderJobKey; + job.m_critical = true; // Passes are a critical part of the rendering system + + // --- Find all dependencies --- + AZStd::unordered_set dependentList; Uuid passAssetUuid = AzTypeInfo::Uuid(); @@ -238,30 +218,30 @@ namespace AZ params.serializeContext = serializeContext; params.jobKey = "Shader Asset"; - if (!FindPassReferencedAssets(params, dependentList, response, job, true)) + if (!FindReferencedAssets(params, &job)) { return; } + // --- Create a job per platform --- + for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms) { - job.m_jobKey = PassBuilderJobKey; + for (auto& jobDependency : job.m_jobDependencyList) + { + jobDependency.m_platformIdentifier = platformInfo.m_identifier.c_str(); + } job.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); - - // Passes are a critical part of the rendering system - job.m_critical = true; - response.m_createJobOutputs.push_back(job); } response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; } - - void PassBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const { - // Handle job cancellation and shutdown cases + // --- Handle job cancellation and shutdown cases --- + AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId); if (jobCancelListener.IsCancelled() || m_isShuttingDown) { @@ -269,7 +249,8 @@ namespace AZ return; } - // Get serialization context + // --- Get serialization context --- + SerializeContext* serializeContext = nullptr; ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext); if (!serializeContext) @@ -278,7 +259,8 @@ namespace AZ return; } - // Load PassAsset + // --- Load PassAsset --- + PassAsset passAsset; AZ::Outcome loadResult = JsonSerializationUtils::LoadObjectFromFile(passAsset, request.m_fullPath); @@ -289,8 +271,8 @@ namespace AZ return; } - // Find all Asset IDs we depend on - AZStd::unordered_set dependentList; + // --- Find all dependencies --- + Uuid passAssetUuid = AzTypeInfo::Uuid(); FindPassReferenceAssetParams params; @@ -300,21 +282,20 @@ namespace AZ params.serializeContext = serializeContext; params.jobKey = "Shader Asset"; - AssetBuilderSDK::CreateJobsResponse dummyResponse; - AssetBuilderSDK::JobDescriptor dummyJob; - - if (!FindPassReferencedAssets(params, dependentList, dummyResponse, dummyJob, false)) + if (!FindReferencedAssets(params, nullptr)) { return; } - // Get destination file name and path + // --- Get destination file name and path --- + AZStd::string destFileName; AZStd::string destPath; AzFramework::StringFunc::Path::GetFullFileName(request.m_fullPath.c_str(), destFileName); AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), destFileName.c_str(), destPath, true); - // Save the asset to binary format for production + // --- Save the asset to binary format for production --- + bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, &passAsset, passAssetUuid, serializeContext); if (result == false) { @@ -322,14 +303,10 @@ namespace AZ return; } - // Success. Save output product(s) to response - AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0); - for (auto& assetId : dependentList) - { - jobProduct.m_dependencies.emplace_back(AssetBuilderSDK::ProductDependency(assetId, 0)); - } + // --- Save output product(s) to response --- - jobProduct.m_dependenciesHandled = true; // We've output the dependencies immediately above so it's OK to tell the AP we've handled dependencies + AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0); + jobProduct.m_dependenciesHandled = true; response.m_outputProducts.push_back(jobProduct); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp index 29a17dc9a8..29af8b7b63 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp @@ -121,7 +121,7 @@ namespace AZ // Load shader and srg const char* ShaderPath = "shader/decomposemsimage.azshader"; - m_decomposeShader = LoadShader(ShaderPath); + m_decomposeShader = LoadCriticalShader(ShaderPath); if (m_decomposeShader == nullptr) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp index ebccc87cac..9173b47fad 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -20,7 +21,7 @@ namespace AZ namespace RPI { - Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath) + Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath, bool isCritical) { Data::AssetId shaderAssetId; @@ -34,6 +35,19 @@ namespace AZ if (!shaderAssetId.IsValid()) { + if (isCritical) + { + Data::Asset shaderAsset = RPI::AssetUtils::LoadCriticalAsset(shaderFilePath); + if (shaderAsset.IsReady()) + { + return shaderAsset.GetId(); + } + else + { + AZ_Error("RPI Utils", false, "Could not load critical shader [%s]", shaderFilePath.c_str()); + } + } + AZ_Error("RPI Utils", false, "Failed to get asset id for shader [%s]", shaderFilePath.c_str()); } @@ -83,11 +97,23 @@ namespace AZ return FindShaderAsset(GetShaderAssetId(shaderFilePath), shaderFilePath); } + Data::Asset FindCriticalShaderAsset(const AZStd::string& shaderFilePath) + { + const bool isCritical = true; + return FindShaderAsset(GetShaderAssetId(shaderFilePath, isCritical), shaderFilePath); + } + Data::Instance LoadShader(const AZStd::string& shaderFilePath) { return LoadShader(GetShaderAssetId(shaderFilePath), shaderFilePath); } + Data::Instance LoadCriticalShader(const AZStd::string& shaderFilePath) + { + const bool isCritical = true; + return LoadShader(GetShaderAssetId(shaderFilePath, isCritical), shaderFilePath); + } + AZ::Data::Instance LoadStreamingTexture(AZStd::string_view path) { AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index 2d3612fc07..b4c8d58fae 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/Gems/LyShine/Code/Source/Draw2d.cpp @@ -79,7 +79,7 @@ void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapSc // Load the shader to be used for 2d drawing const char* shaderFilepath = "Shaders/SimpleTextured.azshader"; - AZ::Data::Instance shader = AZ::RPI::LoadShader(shaderFilepath); + AZ::Data::Instance shader = AZ::RPI::LoadCriticalShader(shaderFilepath); // Set scene to be associated with the dynamic draw context AZ::RPI::ScenePtr scene; diff --git a/Gems/LyShine/Code/Source/UiRenderer.cpp b/Gems/LyShine/Code/Source/UiRenderer.cpp index 357431c80a..c52c249d20 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.cpp +++ b/Gems/LyShine/Code/Source/UiRenderer.cpp @@ -58,7 +58,7 @@ void UiRenderer::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstra // Load the UI shader const char* uiShaderFilepath = "Shaders/LyShineUI.azshader"; - AZ::Data::Instance uiShader = AZ::RPI::LoadShader(uiShaderFilepath); + AZ::Data::Instance uiShader = AZ::RPI::LoadCriticalShader(uiShaderFilepath); // Create scene to be used by the dynamic draw context if (m_viewportContext) From 39d56a8834c7aa08db5b0c7ac1b2b507bedf40f8 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Wed, 11 Aug 2021 10:45:48 -0700 Subject: [PATCH 023/101] Removing product dependency check from pass builder test since shaders references are now registered as a job dependency and not a product dependency Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp b/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp index ad1df41824..4e088cece5 100644 --- a/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp +++ b/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp @@ -112,9 +112,6 @@ namespace UnitTest EXPECT_TRUE(response.m_resultCode == AssetBuilderSDK::ProcessJobResult_Success); EXPECT_TRUE(response.m_outputProducts.size() == 1); - // Verify the dependency was registered - EXPECT_TRUE(response.m_outputProducts[0].m_dependencies.size() == 1); - // Verify input and output names are the same Data::Asset readAsset = LoadAssetFromFile(response.m_outputProducts[0].m_productFileName.c_str()); RPI::PassAsset* readPassAsset = static_cast(readAsset.GetData()); From f1e8d37b86cc0eadad974a77c8e128af5317f1ba Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 11 Aug 2021 14:55:28 -0500 Subject: [PATCH 024/101] holding pen for refactor Signed-off-by: Guthrie Adams --- .../Window/AtomToolsMainWindow.h | 5 +- .../Code/Source/AtomToolsFrameworkModule.cpp | 7 +- .../Source/Window/AtomToolsMainWindow.cpp | 18 +- .../AtomToolsMainWindowSystemComponent.cpp | 73 +++++++ .../AtomToolsMainWindowSystemComponent.h | 36 ++++ .../Code/atomtoolsframework_files.cmake | 2 + .../MaterialDocumentNotificationBus.h | 48 ++--- .../Document/MaterialDocumentRequestBus.h | 32 +-- .../MaterialDocumentSystemRequestBus.h | 40 ++-- .../MaterialDocumentSystemComponent.cpp | 66 +++--- .../Source/Window/MaterialEditorWindow.cpp | 53 ++--- .../Window/MaterialEditorWindowComponent.cpp | 35 +--- .../Scripts/GenerateAllMaterialScreenshots.py | 7 +- ...ManagementConsoleDocumentNotificationBus.h | 27 +++ ...haderManagementConsoleDocumentRequestBus.h | 9 +- ...anagementConsoleDocumentSystemRequestBus.h | 11 +- .../ShaderManagementConsoleDocument.cpp | 67 ++++-- .../ShaderManagementConsoleDocument.h | 8 +- ...nagementConsoleDocumentSystemComponent.cpp | 136 ++++++++---- ...ManagementConsoleDocumentSystemComponent.h | 8 +- .../Window/ShaderManagementConsoleWindow.cpp | 198 ++++++++++-------- .../Window/ShaderManagementConsoleWindow.h | 7 +- ...ShaderManagementConsoleWindowComponent.cpp | 19 +- 23 files changed, 569 insertions(+), 343 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index 82444246fd..751b30a907 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -16,8 +16,8 @@ #include #include +#include #include -#include #include namespace AtomToolsFramework @@ -53,10 +53,9 @@ namespace AtomToolsFramework virtual void SelectNextTab(); AzQtComponents::FancyDocking* m_advancedDockManager = nullptr; - QWidget* m_centralWidget = nullptr; QMenuBar* m_menuBar = nullptr; AzQtComponents::TabWidget* m_tabWidget = nullptr; - QStatusBar* m_statusBar = nullptr; + QLabel* m_statusMessage = nullptr; AZStd::unordered_map m_dockWidgets; }; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp index bee27dfdca..b601596032 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp @@ -8,20 +8,23 @@ #include #include +#include namespace AtomToolsFramework { AtomToolsFrameworkModule::AtomToolsFrameworkModule() { m_descriptors.insert(m_descriptors.end(), { - AtomToolsFrameworkSystemComponent::CreateDescriptor(), - }); + AtomToolsFrameworkSystemComponent::CreateDescriptor(), + AtomToolsMainWindowSystemComponent::CreateDescriptor(), + }); } AZ::ComponentTypeList AtomToolsFrameworkModule::GetRequiredSystemComponents() const { return AZ::ComponentTypeList{ azrtti_typeid(), + azrtti_typeid(), }; } } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index f6e56b1ff6..55bec32dc7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -7,6 +7,8 @@ */ #include +#include +#include namespace AtomToolsFramework { @@ -21,11 +23,15 @@ namespace AtomToolsFramework setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - m_statusBar = new QStatusBar(this); - m_statusBar->setObjectName("StatusBar"); - statusBar()->addPermanentWidget(m_statusBar, 1); + m_statusMessage = new QLabel(statusBar()); + statusBar()->addPermanentWidget(m_statusMessage, 1); - m_centralWidget = new QWidget(this); + auto centralWidget = new QWidget(this); + auto centralWidgetLayout = new QVBoxLayout(centralWidget); + centralWidgetLayout->setMargin(0); + centralWidgetLayout->setContentsMargins(0, 0, 0, 0); + centralWidget->setLayout(centralWidgetLayout); + setCentralWidget(centralWidget); AtomToolsMainWindowRequestBus::Handler::BusConnect(); } @@ -111,7 +117,7 @@ namespace AtomToolsFramework void AtomToolsMainWindow::CreateTabBar() { - m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget); + m_tabWidget = new AzQtComponents::TabWidget(centralWidget()); m_tabWidget->setObjectName("TabWidget"); m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); m_tabWidget->setContentsMargins(0, 0, 0, 0); @@ -131,6 +137,8 @@ namespace AtomToolsFramework { OpenTabContextMenu(); }); + + centralWidget()->layout()->addWidget(m_tabWidget); } void AtomToolsMainWindow::AddTabForDocumentId( diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp new file mode 100644 index 0000000000..3114a5d9f7 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp @@ -0,0 +1,73 @@ +/* + * 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 +#include +#include +#include +#include +#include + +namespace AtomToolsFramework +{ + void AtomToolsMainWindowSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class() + ->Version(0); + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->EBus("AtomToolsMainWindowFactoryRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("CreateMainWindow", &AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) + ->Event("DestroyMainWindow", &AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) + ; + + behaviorContext->EBus("AtomToolsMainWindowRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("ActivateWindow", &AtomToolsMainWindowRequestBus::Events::ActivateWindow) + ->Event("SetDockWidgetVisible", &AtomToolsMainWindowRequestBus::Events::SetDockWidgetVisible) + ->Event("IsDockWidgetVisible", &AtomToolsMainWindowRequestBus::Events::IsDockWidgetVisible) + ->Event("GetDockWidgetNames", &AtomToolsMainWindowRequestBus::Events::GetDockWidgetNames) + ->Event("ResizeViewportRenderTarget", &AtomToolsMainWindowRequestBus::Events::ResizeViewportRenderTarget) + ->Event("LockViewportRenderTargetSize", &AtomToolsMainWindowRequestBus::Events::LockViewportRenderTargetSize) + ->Event("UnlockViewportRenderTargetSize", &AtomToolsMainWindowRequestBus::Events::UnlockViewportRenderTargetSize) + ; + } + } + + void AtomToolsMainWindowSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); + } + + void AtomToolsMainWindowSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); + } + + void AtomToolsMainWindowSystemComponent::Init() + { + } + + void AtomToolsMainWindowSystemComponent::Activate() + { + } + + void AtomToolsMainWindowSystemComponent::Deactivate() + { + } + +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h new file mode 100644 index 0000000000..b982327326 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h @@ -0,0 +1,36 @@ +/* + * 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 + +namespace AtomToolsFramework +{ + //! AtomToolsMainWindowSystemComponent is used for initialization and registration of other classes. + class AtomToolsMainWindowSystemComponent + : public AZ::Component + { + public: + AZ_COMPONENT(AtomToolsMainWindowSystemComponent, "{6E42380B-4ECD-47CF-B904-E16AB4E87D0D}"); + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + private: + + //////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Init() override; + void Activate() override; + void Deactivate() override; + //////////////////////////////////////////////////////////////////////// + }; +} diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 49e641eb9c..8eb82778e3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -45,4 +45,6 @@ set(FILES Source/Viewport/RenderViewportWidget.cpp Source/Viewport/ModularViewportCameraController.cpp Source/Window/AtomToolsMainWindow.cpp + Source/Window/AtomToolsMainWindowSystemComponent.cpp + Source/Window/AtomToolsMainWindowSystemComponent.h ) \ No newline at end of file diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h index aafd0a0a57..963a348697 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h @@ -25,58 +25,58 @@ namespace MaterialEditor static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - //! Signal that a material document was created - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was created + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentCreated([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was destroyed - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was destroyed + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentDestroyed([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was opened - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was opened + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentOpened([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was closed - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was closed + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentClosed([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was saved - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was saved + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentSaved([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was selected - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was selected + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentSelected([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was modified - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was modified + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentModified([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document dependency was modified - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document dependency was modified + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentDependencyModified([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was modified externally - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was modified externally + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentExternallyModified([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document undo state was updated - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document undo state was updated + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentUndoStateChanged([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material property changed - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a property changed + //! @param documentId unique id of document for which the notification is sent //! @param property object containing the property value and configuration that was modified virtual void OnDocumentPropertyValueModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} //! Signal that the property configuration has been changed. - //! @param documentId unique id of material document for which the notification is sent + //! @param documentId unique id of document for which the notification is sent //! @param property object containing the property value and configuration that was modified virtual void OnDocumentPropertyConfigModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} //! Signal that the property group visibility has been changed. - //! @param documentId unique id of material document for which the notification is sent + //! @param documentId unique id of document for which the notification is sent //! @param groupId id of the group that changed //! @param visible whether the property group is visible virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h index f81476a3a9..23b5749554 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h @@ -39,10 +39,10 @@ namespace MaterialEditor static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; typedef AZ::Uuid BusIdType; - //! Get absolute path of material source file + //! Get absolute path of document virtual AZStd::string_view GetAbsolutePath() const = 0; - //! Get relative path of material source file + //! Get relative path of document virtual AZStd::string_view GetRelativePath() const = 0; //! Get material asset created by MaterialDocument @@ -72,52 +72,52 @@ namespace MaterialEditor //! Modify material property value virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0; - //! Load source material and related data - //! @param loadPath Absolute path of material to load + //! Load document and related data + //! @param loadPath Absolute path of document to load virtual bool Open(AZStd::string_view loadPath) = 0; //! Reload document preserving edits virtual bool Rebuild() = 0; - //! Save material to source file + //! Save document to file virtual bool Save() = 0; - //! Save material to a new source file - //! @param savePath Absolute path where material is saved + //! Save document copy + //! @param savePath Absolute path where document is saved virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; //! Save material to a new source file as a child of the open material //! @param savePath Absolute path where material is saved virtual bool SaveAsChild(AZStd::string_view savePath) = 0; - //! Close material document and reset its data + //! Close document and reset its data virtual bool Close() = 0; - //! Material is loaded + //! document is loaded virtual bool IsOpen() const = 0; - //! Material has changes pending + //! document has changes pending virtual bool IsModified() const = 0; //! Can the document be saved virtual bool IsSavable() const = 0; - //! Returns true if there are reversible modifications to the material document + //! Returns true if there are reversible modifications to the document virtual bool CanUndo() const = 0; - //! Returns true if there are changes that were reversed and can be re-applied to the material document + //! Returns true if there are changes that were reversed and can be re-applied to the document virtual bool CanRedo() const = 0; - //! Restores the previous state of the material document + //! Restores the previous state of the document virtual bool Undo() = 0; - //! Restores the next state of the material document + //! Restores the next state of the document virtual bool Redo() = 0; - //! Signal that property editing is about to begin, like beginning to drag a slider control + //! Signal that editing is about to begin, like beginning to drag a slider control virtual bool BeginEdit() = 0; - //! Signal that property editing has completed, like after releasing the mouse button after continuously dragging a slider control + //! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control virtual bool EndEdit() = 0; }; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h index 18534b3d2d..47fa5dab85 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h @@ -23,53 +23,53 @@ namespace MaterialEditor static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - //! Create a material document object - //! @return Uuid of new material document, or null Uuid if failed + //! Create a document object + //! @return Uuid of new document, or null Uuid if failed virtual AZ::Uuid CreateDocument() = 0; - //! Destroy a material document object with the specified id + //! Destroy a document object with the specified id //! @return true if Uuid was found and removed, otherwise false virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0; - //! Open a material document for editing - //! @param sourcePath material document to open. - //! @return unique id of new material document if successful, otherwise null Uuid + //! Open a document for editing + //! @param sourcePath document to open. + //! @return unique id of new document if successful, otherwise null Uuid virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0; //! Create a new document by specifying a source and prompting the user for destination path. //! If the source file is a material type then this results in creating a new material based on that type. //! If the source file is a material this results in creating a child material with the source file as its parent. - //! @param sourcePath material document to open. + //! @param sourcePath document to open. //! @param targetPath location where document is saved. - //! @return unique id of new material document if successful, otherwise null Uuid + //! @return unique id of new document if successful, otherwise null Uuid virtual AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) = 0; - //! Close the specified material document - //! @param documentId unique id of material document to close + //! Close the specified document + //! @param documentId unique id of document to close virtual bool CloseDocument(const AZ::Uuid& documentId) = 0; - //! Close all material documents + //! Close all documents virtual bool CloseAllDocuments() = 0; - //! Close all material documents except for documentId - //! @param documentId unique id of material document to not close + //! Close all documents except for documentId + //! @param documentId unique id of document to not close virtual bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) = 0; - //! Save the specified material document - //! @param documentId unique id of material document to save + //! Save the specified document + //! @param documentId unique id of document to save virtual bool SaveDocument(const AZ::Uuid& documentId) = 0; - //! Save the specified material document to a different file - //! @param documentId unique id of material document to save + //! Save the specified document to a different file + //! @param documentId unique id of document to save //! @param targetPath location where document is saved. virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; - //! Save the specified material document to a different file, referencing the original material as its parent - //! @param documentId unique id of material document to save + //! Save the specified document to a different file, referencing the original material as its parent + //! @param documentId unique id of document to save //! @param targetPath location where document is saved. virtual bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; - //! Save all material documents + //! Save all documents virtual bool SaveAllDocuments() = 0; }; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp index e4a3b8235d..3ecabaabcc 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp @@ -189,7 +189,7 @@ namespace MaterialEditor if (m_settings->m_showReloadDocumentPrompt && (QMessageBox::question(QApplication::activeWindow(), - QString("Material document was externally modified"), + QString("Document was externally modified"), QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) { @@ -203,7 +203,7 @@ namespace MaterialEditor if (!openResult) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be opened"), + QApplication::activeWindow(), QString("Document could not be opened"), QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } @@ -216,7 +216,7 @@ namespace MaterialEditor if (m_settings->m_showReloadDocumentPrompt && (QMessageBox::question(QApplication::activeWindow(), - QString("Material document dependencies have changed"), + QString("Document dependencies have changed"), QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) { @@ -230,7 +230,7 @@ namespace MaterialEditor if (!openResult) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be opened"), + QApplication::activeWindow(), QString("Document could not be opened"), QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } @@ -284,7 +284,7 @@ namespace MaterialEditor if (isModified) { auto selection = QMessageBox::question(QApplication::activeWindow(), - QString("Material document has unsaved changes"), + QString("Document has unsaved changes"), QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); if (selection == QMessageBox::Cancel) @@ -309,7 +309,7 @@ namespace MaterialEditor if (!closeResult) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be closed"), + QApplication::activeWindow(), QString("Document could not be closed"), QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -353,18 +353,18 @@ namespace MaterialEditor bool MaterialDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) { - AZStd::string saveMaterialPath; - MaterialDocumentRequestBus::EventResult(saveMaterialPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string saveDocumentPath; + MaterialDocumentRequestBus::EventResult(saveDocumentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath)) + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } - const QFileInfo saveInfo(saveMaterialPath.c_str()); + const QFileInfo saveInfo(saveDocumentPath.c_str()); if (saveInfo.exists() && !saveInfo.isWritable()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); return false; } @@ -375,8 +375,8 @@ namespace MaterialEditor if (!result) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -385,28 +385,28 @@ namespace MaterialEditor bool MaterialDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) { - AZStd::string saveMaterialPath = targetPath; - if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath)) + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } - const QFileInfo saveInfo(saveMaterialPath.c_str()); + const QFileInfo saveInfo(saveDocumentPath.c_str()); if (saveInfo.exists() && !saveInfo.isWritable()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); return false; } AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveMaterialPath); + MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); if (!result) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -415,28 +415,28 @@ namespace MaterialEditor bool MaterialDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) { - AZStd::string saveMaterialPath = targetPath; - if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath)) + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } - const QFileInfo saveInfo(saveMaterialPath.c_str()); + const QFileInfo saveInfo(saveDocumentPath.c_str()); if (saveInfo.exists() && !saveInfo.isWritable()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); return false; } AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveMaterialPath); + MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveDocumentPath); if (!result) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -467,7 +467,7 @@ namespace MaterialEditor if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document path is invalid:\n%1").arg(requestedPath.c_str())); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); return AZ::Uuid::CreateNull(); } @@ -476,9 +476,9 @@ namespace MaterialEditor { for (const auto& documentPair : m_documentMap) { - AZStd::string openMaterialPath; - MaterialDocumentRequestBus::EventResult(openMaterialPath, documentPair.first, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - if (openMaterialPath == requestedPath) + AZStd::string openDocumentPath; + MaterialDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + if (openDocumentPath == requestedPath) { MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); return documentPair.first; @@ -493,7 +493,7 @@ namespace MaterialEditor if (documentId.IsNull()) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be created"), + QApplication::activeWindow(), QString("Document could not be created"), QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); return AZ::Uuid::CreateNull(); } @@ -505,7 +505,7 @@ namespace MaterialEditor if (!openResult) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be opened"), + QApplication::activeWindow(), QString("Document could not be opened"), QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); return AZ::Uuid::CreateNull(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index f4dfa3df1b..52ce217834 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -36,8 +36,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include -#include -#include #include AZ_POP_DISABLE_WARNING @@ -77,20 +75,13 @@ namespace MaterialEditor m_toolBar->setObjectName("ToolBar"); addToolBar(m_toolBar); - m_materialViewport = new MaterialViewportWidget(m_centralWidget); - m_materialViewport->setObjectName("Viewport"); - m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - CreateMenu(); CreateTabBar(); - QVBoxLayout* vl = new QVBoxLayout(m_centralWidget); - vl->setMargin(0); - vl->setContentsMargins(0, 0, 0, 0); - vl->addWidget(m_tabWidget); - vl->addWidget(m_materialViewport); - m_centralWidget->setLayout(vl); - setCentralWidget(m_centralWidget); + m_materialViewport = new MaterialViewportWidget(centralWidget()); + m_materialViewport->setObjectName("Viewport"); + m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + centralWidget()->layout()->addWidget(m_materialViewport); AddDockWidget("Asset Browser", new MaterialBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Horizontal); @@ -200,7 +191,7 @@ namespace MaterialEditor // Create a new tab for the document ID and assign it's label to the file name of the document. AddTabForDocumentId(documentId, filename, absolutePath, [this]{ // The tab widget requires a dummy page per tab - auto contentWidget = new QWidget(m_centralWidget); + auto contentWidget = new QWidget(centralWidget()); contentWidget->setContentsMargins(0, 0, 0, 0); contentWidget->setFixedSize(0, 0); return contentWidget; @@ -247,8 +238,8 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } } @@ -258,7 +249,7 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + m_statusMessage->setText(QString("%1").arg(status)); } void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId) @@ -296,8 +287,8 @@ namespace MaterialEditor UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void MaterialEditorWindow::CreateMenu() @@ -341,8 +332,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Save); @@ -355,8 +346,8 @@ namespace MaterialEditor documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::SaveAs); @@ -369,8 +360,8 @@ namespace MaterialEditor documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -379,8 +370,8 @@ namespace MaterialEditor MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Failed to save materials."); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save documents."); + m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -425,8 +416,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to perform Undo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -437,8 +428,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to perform Redo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 8406ae891f..5359ba8e53 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -30,47 +30,24 @@ namespace MaterialEditor serialize->Class() ->Version(0); } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("MaterialEditorWindowAtomRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("CreateMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) - ->Event("DestroyMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) - ; - - behaviorContext->EBus("MaterialEditorWindowRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("ActivateWindow", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ActivateWindow) - ->Event("SetDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::SetDockWidgetVisible) - ->Event("IsDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::IsDockWidgetVisible) - ->Event("GetDockWidgetNames", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::GetDockWidgetNames) - ->Event("ResizeViewportRenderTarget", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ResizeViewportRenderTarget) - ->Event("LockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::LockViewportRenderTargetSize) - ->Event("UnlockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::UnlockViewportRenderTargetSize) - ; - } } void MaterialEditorWindowComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetBrowserService", 0x1e54fffb)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("SourceControlService", 0x67f338fd)); + required.push_back(AZ_CRC_CE("AssetBrowserService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("SourceControlService")); + required.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); } void MaterialEditorWindowComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("MaterialEditorWindowService", 0xb6e7d922)); + provided.push_back(AZ_CRC_CE("MaterialEditorWindowService")); } void MaterialEditorWindowComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("MaterialEditorWindowService", 0xb6e7d922)); + incompatible.push_back(AZ_CRC_CE("MaterialEditorWindowService")); } void MaterialEditorWindowComponent::Init() diff --git a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py index d7f52d7a24..2116a3de6c 100755 --- a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py +++ b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py @@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT """ import azlmbr.bus +import azlmbr.atomtools import azlmbr.materialeditor import azlmbr.name import azlmbr.render @@ -122,12 +123,12 @@ def CaptureScreenshot(screenshotOutputPath): def ResizeViewport(width, height): # This locks the size of the render target to the desired resolution - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'LockViewportRenderTargetSize', width, height) + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'LockViewportRenderTargetSize', width, height) # This resizes the window to closely match the render target resolution so it doesn't appear stretched while the script is running - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'ResizeViewportRenderTarget', width, height) + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'ResizeViewportRenderTarget', width, height) def ReleaseViewportResolutionLock(): - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'UnlockViewportRenderTargetSize') + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'UnlockViewportRenderTargetSize') def GenerateMaterialScreenshot(materialName, uniqueSuffix="", diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h index e497b2bc2f..68325beabb 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h @@ -10,6 +10,9 @@ #include #include +#include +#include + namespace ShaderManagementConsole { class ShaderManagementConsoleDocumentNotifications @@ -47,9 +50,33 @@ namespace ShaderManagementConsole //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentModified([[maybe_unused]] const AZ::Uuid& documentId) {} + //! Signal that a document dependency was modified + //! @param documentId unique id of document for which the notification is sent + virtual void OnDocumentDependencyModified([[maybe_unused]] const AZ::Uuid& documentId) {} + + //! Signal that a document was modified externally + //! @param documentId unique id of document for which the notification is sent + virtual void OnDocumentExternallyModified([[maybe_unused]] const AZ::Uuid& documentId) {} + //! Signal that a document undo state was updated //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentUndoStateChanged([[maybe_unused]] const AZ::Uuid& documentId) {} + + //! Signal that a property changed + //! @param documentId unique id of document for which the notification is sent + //! @param property object containing the property value and configuration that was modified + virtual void OnDocumentPropertyValueModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} + + //! Signal that the property configuration has been changed. + //! @param documentId unique id of document for which the notification is sent + //! @param property object containing the property value and configuration that was modified + virtual void OnDocumentPropertyConfigModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} + + //! Signal that the property group visibility has been changed. + //! @param documentId unique id of document for which the notification is sent + //! @param groupId id of the group that changed + //! @param visible whether the property group is visible + virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} }; using ShaderManagementConsoleDocumentNotificationBus = AZ::EBus; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h index 25e157d1f3..ed002f65ed 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h @@ -18,7 +18,6 @@ namespace ShaderManagementConsole { - using ShaderManagementConsoleDocumentResult = AZ::Outcome; class ShaderManagementConsoleDocumentRequests : public AZ::EBusTraits @@ -48,17 +47,17 @@ namespace ShaderManagementConsole //! Load document and related data //! @param loadPath Absolute path of document to load - virtual ShaderManagementConsoleDocumentResult Open(AZStd::string_view loadPath) = 0; + virtual bool Open(AZStd::string_view loadPath) = 0; //! Save document to file - virtual ShaderManagementConsoleDocumentResult Save() = 0; + virtual bool Save() = 0; //! Save document copy //! @param savePath Absolute path where document is saved - virtual ShaderManagementConsoleDocumentResult SaveAsCopy(AZStd::string_view savePath) = 0; + virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; //! Close document and reset its data - virtual ShaderManagementConsoleDocumentResult Close() = 0; + virtual bool Close() = 0; //! document is loaded virtual bool IsOpen() const = 0; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h index b21686ebaf..93c46f442f 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h @@ -29,9 +29,9 @@ namespace ShaderManagementConsole virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0; //! Open a document for editing - //! @param path document to edit. + //! @param sourcePath document to open. //! @return unique id of new document if successful, otherwise null Uuid - virtual AZ::Uuid OpenDocument(AZStd::string_view path) = 0; + virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0; //! Close the specified document //! @param documentId unique id of document to close @@ -40,13 +40,18 @@ namespace ShaderManagementConsole //! Close all documents virtual bool CloseAllDocuments() = 0; + //! Close all documents except for documentId + //! @param documentId unique id of document to not close + virtual bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) = 0; + //! Save the specified document //! @param documentId unique id of document to save virtual bool SaveDocument(const AZ::Uuid& documentId) = 0; //! Save the specified document to a different file //! @param documentId unique id of document to save - virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId) = 0; + //! @param targetPath location where document is saved. + virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; //! Save all documents virtual bool SaveAllDocuments() = 0; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp index 67990d4b71..9dae9c10cc 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp @@ -28,6 +28,7 @@ namespace ShaderManagementConsole { ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); ShaderManagementConsoleDocumentRequestBus::Handler::BusDisconnect(); + Clear(); } const AZ::Uuid& ShaderManagementConsoleDocument::GetId() const @@ -71,19 +72,21 @@ namespace ShaderManagementConsole return m_shaderVariantListSourceData.m_shaderVariants[index]; } - ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Open(AZStd::string_view loadPath) + bool ShaderManagementConsoleDocument::Open(AZStd::string_view loadPath) { Clear(); m_absolutePath = loadPath; if (!AzFramework::StringFunc::Path::Normalize(m_absolutePath)) { - return AZ::Failure(AZStd::string::format("Document path could not be normalized: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document path could not be normalized: '%s'.", m_absolutePath.c_str()); + return false; } if (AzFramework::StringFunc::Path::IsRelative(m_absolutePath.c_str())) { - return AZ::Failure(AZStd::string::format("Document path must be absolute: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document path must be absolute: '%s'.", m_absolutePath.c_str()); + return false; } if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) @@ -91,7 +94,8 @@ namespace ShaderManagementConsole // Load the shader config data and create a shader config asset from it if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, m_shaderVariantListSourceData)) { - return AZ::Failure(AZStd::string::format("Failed loading shader variant list data: '%s.'", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Failed loading shader variant list data: '%s.'", m_absolutePath.c_str()); + return false; } } @@ -103,13 +107,15 @@ namespace ShaderManagementConsole watchFolder); if (!result) { - return AZ::Failure(AZStd::string::format("Could not find source data: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Could not find source data: '%s'.", m_absolutePath.c_str()); + return false; } m_relativePath = m_shaderVariantListSourceData.m_shaderFilePath; if (!AzFramework::StringFunc::Path::Normalize(m_relativePath)) { - return AZ::Failure(AZStd::string::format("Shader path could not be normalized: '%s'.", m_relativePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Shader path could not be normalized: '%s'.", m_relativePath.c_str()); + return false; } AZStd::string shaderPath = m_relativePath; @@ -118,27 +124,32 @@ namespace ShaderManagementConsole m_shaderAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath(shaderPath.c_str()); if (!m_shaderAsset) { - return AZ::Failure(AZStd::string::format("Could not load shader asset: %s.", shaderPath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Could not load shader asset: %s.", shaderPath.c_str()); + return false; } ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, m_id); - return AZ::Success(AZStd::string::format("Document loaded: '%s'", m_absolutePath.c_str())); + AZ_TracePrintf("ShaderManagementConsoleDocument", "Document loaded: '%s'", m_absolutePath.c_str()); + return true; } - ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Save() + bool ShaderManagementConsoleDocument::Save() { if (!IsOpen()) { - return AZ::Failure(AZStd::string::format("Document is not open to be saved: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); + return false; } if (!IsSavable()) { - return AZ::Failure(AZStd::string::format("Document can not be saved: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document can not be saved: '%s'.", m_absolutePath.c_str()); + return false; } - return AZ::Failure(AZStd::string::format("%s is not implemented!", __FUNCTION__)); + AZ_Error("ShaderManagementConsoleDocument", false, "%s is not implemented!", __FUNCTION__); + return false; // Auto add or checkout saved file //AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, @@ -147,28 +158,33 @@ namespace ShaderManagementConsole //ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id); - //return AZ::Success(AZStd::string::format("Document saved: %s", m_absolutePath.data())); + //AZ_TracePrintf("ShaderManagementConsoleDocument", "Document saved: %s", m_absolutePath.data()); + //return true; } - ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::SaveAsCopy(AZStd::string_view savePath) + bool ShaderManagementConsoleDocument::SaveAsCopy(AZStd::string_view savePath) { if (!IsOpen()) { - return AZ::Failure(AZStd::string::format("Document is not open to be saved: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); + return false; } if (!IsSavable()) { - return AZ::Failure(AZStd::string::format("Document can not be saved: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document can not be saved: '%s'.", m_absolutePath.c_str()); + return false; } AZStd::string normalizedSavePath = savePath; if (!AzFramework::StringFunc::Path::Normalize(normalizedSavePath)) { - return AZ::Failure(AZStd::string::format("Document save path could not be normalized: '%s'.", normalizedSavePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document save path could not be normalized: '%s'.", normalizedSavePath.c_str()); + return false; } - return AZ::Failure(AZStd::string::format("%s is not implemented!", __FUNCTION__)); + AZ_Error("ShaderManagementConsoleDocument", false, "%s is not implemented!", __FUNCTION__); + return false; // Auto add or checkout saved file //AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, @@ -177,19 +193,22 @@ namespace ShaderManagementConsole //ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id); - //return AZ::Success(AZStd::string::format("Document saved: %s", normalizedSavePath.c_str())); + //AZ_TracePrintf("ShaderManagementConsoleDocument", "Document saved: %s", normalizedSavePath.c_str()); + //return true; } - ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Close() + bool ShaderManagementConsoleDocument::Close() { if (!IsOpen()) { - return AZ::Failure(AZStd::string("Document is not open")); + AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open"); + return false; } Clear(); ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentClosed, m_id); - return AZ::Success(AZStd::string("Document was closed")); + AZ_TracePrintf("ShaderManagementConsoleDocument", "Document was closed"); + return true; } bool ShaderManagementConsoleDocument::IsOpen() const @@ -269,5 +288,9 @@ namespace ShaderManagementConsole { m_absolutePath.clear(); m_relativePath.clear(); + m_shaderVariantListSourceData = {}; + m_shaderAsset = {}; + m_undoHistory = {}; + m_undoHistoryIndex = {}; } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h index 6c9580c086..3d1a88c62e 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h @@ -41,10 +41,10 @@ namespace ShaderManagementConsole const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const override; size_t GetShaderVariantCount() const override; const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const override; - ShaderManagementConsoleDocumentResult Open(AZStd::string_view loadPath) override; - ShaderManagementConsoleDocumentResult Save() override; - ShaderManagementConsoleDocumentResult SaveAsCopy(AZStd::string_view savePath) override; - ShaderManagementConsoleDocumentResult Close() override; + bool Open(AZStd::string_view loadPath) override; + bool Save() override; + bool SaveAsCopy(AZStd::string_view savePath) override; + bool Close() override; bool IsOpen() const override; bool IsModified() const override; bool IsSavable() const override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp index fae9ec75ef..f06aae29d7 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp @@ -8,9 +8,11 @@ #include -#include -#include +#include +#include #include +#include +#include #include #include @@ -67,6 +69,7 @@ namespace ShaderManagementConsole ->Event("OpenDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument) ->Event("CloseDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument) ->Event("CloseAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments) + ->Event("CloseAllDocumentsExcept", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept) ->Event("SaveDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument) ->Event("SaveDocumentAsCopy", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy) ->Event("SaveAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments) @@ -152,9 +155,9 @@ namespace ShaderManagementConsole return m_documentMap.erase(documentId) != 0; } - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view path) + AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath) { - return OpenDocumentImpl(path, true); + return OpenDocumentImpl(sourcePath, true); } bool ShaderManagementConsoleDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) @@ -163,26 +166,46 @@ namespace ShaderManagementConsole ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen); if (!isOpen) { + // immediately destroy unopened documents + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); return true; } + AZStd::string documentPath; + ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + bool isModified = false; ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); if (isModified) { - if (QMessageBox::question(QApplication::activeWindow(), "document has unsaved changes", "Would you like to close anyway?", - QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + auto selection = QMessageBox::question(QApplication::activeWindow(), + QString("Document has unsaved changes"), + QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (selection == QMessageBox::Cancel) { + AZ_TracePrintf("ShaderManagementConsoleDocument", "Close document canceled: %s", documentPath.c_str()); return false; } + if (selection == QMessageBox::Yes) + { + if (!SaveDocument(documentId)) + { + AZ_Error("ShaderManagementConsoleDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str()); + return false; + } + } } - ShaderManagementConsoleDocumentResult closeResult = AZ::Success(AZStd::string("There is no active document")); + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool closeResult = true; ShaderManagementConsoleDocumentRequestBus::EventResult(closeResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Close); if (!closeResult) { - QMessageBox::critical(QApplication::activeWindow(), "Failed to close document", - QString::fromUtf8(closeResult.GetError().data(), (int)closeResult.GetError().size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be closed"), + QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -205,60 +228,83 @@ namespace ShaderManagementConsole return result; } + bool ShaderManagementConsoleDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) + { + bool result = true; + auto documentMap = m_documentMap; + for (const auto& documentPair : documentMap) + { + if (documentPair.first != documentId) + { + if (!CloseDocument(documentPair.first)) + { + result = false; + } + } + } + + return result; + } + bool ShaderManagementConsoleDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) { - AZStd::string documentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string saveDocumentPath; + ShaderManagementConsoleDocumentRequestBus::EventResult(saveDocumentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - const QFileInfo saveInfo(documentPath.c_str()); - if (saveInfo.absoluteFilePath().isEmpty()) + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } + const QFileInfo saveInfo(saveDocumentPath.c_str()); if (saveInfo.exists() && !saveInfo.isWritable()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Unable to save document. File can not be overwritten.")); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); return false; } - ShaderManagementConsoleDocumentResult result = AZ::Failure(AZStd::string("There is no active document")); + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Save); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "document not saved", - QString::fromUtf8(result.GetError().data(), (int)result.GetError().size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } - AZ_TracePrintf("ShaderManagementConsole", "%s\n", result.GetValue().c_str()); return true; } - bool ShaderManagementConsoleDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId) + bool ShaderManagementConsoleDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) { - AZStd::string documentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - - const QFileInfo& saveInfo = AtomToolsFramework::GetSaveFileInfo(documentPath.c_str()); - if (saveInfo.absoluteFilePath().isEmpty()) + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } - AZStd::string saveDocumentPath = saveInfo.absoluteFilePath().toUtf8().constData(); - AzFramework::StringFunc::Path::Normalize(saveDocumentPath); + const QFileInfo saveInfo(saveDocumentPath.c_str()); + if (saveInfo.exists() && !saveInfo.isWritable()) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); + return false; + } - ShaderManagementConsoleDocumentResult result = AZ::Failure(AZStd::string("There is no active document")); + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "document copy not saved", - QString::fromUtf8(result.GetError().data(), (int)result.GetError().size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } - AZ_TracePrintf("ShaderManagementConsole", "%s\n", result.GetValue().c_str()); return true; } @@ -276,13 +322,17 @@ namespace ShaderManagementConsole return result; } - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view path, bool checkIfAlreadyOpen) + AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) { - AZStd::string requestedPath = path; - if (requestedPath.empty() || !AzFramework::StringFunc::Path::Normalize(requestedPath)) + AZStd::string requestedPath = sourcePath; + if (requestedPath.empty()) { - QMessageBox::critical(QApplication::activeWindow(), "document path is invalid", - QString::fromUtf8(requestedPath.data(), (int)requestedPath.size())); + return AZ::Uuid::CreateNull(); + } + + if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); return AZ::Uuid::CreateNull(); } @@ -301,21 +351,27 @@ namespace ShaderManagementConsole } } + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + AZ::Uuid documentId = AZ::Uuid::CreateNull(); ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(documentId, &ShaderManagementConsoleDocumentSystemRequestBus::Events::CreateDocument); if (documentId.IsNull()) { - QMessageBox::critical(QApplication::activeWindow(), "Failed to create document", - QString::fromUtf8(requestedPath.data(), (int)requestedPath.size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be created"), + QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); return AZ::Uuid::CreateNull(); } - ShaderManagementConsoleDocumentResult openResult = AZ::Failure(AZStd::string("Failed to open document")); + traceRecorder.GetDump().clear(); + + bool openResult = false; ShaderManagementConsoleDocumentRequestBus::EventResult(openResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Open, requestedPath); if (!openResult) { - QMessageBox::critical(QApplication::activeWindow(), "Failed to open document", - QString::fromUtf8(openResult.GetError().data(), (int)openResult.GetError().size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); return AZ::Uuid::CreateNull(); } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h index 245222976e..05c61ce058 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h @@ -53,16 +53,18 @@ namespace ShaderManagementConsole // ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides... AZ::Uuid CreateDocument() override; bool DestroyDocument(const AZ::Uuid& documentId) override; - AZ::Uuid OpenDocument(AZStd::string_view path) override; + AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; bool CloseDocument(const AZ::Uuid& documentId) override; bool CloseAllDocuments() override; + bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override; bool SaveDocument(const AZ::Uuid& documentId) override; - bool SaveDocumentAsCopy(const AZ::Uuid& documentId) override; + bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; bool SaveAllDocuments() override; //////////////////////////////////////////////////////////////////////// - AZ::Uuid OpenDocumentImpl(AZStd::string_view path, bool checkIfAlreadyOpen); + AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); AZStd::unordered_map> m_documentMap; + const size_t m_maxMessageBoxLineCount = 15; }; } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 0a082f3c33..b23e828d5e 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include #include @@ -23,11 +25,8 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include -#include #include #include -#include -#include #include AZ_POP_DISABLE_WARNING @@ -36,6 +35,14 @@ namespace ShaderManagementConsole ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */) : AtomToolsFramework::AtomToolsMainWindow(parent) { + resize(1280, 1024); + + // Among other things, we need the window wrapper to save the main window size, position, and state + auto mainWindowWrapper = + new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons); + mainWindowWrapper->setGuest(this); + mainWindowWrapper->enableSaveRestoreGeometry("O3DE", "ShaderManagementConsole", "mainWindowGeometry"); + setWindowTitle("Shader Management Console"); setObjectName("ShaderManagementConsoleWindow"); @@ -47,16 +54,14 @@ namespace ShaderManagementConsole CreateMenu(); CreateTabBar(); - QVBoxLayout* vl = new QVBoxLayout(m_centralWidget); - vl->setMargin(0); - vl->setContentsMargins(0, 0, 0, 0); - vl->addWidget(m_tabWidget); - m_centralWidget->setLayout(vl); - setCentralWidget(m_centralWidget); - AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal); + SetDockWidgetVisible("Python Terminal", false); + + // Restore geometry and show the window + mainWindowWrapper->showFromSettings(); + ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect(); OnDocumentOpened(AZ::Uuid::CreateNull()); } @@ -103,8 +108,7 @@ namespace ShaderManagementConsole // Create a new tab for the document ID and assign it's label to the file name of the document. AddTabForDocumentId(documentId, filename, absolutePath, [this, documentId]{ // The document tab contains a table view. - auto contentWidget = new QTableView(m_centralWidget); - contentWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + auto contentWidget = new QTableView(centralWidget()); contentWidget->setSelectionBehavior(QAbstractItemView::SelectRows); contentWidget->setModel(CreateDocumentContent(documentId)); return contentWidget; @@ -142,11 +146,22 @@ namespace ShaderManagementConsole activateWindow(); raise(); + + const QString documentPath = GetDocumentPath(documentId); + if (!documentPath.isEmpty()) + { + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } } void ShaderManagementConsoleWindow::OnDocumentClosed(const AZ::Uuid& documentId) { RemoveTabForDocumentId(documentId); + + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId) @@ -182,6 +197,10 @@ namespace ShaderManagementConsole AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); + + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void ShaderManagementConsoleWindow::CreateMenu() @@ -206,8 +225,47 @@ namespace ShaderManagementConsole m_menuFile->addSeparator(); + m_actionSave = m_menuFile->addAction("&Save", [this]() { + const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); + bool result = false; + ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument, documentId); + if (!result) + { + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } + }, QKeySequence::Save); + + m_actionSaveAsCopy = m_menuFile->addAction("Save &As...", [this]() { + const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); + const QString documentPath = GetDocumentPath(documentId); + + bool result = false; + ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy, + documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); + if (!result) + { + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } + }, QKeySequence::SaveAs); + + m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() { + bool result = false; + ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments); + if (!result) + { + const QString status = QString("Failed to save documents."); + m_statusMessage->setText(QString("%1").arg(status)); + } + }); + + m_menuFile->addSeparator(); + m_actionClose = m_menuFile->addAction("&Close", [this]() { - CloseDocumentForTab(m_tabWidget->currentIndex()); + const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); }, QKeySequence::Close); m_actionCloseAll = m_menuFile->addAction("Close All", [this]() { @@ -215,23 +273,8 @@ namespace ShaderManagementConsole }); m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() { - CloseAllExceptDocumentForTab(m_tabWidget->currentIndex()); - }); - - m_menuFile->addSeparator(); - - m_actionSave = m_menuFile->addAction("&Save", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument, documentId); - }, QKeySequence::Save); - - m_actionSaveAsCopy = m_menuFile->addAction("Save &As...", [this]() { - const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy, documentId); - }, QKeySequence::SaveAs); - - m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); m_menuFile->addSeparator(); @@ -254,37 +297,46 @@ namespace ShaderManagementConsole m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentRequestBus::Event(documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo); + bool result = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo); + if (!result) + { + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Failed to perform Undo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } }, QKeySequence::Undo); m_actionRedo = m_menuEdit->addAction("&Redo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentRequestBus::Event(documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo); + bool result = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo); + if (!result) + { + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Failed to perform Redo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } }, QKeySequence::Redo); m_menuEdit->addSeparator(); - m_actionSettings = m_menuEdit->addAction("&Preferences...", [this]() { + m_actionSettings = m_menuEdit->addAction("&Settings...", [this]() { }, QKeySequence::Preferences); m_actionSettings->setEnabled(false); m_menuView = m_menuBar->addMenu("&View"); - m_actionAssetBrowser = m_menuView->addAction( - "&Asset Browser", - [this]() - { - const AZStd::string label = "Asset Browser"; - SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); - }); + m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() { + const AZStd::string label = "Asset Browser"; + SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); + }); + + m_actionPythonTerminal = m_menuView->addAction("Python &Terminal", [this]() { + const AZStd::string label = "Python Terminal"; + SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); + }); - m_actionPythonTerminal = m_menuView->addAction( - "Python &Terminal", - [this]() - { - const AZStd::string label = "Python Terminal"; - SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); - }); m_menuView->addSeparator(); @@ -313,14 +365,23 @@ namespace ShaderManagementConsole // When the last tab is removed tabIndex will be -1 and the document ID will be null // This should automatically clear the active document connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) { - SelectDocumentForTab(tabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); + ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) { - CloseDocumentForTab(tabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); }); } + QString ShaderManagementConsoleWindow::GetDocumentPath(const AZ::Uuid& documentId) const + { + AZStd::string absolutePath; + ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Handler::GetAbsolutePath); + return absolutePath.c_str(); + } + void ShaderManagementConsoleWindow::OpenTabContextMenu() { const QTabBar* tabBar = m_tabWidget->tabBar(); @@ -332,51 +393,22 @@ namespace ShaderManagementConsole QMenu tabMenu; const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select"; tabMenu.addAction(selectActionName, [this, clickedTabIndex]() { - SelectDocumentForTab(clickedTabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); + ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); tabMenu.addAction("Close", [this, clickedTabIndex]() { - CloseDocumentForTab(clickedTabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); }); auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() { - CloseAllExceptDocumentForTab(clickedTabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); closeOthersAction->setEnabled(tabBar->count() > 1); tabMenu.exec(QCursor::pos()); } } - void ShaderManagementConsoleWindow::SelectDocumentForTab(const int tabIndex) - { - const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); - } - - void ShaderManagementConsoleWindow::CloseDocumentForTab(const int tabIndex) - { - const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); - } - - void ShaderManagementConsoleWindow::CloseAllExceptDocumentForTab(const int tabIndex) - { - AZStd::vector documentIdsToClose; - documentIdsToClose.reserve(m_tabWidget->count()); - const AZ::Uuid documentIdToKeepOpen = GetDocumentIdFromTab(tabIndex); - for (int tabI = 0; tabI < m_tabWidget->count(); ++tabI) - { - const AZ::Uuid documentId = GetDocumentIdFromTab(tabI); - if (documentId != documentIdToKeepOpen) - { - documentIdsToClose.push_back(documentId); - } - } - - for (const AZ::Uuid& documentId : documentIdsToClose) - { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); - } - } - QStandardItemModel* ShaderManagementConsoleWindow::CreateDocumentContent(const AZ::Uuid& documentId) { AZStd::unordered_set optionNames; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index aae31d1000..7f3f772961 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -52,11 +52,10 @@ namespace ShaderManagementConsole void CreateMenu() override; void CreateTabBar() override; - void OpenTabContextMenu() override; - void SelectDocumentForTab(const int tabIndex); - void CloseDocumentForTab(const int tabIndex); - void CloseAllExceptDocumentForTab(const int tabIndex); + QString GetDocumentPath(const AZ::Uuid& documentId) const; + + void OpenTabContextMenu() override; void closeEvent(QCloseEvent* closeEvent) override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp index 44715ef64f..a89cdfddb8 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp @@ -44,14 +44,6 @@ namespace ShaderManagementConsole if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("CreateShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) - ->Event("DestroyShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) - ; - behaviorContext->EBus("ShaderManagementConsoleRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") @@ -65,19 +57,20 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetBrowserService", 0x1e54fffb)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("SourceControlService", 0x67f338fd)); + required.push_back(AZ_CRC_CE("AssetBrowserService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("SourceControlService")); + required.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); } void ShaderManagementConsoleWindowComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("ShaderManagementConsoleWindowService", 0xb6e7d922)); + provided.push_back(AZ_CRC_CE("ShaderManagementConsoleWindowService")); } void ShaderManagementConsoleWindowComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("ShaderManagementConsoleWindowService", 0xb6e7d922)); + incompatible.push_back(AZ_CRC_CE("ShaderManagementConsoleWindowService")); } void ShaderManagementConsoleWindowComponent::Init() From ce7598c10bbc615ba3a954e6bdbfd7ced16c9e61 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 12:59:32 -0700 Subject: [PATCH 025/101] [redcode/crythread-2nd-pass] fixed missing includes Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp | 1 + Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm | 2 ++ Code/Legacy/CryCommon/VectorMap.h | 1 + .../AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp index 1e87b902a6..3030dcc740 100644 --- a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp +++ b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp @@ -10,6 +10,7 @@ #include #include // for AZ_MAX_PATH_LEN +#include #include diff --git a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm index cfba0d8aac..f4ea67c6e6 100644 --- a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm @@ -11,6 +11,8 @@ #include <../Common/Apple/Launcher_Apple.h> #include <../Common/UnixLike/Launcher_UnixLike.h> +#include + #if AZ_TESTS_ENABLED int main(int argc, char* argv[]) diff --git a/Code/Legacy/CryCommon/VectorMap.h b/Code/Legacy/CryCommon/VectorMap.h index 1a42f0e48f..ee99c6f952 100644 --- a/Code/Legacy/CryCommon/VectorMap.h +++ b/Code/Legacy/CryCommon/VectorMap.h @@ -14,6 +14,7 @@ #define CRYINCLUDE_CRYCOMMON_VECTORMAP_H #pragma once +#include // for stl::free_container //-------------------------------------------------------------------------- // VectorMap diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h index 7dd2629bd0..018bc74877 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h @@ -96,7 +96,7 @@ namespace AZ void UnregisterFont(const char* fontName); private: - using FontMap = std::unordered_map; + using FontMap = AZStd::unordered_map; using FontMapItor = FontMap::iterator; using FontMapConstItor = FontMap::const_iterator; From 8b8e249e05852e4d2d6da1435df7275f92f894f6 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 11 Aug 2021 13:59:41 -0700 Subject: [PATCH 026/101] Add new functions to mock unit test class. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h index 7c132b29a3..a63e782146 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h @@ -25,6 +25,10 @@ namespace AZ MOCK_CONST_METHOD2(Visit, bool(const VisitorCallback&, AZStd::string_view)); MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(const NotifyCallback&)); MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&)); + MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(const PreMergeEventCallback&)); + MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(PreMergeEventCallback&&)); + MOCK_METHOD1(PostMergeEventHandler, PreMergeEventHandler(const PostMergeEventCallback&)); + MOCK_METHOD1(PostMergeEventHandler, PreMergeEventHandler(PostMergeEventCallback&&)); MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view)); MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view)); From 6c83dcd702ed015d9f6d6a3b08685a4f59752673 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:44:04 -0700 Subject: [PATCH 027/101] [redcode/crythread-2nd-pass] fixed another missing include Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp index 5cc3070cdb..44426f6d01 100644 --- a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp +++ b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp @@ -9,6 +9,7 @@ #include #include +#include int APIENTRY WinMain([[maybe_unused]] HINSTANCE hInstance, [[maybe_unused]] HINSTANCE hPrevInstance, [[maybe_unused]] LPSTR lpCmdLine, [[maybe_unused]] int nCmdShow) { From 5a891c8cbdd769744a75c1118b6445199ce249fd Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:54:59 -0700 Subject: [PATCH 028/101] [redcode/crythread-2nd-pass] replaced remaining CrySpinLock/CryWriteLock usage with equivalent AZStd version Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/Synchronization.h | 33 ++++-------------------- Code/Legacy/CryCommon/physinterface.h | 6 +++-- Code/Legacy/CrySystem/DebugCallStack.cpp | 7 ++--- 3 files changed, 13 insertions(+), 33 deletions(-) diff --git a/Code/Legacy/CryCommon/Synchronization.h b/Code/Legacy/CryCommon/Synchronization.h index 3bac215998..d38160c967 100644 --- a/Code/Legacy/CryCommon/Synchronization.h +++ b/Code/Legacy/CryCommon/Synchronization.h @@ -21,7 +21,7 @@ // //--------------------------------------------------------------------------- -#include "MultiThread.h" +#include namespace stl { @@ -51,43 +51,20 @@ namespace stl struct PSyncMultiThread { - PSyncMultiThread() - : _Semaphore(0) {} + PSyncMultiThread() {} void Lock() { - CryWriteLock(&_Semaphore); + m_lock.lock(); } void Unlock() { - CryReleaseWriteLock(&_Semaphore); - } - int IsLocked() const volatile - { - return _Semaphore; + m_lock.unlock(); } private: - volatile int _Semaphore; + AZStd::spin_mutex m_lock; }; - -#ifdef _DEBUG - - struct PSyncDebug - : public PSyncMultiThread - { - void Lock() - { - assert(!IsLocked()); - PSyncMultiThread::Lock(); - } - }; - -#else - - typedef PSyncNone PSyncDebug; - -#endif }; #endif // CRYINCLUDE_CRYCOMMON_SYNCHRONIZATION_H diff --git a/Code/Legacy/CryCommon/physinterface.h b/Code/Legacy/CryCommon/physinterface.h index 89b7318eaa..b1aaa5aef4 100644 --- a/Code/Legacy/CryCommon/physinterface.h +++ b/Code/Legacy/CryCommon/physinterface.h @@ -26,6 +26,8 @@ #include +#include + ////////////////////////////////////////////////////////////////////////// // Physics defines. ////////////////////////////////////////////////////////////////////////// @@ -2834,8 +2836,8 @@ struct IGeometry virtual int PointInsideStatus(const Vec3& pt) = 0; // for meshes, will create an auxiliary hashgrid for acceleration // IntersectLocked - the main function for geomtries. pdata1,pdata2,pparams can be 0 - defaults will be assumed. // returns a pointer to an internal thread-specific contact buffer, locked with the lock argument - virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, WriteLockCond& lock) = 0; - virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, WriteLockCond& lock, int iCaller) = 0; + virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, AZStd::spin_mutex& lock) = 0; + virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, AZStd::spin_mutex& lock, int iCaller) = 0; // Intersect - same as Intersect, but doesn't lock pcontacts virtual int Intersect(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts) = 0; // FindClosestPoint - for non-convex meshes only does local search, doesn't guarantee global minimum diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp index 576c3ee9fb..a043f16756 100644 --- a/Code/Legacy/CrySystem/DebugCallStack.cpp +++ b/Code/Legacy/CrySystem/DebugCallStack.cpp @@ -18,6 +18,7 @@ #include #include +#include #define VS_VERSION_INFO 1 #define IDD_CRITICAL_ERROR 101 @@ -152,13 +153,13 @@ void DebugCallStack::SetUserDialogEnable(const bool bUserDialogEnable) DWORD g_idDebugThreads[10]; const char* g_nameDebugThreads[10]; int g_nDebugThreads = 0; -volatile int g_lockThreadDumpList = 0; +AZStd::spin_mutex g_lockThreadDumpList = 0; void MarkThisThreadForDebugging(const char* name) { EBUS_EVENT(AZ::Debug::EventTraceDrillerSetupBus, SetThreadName, AZStd::this_thread::get_id(), name); - WriteLock lock(g_lockThreadDumpList); + AZStd::lock_guard lock(g_lockThreadDumpList); DWORD id = GetCurrentThreadId(); if (g_nDebugThreads == sizeof(g_idDebugThreads) / sizeof(g_idDebugThreads[0])) { @@ -178,7 +179,7 @@ void MarkThisThreadForDebugging(const char* name) void UnmarkThisThreadFromDebugging() { - WriteLock lock(g_lockThreadDumpList); + AZStd::lock_guard lock(g_lockThreadDumpList); DWORD id = GetCurrentThreadId(); for (int i = g_nDebugThreads - 1; i >= 0; i--) { From 337ea488b6539ced5d2e9bf2518b52c93b8fdf56 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:57:49 -0700 Subject: [PATCH 029/101] [redcode/crythread-2nd-pass] replaced remaining CryInterlocked* usage with equivalent AZStd version Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/IFunctorBase.h | 8 +++-- Code/Legacy/CryCommon/smartptr.h | 36 ++++++++----------- .../Code/Source/Engine/AudioRequests.cpp | 2 +- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/Code/Legacy/CryCommon/IFunctorBase.h b/Code/Legacy/CryCommon/IFunctorBase.h index 2a8af50d33..c7d39ee923 100644 --- a/Code/Legacy/CryCommon/IFunctorBase.h +++ b/Code/Legacy/CryCommon/IFunctorBase.h @@ -15,6 +15,8 @@ #pragma once +#include + // Base class for functor storage. // Not intended for direct usage. class IFunctorBase @@ -27,19 +29,19 @@ public: void AddRef() { - CryInterlockedIncrement(&m_nReferences); + m_nReferences.fetch_add(1, AZStd::memory_order_acq_rel); } void Release() { - if (CryInterlockedDecrement(&m_nReferences) <= 0) + if (m_nReferences.fetch_sub(1, AZStd::memory_order_acq_rel) == 1) { delete this; } } protected: - volatile int m_nReferences; + AZStd::atomic_int m_nReferences; }; // Base Template for specialization. diff --git a/Code/Legacy/CryCommon/smartptr.h b/Code/Legacy/CryCommon/smartptr.h index 246e18d541..fd833b12e3 100644 --- a/Code/Legacy/CryCommon/smartptr.h +++ b/Code/Legacy/CryCommon/smartptr.h @@ -18,6 +18,9 @@ void CryFatalError(const char*, ...) PRINTF_PARAMS(1, 2); #if defined(APPLE) #include #endif + +#include + ////////////////////////////////////////////////////////////////// // SMART POINTER ////////////////////////////////////////////////////////////////// @@ -352,38 +355,32 @@ protected: class CMultiThreadRefCount { public: - CMultiThreadRefCount() - : m_cnt(0) {} + CMultiThreadRefCount() {} virtual ~CMultiThreadRefCount() {} inline int AddRef() { - return CryInterlockedIncrement(&m_cnt); + return m_count.fetch_add(1, AZStd::memory_order_acq_rel) + 1; // because we get the original value back } inline int Release() { - const int nCount = CryInterlockedDecrement(&m_cnt); - assert(nCount >= 0); + const int nCount = m_count.fetch_sub(1, AZStd::memory_order_acq_rel) - 1; // because we get the original value back + AZ_Assert(nCount >= 0, "Deleting Reference Counted Object Twice"); if (nCount == 0) { delete this; } - else if (nCount < 0) - { - assert(0); - CryFatalError("Deleting Reference Counted Object Twice"); - } return nCount; } - inline int GetRefCount() const { return m_cnt; } + inline int GetRefCount() const { return m_count.load(AZStd::memory_order_acquire); } protected: // Allows the memory for the object to be deallocated in the dynamic module where it was originally constructed, as it may use different memory manager (Debug/Release configurations) virtual void DeleteThis() { delete this; } private: - volatile int m_cnt; + AZStd::atomic_int m_count{ 0 }; }; // base class for interfaces implementing reference counting that needs to be thread-safe @@ -404,29 +401,24 @@ public: virtual void AddRef() { - CryInterlockedIncrement(&m_nRefCounter); + m_nRefCounter.fetch_add(1, AZStd::memory_order_acq_rel); } virtual void Release() { - const int nCount = CryInterlockedDecrement(&m_nRefCounter); - assert(nCount >= 0); + const int nCount = m_nRefCounter.fetch_sub(1, AZStd::memory_order_acq_rel) - 1; // because we get the original value back + AZ_Assert(nCount >= 0, "Deleting Reference Counted Object Twice"); if (nCount == 0) { delete this; } - else if (nCount < 0) - { - assert(0); - CryFatalError("Deleting Reference Counted Object Twice"); - } } - Counter NumRefs() const { return m_nRefCounter; } + Counter NumRefs() const { return m_nRefCounter.load(AZStd::memory_order_acquire); } protected: - volatile Counter m_nRefCounter; + AZStd::atomic m_nRefCounter{ 0 }; }; typedef _i_reference_target _i_reference_target_t; diff --git a/Gems/AudioSystem/Code/Source/Engine/AudioRequests.cpp b/Gems/AudioSystem/Code/Source/Engine/AudioRequests.cpp index 35da74b0de..0862483ab8 100644 --- a/Gems/AudioSystem/Code/Source/Engine/AudioRequests.cpp +++ b/Gems/AudioSystem/Code/Source/Engine/AudioRequests.cpp @@ -153,7 +153,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// void SAudioRequestDataInternal::Release() { - const int nCount = CryInterlockedDecrement(&m_nRefCounter); + const int nCount = m_nRefCounter.fetch_sub(1, AZStd::memory_order_acq_rel) - 1; // because we get the original value back AZ_Assert(nCount >= 0, "AudioRequests Release - Decremented reference counter too many times!"); if (nCount == 0) From c173dee2bcf8c348babdb93b1ea9368b0027050b Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:38:54 -0700 Subject: [PATCH 030/101] [redcode/crythread-2nd-pass] removed MultiThread.h along with external CryInterlocked* definitions Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/MultiThread.h | 277 -------------------- Code/Legacy/CryCommon/WinBase.cpp | 85 +----- Code/Legacy/CryCommon/crycommon_files.cmake | 1 - Code/Legacy/CryCommon/platform.h | 4 - Code/Legacy/CryCommon/platform_impl.cpp | 52 ---- Code/Legacy/CrySystem/Log.h | 1 - 6 files changed, 1 insertion(+), 419 deletions(-) delete mode 100644 Code/Legacy/CryCommon/MultiThread.h diff --git a/Code/Legacy/CryCommon/MultiThread.h b/Code/Legacy/CryCommon/MultiThread.h deleted file mode 100644 index c3aa892d14..0000000000 --- a/Code/Legacy/CryCommon/MultiThread.h +++ /dev/null @@ -1,277 +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 - -#if defined(APPLE) || defined(LINUX) -#include -#endif - -#include - -#include "CryAssert.h" - -// Section dictionary -#if defined(AZ_RESTRICTED_PLATFORM) -#define MULTITHREAD_H_SECTION_TRAITS 1 -#define MULTITHREAD_H_SECTION_DEFINE_CRYINTERLOCKEXCHANGE 2 -#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYSPINLOCK 3 -#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADD 4 -#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADDSIZE 5 -#define MULTITHREAD_H_SECTION_CRYINTERLOCKEDFLUSHSLIST_PT1 6 -#define MULTITHREAD_H_SECTION_CRYINTERLOCKEDFLUSHSLIST_PT2 7 -#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDCOMPAREEXCHANGE64 8 -#endif - -#define WRITE_LOCK_VAL (1 << 16) - -// Traits -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_TRAITS - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif - -void CrySpinLock(volatile int* pLock, int checkVal, int setVal); -void CryReleaseSpinLock (volatile int*, int); - -LONG CryInterlockedIncrement(int volatile* lpAddend); -LONG CryInterlockedDecrement(int volatile* lpAddend); -LONG CryInterlockedOr(LONG volatile* Destination, LONG Value); -LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value); -LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand); -void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand); -void* CryInterlockedExchangePointer (void* volatile* dst, void* exchange); - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_DEFINE_CRYINTERLOCKEXCHANGE - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif - -ILINE void CrySpinLock(volatile int* pLock, int checkVal, int setVal) -{ -#ifdef _CPU_X86 -# ifdef __GNUC__ - int val; - __asm__ __volatile__ ( - "0: mov %[checkVal], %%eax\n" - " lock cmpxchg %[setVal], (%[pLock])\n" - " jnz 0b" - : "=m" (*pLock) - : [pLock] "r" (pLock), "m" (*pLock), - [checkVal] "m" (checkVal), - [setVal] "r" (setVal) - : "eax", "cc", "memory" - ); -# else //!__GNUC__ - __asm - { - mov edx, setVal - mov ecx, pLock -Spin: - // Trick from Intel Optimizations guide -#ifdef _CPU_SSE - pause -#endif - mov eax, checkVal - lock cmpxchg [ecx], edx - jnz Spin - } -# endif //!__GNUC__ -#else // !_CPU_X86 -# if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYSPINLOCK - #include AZ_RESTRICTED_FILE(MultiThread_h) -# endif -# if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -# undef AZ_RESTRICTED_SECTION_IMPLEMENTED -# elif defined(APPLE) || defined(LINUX) - // register int val; - // __asm__ __volatile__ ( - // "0: mov %[checkVal], %%eax\n" - // " lock cmpxchg %[setVal], (%[pLock])\n" - // " jnz 0b" - // : "=m" (*pLock) - // : [pLock] "r" (pLock), "m" (*pLock), - // [checkVal] "m" (checkVal), - // [setVal] "r" (setVal) - // : "eax", "cc", "memory" - // ); - //while(CryInterlockedCompareExchange((volatile long*)pLock,setVal,checkVal)!=checkVal) ; - uint loops = 0; - while (__sync_val_compare_and_swap((volatile int32_t*)pLock, (int32_t)checkVal, (int32_t)setVal) != checkVal) - { -# if !defined (ANDROID) && !defined(IOS) - _mm_pause(); -# endif - - if (!(++loops & 0x7F)) - { - usleep(1); // give threads with other prio chance to run - } - else if (!(loops & 0x3F)) - { - sched_yield(); // give threads with same prio chance to run - } - } -# else - // NOTE: The code below will fail on 64bit architectures! - while (_InterlockedCompareExchange((volatile LONG*)pLock, setVal, checkVal) != checkVal) - { - _mm_pause(); - } -# endif -#endif -} - -ILINE void CryReleaseSpinLock(volatile int* pLock, int setVal) -{ - *pLock = setVal; -} - -////////////////////////////////////////////////////////////////////////// -ILINE void CryInterlockedAdd(volatile int* pVal, int iAdd) -{ -#ifdef _CPU_X86 -# ifdef __GNUC__ - __asm__ __volatile__ ( - " lock add %[iAdd], (%[pVal])\n" - : "=m" (*pVal) - : [pVal] "r" (pVal), "m" (*pVal), [iAdd] "r" (iAdd) - ); -# else - __asm - { - mov edx, pVal - mov eax, iAdd - lock add [edx], eax - } -# endif -#else - // NOTE: The code below will fail on 64bit architectures! -#if defined(_WIN64) - _InterlockedExchangeAdd((volatile LONG*)pVal, iAdd); -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADD - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(APPLE) || defined(LINUX) - CryInterlockedExchangeAdd((volatile LONG*)pVal, iAdd); -#elif defined(APPLE) - OSAtomicAdd32(iAdd, (volatile LONG*)pVal); -#else - InterlockedExchangeAdd((volatile LONG*)pVal, iAdd); -#endif - -#endif -} - -ILINE void CryInterlockedAddSize(volatile size_t* pVal, ptrdiff_t iAdd) -{ -#if defined(PLATFORM_64BIT) -#if defined(_WIN64) - _InterlockedExchangeAdd64((volatile __int64*)pVal, iAdd); -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADDSIZE - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(WIN32) - InterlockedExchangeAdd64((volatile LONG64*)pVal, iAdd); -#elif defined(APPLE) || defined(LINUX) - (void)__sync_fetch_and_add((int64_t*)pVal, (int64_t)iAdd); -#else - int64 x, n; - do - { - x = (int64) * pVal; - n = x + iAdd; - } - while (CryInterlockedCompareExchange64((volatile int64*)pVal, n, x) != x); -#endif -#else - CryInterlockedAdd((volatile int*)pVal, (int)iAdd); -#endif -} - - - -////////////////////////////////////////////////////////////////////////// -ILINE void CryWriteLock(volatile int* rw) -{ - CrySpinLock(rw, 0, WRITE_LOCK_VAL); -} - -ILINE void CryReleaseWriteLock(volatile int* rw) -{ - CryInterlockedAdd(rw, -WRITE_LOCK_VAL); -} - -////////////////////////////////////////////////////////////////////////// -struct WriteLock -{ - ILINE WriteLock(volatile int& rw) { CryWriteLock(&rw); prw = &rw; } - ~WriteLock() { CryReleaseWriteLock(prw); } -private: - volatile int* prw; -}; - -////////////////////////////////////////////////////////////////////////// -struct WriteLockCond -{ - ILINE WriteLockCond(volatile int& rw, int bActive = 1) - { - if (bActive) - { - CrySpinLock(&rw, 0, iActive = WRITE_LOCK_VAL); - } - else - { - iActive = 0; - } - prw = &rw; - } - ILINE WriteLockCond() { prw = &(iActive = 0); } - ~WriteLockCond() - { - CryInterlockedAdd(prw, -iActive); - } - void SetActive(int bActive = 1) { iActive = -bActive & WRITE_LOCK_VAL; } - void Release() { CryInterlockedAdd(prw, -iActive); } - volatile int* prw; - int iActive; -}; - - -#if defined(LINUX) || defined(APPLE) -ILINE int64 CryInterlockedCompareExchange64(volatile int64* addr, int64 exchange, int64 comperand) -{ - return __sync_val_compare_and_swap(addr, comperand, exchange); - // This is OK, because long is signed int64 on Linux x86_64 - //return CryInterlockedCompareExchange((volatile long*)addr, (long)exchange, (long)comperand); -} -#else -ILINE int64 CryInterlockedCompareExchange64(volatile int64* addr, int64 exchange, int64 compare) -{ - // forward to system call -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDCOMPAREEXCHANGE64 - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - return _InterlockedCompareExchange64((volatile int64*)addr, exchange, compare); -#endif -} -#endif diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 15146fbac1..a11787fef0 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -1292,90 +1292,7 @@ short CryGetAsyncKeyState(int vKey) return 0; } -#if defined(LINUX) || defined(APPLE) || defined(DEFINE_CRY_INTERLOCKED_INCREMENT) -//[K01]: http://www.memoryhole.net/kyle/2007/05/atomic_incrementing.html -//http://forums.devx.com/archive/index.php/t-160558.html -////////////////////////////////////////////////////////////////////////// -DLL_EXPORT LONG CryInterlockedIncrement(LONG volatile* lpAddend) -{ - /*int r; - __asm__ __volatile__ ( - "lock ; xaddl %0, (%1) \n\t" - : "=r" (r) - : "r" (lpAddend), "0" (1) - : "memory" - ); - return (LONG) (r + 1); */// add, since we get the original value back. - return __sync_fetch_and_add(lpAddend, 1) + 1; -} - -////////////////////////////////////////////////////////////////////////// -DLL_EXPORT LONG CryInterlockedDecrement(LONG volatile* lpAddend) -{ - /*int r; - __asm__ __volatile__ ( - "lock ; xaddl %0, (%1) \n\t" - : "=r" (r) - : "r" (lpAddend), "0" (-1) - : "memory" - ); - return (LONG) (r - 1); */// subtract, since we get the original value back. - return __sync_fetch_and_sub(lpAddend, 1) - 1; -} - -////////////////////////////////////////////////////////////////////////// -DLL_EXPORT LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value) -{ - /* LONG r; - __asm__ __volatile__ ( - #if defined(LINUX64) || defined(APPLE) // long is 64 bits on amd64. - "lock ; xaddq %0, (%1) \n\t" - #else - "lock ; xaddl %0, (%1) \n\t" - #endif - : "=r" (r) - : "r" (lpAddend), "0" (Value) - : "memory" - ); - return r;*/ - return __sync_fetch_and_add(lpAddend, Value); -} - -DLL_EXPORT LONG CryInterlockedOr(LONG volatile* Destination, LONG Value) -{ - return __sync_fetch_and_or(Destination, Value); -} - -DLL_EXPORT LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand) -{ - return __sync_val_compare_and_swap(dst, comperand, exchange); - /*LONG r; - __asm__ __volatile__ ( - #if defined(LINUX64) || defined(APPLE) // long is 64 bits on amd64. - "lock ; cmpxchgq %2, (%1) \n\t" - #else - "lock ; cmpxchgl %2, (%1) \n\t" - #endif - : "=a" (r) - : "r" (dst), "r" (exchange), "0" (comperand) - : "memory" - ); - return r;*/ -} - - -DLL_EXPORT void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand) -{ - return __sync_val_compare_and_swap(dst, comperand, exchange); - //return (void*)CryInterlockedCompareExchange((long volatile*)dst, (long)exchange, (long)comperand); -} - -DLL_EXPORT void* CryInterlockedExchangePointer(void* volatile* dst, void* exchange) -{ - __sync_synchronize(); - return __sync_lock_test_and_set(dst, exchange); - //return (void*)CryInterlockedCompareExchange((long volatile*)dst, (long)exchange, (long)comperand); -} +#if defined(LINUX) || defined(APPLE) threadID CryGetCurrentThreadId() { diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index d9d4493632..4c1440c67d 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -96,7 +96,6 @@ set(FILES LegacyAllocator.h MetaUtils.h MiniQueue.h - MultiThread.h MultiThread_Containers.h NullAudioSystem.h PNoise3.h diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 9f6e8b212d..842325af9f 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -730,10 +730,6 @@ enum ETriState typedef int socklen_t; #endif - -// Include MultiThreading support. -#include "MultiThread.h" - // In RELEASE disable printf and fprintf #if defined(_RELEASE) && !defined(RELEASE_LOGGING) #if defined(AZ_RESTRICTED_PLATFORM) diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index e16b18bc06..becd88c0b5 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -308,58 +308,6 @@ short CryGetAsyncKeyState([[maybe_unused]] int vKey) #endif } -////////////////////////////////////////////////////////////////////////// -LONG CryInterlockedIncrement(int volatile* lpAddend) -{ - return InterlockedIncrement((volatile LONG*)lpAddend); -} - -////////////////////////////////////////////////////////////////////////// -LONG CryInterlockedDecrement(int volatile* lpAddend) -{ - return InterlockedDecrement((volatile LONG*)lpAddend); -} - -////////////////////////////////////////////////////////////////////////// -LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value) -{ - return InterlockedExchangeAdd(lpAddend, Value); -} - -LONG CryInterlockedOr(LONG volatile* Destination, LONG Value) -{ - return InterlockedOr(Destination, Value); -} - -LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand) -{ - return InterlockedCompareExchange(dst, exchange, comperand); -} - -void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand) -{ - return InterlockedCompareExchangePointer(dst, exchange, comperand); -} - -void* CryInterlockedExchangePointer(void* volatile* dst, void* exchange) -{ - return InterlockedExchangePointer(dst, exchange); -} - -void CryInterlockedAdd(volatile size_t* pVal, ptrdiff_t iAdd) -{ -#if defined (PLATFORM_64BIT) -#if !defined(NDEBUG) - size_t v = (size_t) -#endif - InterlockedAdd64((volatile int64*)pVal, iAdd); -#else - size_t v = (size_t)CryInterlockedExchangeAdd((volatile long*)pVal, (long)iAdd); - v += iAdd; -#endif - assert((iAdd == 0) || (iAdd < 0 && v < v - (size_t)iAdd) || (iAdd > 0 && v > v - (size_t)iAdd)); -} - ////////////////////////////////////////////////////////////////////////// uint32 CryGetFileAttributes(const char* lpFileName) { diff --git a/Code/Legacy/CrySystem/Log.h b/Code/Legacy/CrySystem/Log.h index 447186e613..085e05e714 100644 --- a/Code/Legacy/CrySystem/Log.h +++ b/Code/Legacy/CrySystem/Log.h @@ -10,7 +10,6 @@ #pragma once #include -#include #include ////////////////////////////////////////////////////////////////////// From 04e64e274f1b8cbd927fb3942cfcee55ecb14a7b Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:53:41 -0700 Subject: [PATCH 031/101] Fix typo in copypasting... Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h index a63e782146..7e6bb3d7b4 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h @@ -27,8 +27,8 @@ namespace AZ MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&)); MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(const PreMergeEventCallback&)); MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(PreMergeEventCallback&&)); - MOCK_METHOD1(PostMergeEventHandler, PreMergeEventHandler(const PostMergeEventCallback&)); - MOCK_METHOD1(PostMergeEventHandler, PreMergeEventHandler(PostMergeEventCallback&&)); + MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(const PostMergeEventCallback&)); + MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(PostMergeEventCallback&&)); MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view)); MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view)); From 8dd44075c85a98214dfa679e330de30cf6c5792f Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 21:04:19 -0700 Subject: [PATCH 032/101] [redcode/crythread-2nd-pass] post merge include fixes Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/GameEngine.h | 1 - Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp | 1 - .../Platform/Android/GridMate/Session/LANSession_Android.cpp | 1 + Code/Legacy/CryCommon/CryLibrary.h | 2 +- Code/Legacy/CryCommon/IFunctorBase.h | 2 -- Code/Legacy/CryCommon/IMaterial.h | 1 - Code/Legacy/CryCommon/smartptr.h | 1 - 7 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Code/Editor/GameEngine.h b/Code/Editor/GameEngine.h index 64fd20a9aa..4d183cc38e 100644 --- a/Code/Editor/GameEngine.h +++ b/Code/Editor/GameEngine.h @@ -20,7 +20,6 @@ #include "LogFile.h" #include "CryListenerSet.h" #include "Util/ModalWindowDismisser.h" -#include #endif class CStartupLogoDialog; diff --git a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp index f8f4711631..34514b8ef1 100644 --- a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp +++ b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp @@ -9,7 +9,6 @@ #include "CryFile.h" #include "PerforceSourceControl.h" #include "PasswordDlg.h" -#include #include #include diff --git a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp index 05fb56dfc1..3fa2a369a6 100644 --- a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp +++ b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace GridMate { diff --git a/Code/Legacy/CryCommon/CryLibrary.h b/Code/Legacy/CryCommon/CryLibrary.h index 787085af00..a034a2a04b 100644 --- a/Code/Legacy/CryCommon/CryLibrary.h +++ b/Code/Legacy/CryCommon/CryLibrary.h @@ -49,7 +49,7 @@ */ #include -#include +#include #include #define INJECT_ENVIRONMENT_FUNCTION "InjectEnvironment" diff --git a/Code/Legacy/CryCommon/IFunctorBase.h b/Code/Legacy/CryCommon/IFunctorBase.h index a64e811516..6fb3a5d981 100644 --- a/Code/Legacy/CryCommon/IFunctorBase.h +++ b/Code/Legacy/CryCommon/IFunctorBase.h @@ -14,8 +14,6 @@ #define CRYINCLUDE_CRYCOMMON_IFUNCTORBASE_H #pragma once -#include - #include // Base class for functor storage. diff --git a/Code/Legacy/CryCommon/IMaterial.h b/Code/Legacy/CryCommon/IMaterial.h index c484c10482..83f9140be7 100644 --- a/Code/Legacy/CryCommon/IMaterial.h +++ b/Code/Legacy/CryCommon/IMaterial.h @@ -37,7 +37,6 @@ struct IRenderMesh; #include #include #include -#include #ifdef MAX_SUB_MATERIALS // This checks that the values are in sync in the different files. diff --git a/Code/Legacy/CryCommon/smartptr.h b/Code/Legacy/CryCommon/smartptr.h index 0ff6a61b60..baf51d5030 100644 --- a/Code/Legacy/CryCommon/smartptr.h +++ b/Code/Legacy/CryCommon/smartptr.h @@ -13,7 +13,6 @@ #include #include -#include void CryFatalError(const char*, ...) PRINTF_PARAMS(1, 2); #if defined(APPLE) From 3fc0a197a0afa0206593aad40983e95f7917e13e Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 21:32:02 -0700 Subject: [PATCH 033/101] [redcode/crythread-2nd-pass] removed re-implemented stubs of Windows synchapi.h functions and CrySimpleThread define in platform.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/Linux_Win32Wrapper.h | 55 ----------- Code/Legacy/CryCommon/WinBase.cpp | 104 --------------------- Code/Legacy/CryCommon/platform.h | 10 +- 3 files changed, 1 insertion(+), 168 deletions(-) diff --git a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h index 7b556b0f62..ffdf3fe998 100644 --- a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h +++ b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h @@ -413,67 +413,12 @@ inline void SetLastError(DWORD dwErrCode) { errno = dwErrCode; } ////////////////////////////////////////////////////////////////////////// extern threadID GetCurrentThreadId(); -////////////////////////////////////////////////////////////////////////// -extern HANDLE CreateEvent( - LPSECURITY_ATTRIBUTES lpEventAttributes, - BOOL bManualReset, - BOOL bInitialState, - LPCSTR lpName - ); - ////////////////////////////////////////////////////////////////////////// extern DWORD Sleep(DWORD dwMilliseconds); ////////////////////////////////////////////////////////////////////////// extern DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable); -////////////////////////////////////////////////////////////////////////// -extern DWORD WaitForSingleObjectEx( - HANDLE hHandle, - DWORD dwMilliseconds, - BOOL bAlertable); - -////////////////////////////////////////////////////////////////////////// -extern DWORD WaitForMultipleObjectsEx( - DWORD nCount, - const HANDLE* lpHandles, - BOOL bWaitAll, - DWORD dwMilliseconds, - BOOL bAlertable); - -////////////////////////////////////////////////////////////////////////// -extern DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); - -////////////////////////////////////////////////////////////////////////// -extern BOOL SetEvent(HANDLE hEvent); - -////////////////////////////////////////////////////////////////////////// -extern BOOL ResetEvent(HANDLE hEvent); - -////////////////////////////////////////////////////////////////////////// -extern HANDLE CreateMutex( - LPSECURITY_ATTRIBUTES lpMutexAttributes, - BOOL bInitialOwner, - LPCSTR lpName - ); - -////////////////////////////////////////////////////////////////////////// -extern BOOL ReleaseMutex(HANDLE hMutex); - -////////////////////////////////////////////////////////////////////////// -typedef DWORD (* PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter); -typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; - -////////////////////////////////////////////////////////////////////////// -extern HANDLE CreateThread( - LPSECURITY_ATTRIBUTES lpThreadAttributes, - SIZE_T dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId - ); - extern BOOL GetComputerName(LPSTR lpBuffer, LPDWORD lpnSize); //required for CryOnline extern DWORD GetCurrentProcessId(void); diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 732920f890..ae646e9e1c 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -923,21 +923,6 @@ threadID GetCurrentThreadId() } #endif -////////////////////////////////////////////////////////////////////////// -HANDLE CreateEvent -( - LPSECURITY_ATTRIBUTES lpEventAttributes, - BOOL bManualReset, - BOOL bInitialState, - LPCSTR lpName -) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "CreateEvent not implemented yet"); - return 0; -} - - ////////////////////////////////////////////////////////////////////////// DWORD Sleep(DWORD dwMilliseconds) { @@ -1003,95 +988,6 @@ DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable) return 0; } -////////////////////////////////////////////////////////////////////////// -DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "WaitForSingleObjectEx not implemented yet"); - return 0; -} - -#if 0 -////////////////////////////////////////////////////////////////////////// -DWORD WaitForMultipleObjectsEx( - DWORD nCount, - const HANDLE* lpHandles, - BOOL bWaitAll, - DWORD dwMilliseconds, - BOOL bAlertable) -{ - //TODO: implement - return 0; -} -#endif - -////////////////////////////////////////////////////////////////////////// -DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "WaitForSingleObject not implemented yet"); - return 0; -} - -////////////////////////////////////////////////////////////////////////// -BOOL SetEvent(HANDLE hEvent) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "SetEvent not implemented yet"); - return TRUE; -} - -////////////////////////////////////////////////////////////////////////// -BOOL ResetEvent(HANDLE hEvent) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "ResetEvent not implemented yet"); - return TRUE; -} - -////////////////////////////////////////////////////////////////////////// -HANDLE CreateMutex -( - LPSECURITY_ATTRIBUTES lpMutexAttributes, - BOOL bInitialOwner, - LPCSTR lpName -) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "CreateMutex not implemented yet"); - return 0; -} - -////////////////////////////////////////////////////////////////////////// -BOOL ReleaseMutex(HANDLE hMutex) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "ReleaseMutex not implemented yet"); - return TRUE; -} - -////////////////////////////////////////////////////////////////////////// - - -typedef DWORD (* PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter); -typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; - -////////////////////////////////////////////////////////////////////////// -HANDLE CreateThread -( - LPSECURITY_ATTRIBUTES lpThreadAttributes, - SIZE_T dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId -) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "CreateThread not implemented yet"); - return 0; -} - #if defined(LINUX) || defined(APPLE) BOOL GetComputerName(LPSTR lpBuffer, LPDWORD lpnSize) { diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 38c0ec7eb5..1b541a293e 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -142,14 +142,6 @@ #endif #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(LINUX) || defined(APPLE) - #if !defined(_DEBUG) - #define SIMPLE_THREAD_STACK_SIZE_KB (256) - #else - #define SIMPLE_THREAD_STACK_SIZE_KB (256 * 4) - #endif -#else - #define SIMPLE_THREAD_STACK_SIZE_KB (32) #endif #include @@ -198,7 +190,7 @@ #elif defined(ANDROID) #include "AndroidSpecific.h" #elif defined(IOS) - #include "iOSSpecific.h" + #include "iOSSpecific.h" #endif #endif From 5fd2d8e7eedac494aab05a17c7e2ee0694f5b74a Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 12 Aug 2021 10:48:09 -0500 Subject: [PATCH 034/101] updating comments Signed-off-by: Guthrie Adams --- .../Code/Include/Atom/Document/MaterialDocumentRequestBus.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h index 23b5749554..515cc44edc 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h @@ -93,10 +93,10 @@ namespace MaterialEditor //! Close document and reset its data virtual bool Close() = 0; - //! document is loaded + //! Document is loaded virtual bool IsOpen() const = 0; - //! document has changes pending + //! Document has changes pending virtual bool IsModified() const = 0; //! Can the document be saved From bbe6ff7b905e1d6b02fd2bfd00d2aa9252bc60d8 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:55:32 -0700 Subject: [PATCH 035/101] [redcode/crythread-2nd-pass] re-add LARGE_INTEGER definition to AppleSpecific.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/AppleSpecific.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index c572250b26..ec7cd8306e 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -458,6 +458,21 @@ typedef HANDLE HMENU; #endif //__cplusplus +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + long long QuadPart; +} LARGE_INTEGER; + extern bool QueryPerformanceCounter(LARGE_INTEGER*); extern bool QueryPerformanceFrequency(LARGE_INTEGER* frequency); From 28c477997d9e97564424c6afbeccaa915b2bf8b1 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:58:41 -0700 Subject: [PATCH 036/101] [redcode/crythread-2nd-pass] fixed missing iOS include Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp index 05fb56dfc1..3fa2a369a6 100644 --- a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp +++ b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace GridMate { From 72e99dd52b83272f0b57fd48015ead570cdb7dcb Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 11:02:44 -0700 Subject: [PATCH 037/101] [redcode/crythread-2nd-pass] removed platform.h include hack linked to CryThread.h for apple platforms in ILog.h and ISystem.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/ILog.h | 7 ------- Code/Legacy/CryCommon/ISystem.h | 7 ------- 2 files changed, 14 deletions(-) diff --git a/Code/Legacy/CryCommon/ILog.h b/Code/Legacy/CryCommon/ILog.h index e71e1f036d..23257ea59b 100644 --- a/Code/Legacy/CryCommon/ILog.h +++ b/Code/Legacy/CryCommon/ILog.h @@ -6,13 +6,6 @@ * */ - -// In Mac, including ILog without including platform.h first fails because platform.h -// includes CryThread.h which includes CryThread_pthreads.h which uses ILog. -// So plaform.h needs the contents of ILog.h. -// By including platform.h outside of the guard, we give platform.h the right include order -#include - #ifndef CRYINCLUDE_CRYCOMMON_ILOG_H #define CRYINCLUDE_CRYCOMMON_ILOG_H #pragma once diff --git a/Code/Legacy/CryCommon/ISystem.h b/Code/Legacy/CryCommon/ISystem.h index e0996fc927..ff72c2e60f 100644 --- a/Code/Legacy/CryCommon/ISystem.h +++ b/Code/Legacy/CryCommon/ISystem.h @@ -6,13 +6,6 @@ * */ - -// In Mac, including ISystem without including platform.h first fails because platform.h -// includes CryThread.h which includes CryThread_pthreads.h which uses ISystem (gEnv). -// So plaform.h needs the contents of ISystem.h. -// By including platform.h outside of the guard, we give platform.h the right include order -#include // Needed for LARGE_INTEGER (for consoles). - #ifndef CRYINCLUDE_CRYCOMMON_ISYSTEM_H #define CRYINCLUDE_CRYCOMMON_ISYSTEM_H #pragma once From cc3d2e9969cfc2f3ba00ebeaa9405d1d1886b37c Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 12:40:03 -0700 Subject: [PATCH 038/101] [redcode/crythread-2nd-pass] replaced instances of AZStd::lock_guard<> with AZStd::scoped_lock as per feedback Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 3 +-- Code/Editor/GameExporter.cpp | 2 +- Code/Editor/IEditorImpl.cpp | 6 +++--- .../PerforcePlugin/PerforceSourceControl.cpp | 2 +- Code/Legacy/CryCommon/CryAssert_Linux.h | 2 +- Code/Legacy/CrySystem/DebugCallStack.cpp | 6 +++--- Code/Legacy/CrySystem/Log.cpp | 8 ++++---- .../RemoteConsole/Core/RemoteConsoleCore.cpp | 17 +++++++++-------- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 25a6313efe..8444f81317 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -938,10 +938,9 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app) QObject::connect(splashScreen, &QObject::destroyed, splashScreen, [=] { - g_splashScreenStateLock.lock(); + AZStd::scoped_lock lock(g_splashScreenStateLock); g_pInitializeUIInfo = nullptr; g_splashScreen = nullptr; - g_splashScreenStateLock.unlock(); }); } diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 3cd64f9fed..415103e10d 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -136,7 +136,7 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE m_settings.SetHiQuality(); } - AZStd::lock_guard autoLock(CGameEngine::GetPakModifyMutex()); + AZStd::scoped_lock autoLock(CGameEngine::GetPakModifyMutex()); // Close this pak file. if (!CloseLevelPack(m_levelPak, true)) diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index 7800c7943e..1459139f66 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -252,7 +252,7 @@ void CEditorImpl::Uninitialize() void CEditorImpl::UnloadPlugins() { - AZStd::lock_guard lock(m_pluginMutex); + AZStd::scoped_lock lock(m_pluginMutex); // Flush core buses. We're about to unload DLLs and need to ensure we don't have module-owned functions left behind. AZ::Data::AssetBus::ExecuteQueuedEvents(); @@ -273,7 +273,7 @@ void CEditorImpl::UnloadPlugins() void CEditorImpl::LoadPlugins() { - AZStd::lock_guard lock(m_pluginMutex); + AZStd::scoped_lock lock(m_pluginMutex); static const QString editor_plugins_folder("EditorPlugins"); @@ -1460,7 +1460,7 @@ void CEditorImpl::UnregisterNotifyListener(IEditorNotifyListener* listener) ISourceControl* CEditorImpl::GetSourceControl() { - AZStd::lock_guard lock(m_pluginMutex); + AZStd::scoped_lock lock(m_pluginMutex); if (m_pSourceControl) { diff --git a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp index 34514b8ef1..10c43c3d1b 100644 --- a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp +++ b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp @@ -56,7 +56,7 @@ void CPerforceSourceControl::ShowSettings() void CPerforceSourceControl::SetSourceControlState(SourceControlState state) { - AZStd::lock_guard lock(g_cPerforceValues); + AZStd::scoped_lock lock(g_cPerforceValues); switch (state) { diff --git a/Code/Legacy/CryCommon/CryAssert_Linux.h b/Code/Legacy/CryCommon/CryAssert_Linux.h index 355194caba..112c60a80c 100644 --- a/Code/Legacy/CryCommon/CryAssert_Linux.h +++ b/Code/Legacy/CryCommon/CryAssert_Linux.h @@ -80,7 +80,7 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts) { - AZStd::lock_guard lk (lock); + AZStd::scoped_lock lk(lock); snprintf(gs_command_str, max_len, "xterm -geometry 100x20 -n 'Assert Dialog [Linux Launcher]' -T 'Assert Dialog [Linux Launcher]' -e 'BinLinux/assert_term \"%s\" \"%s\" %d \"%s\"; echo \"$?\" > .assert_return'", szCondition, (file_len > 60) ? szFile + (file_len - 61) : szFile, line, gs_szMessage); int ret = system(gs_command_str); diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp index 640afe8da1..cdfc5de21e 100644 --- a/Code/Legacy/CrySystem/DebugCallStack.cpp +++ b/Code/Legacy/CrySystem/DebugCallStack.cpp @@ -154,13 +154,13 @@ void DebugCallStack::SetUserDialogEnable(const bool bUserDialogEnable) DWORD g_idDebugThreads[10]; const char* g_nameDebugThreads[10]; int g_nDebugThreads = 0; -AZStd::spin_mutex g_lockThreadDumpList = 0; +AZStd::spin_mutex g_lockThreadDumpList; void MarkThisThreadForDebugging(const char* name) { EBUS_EVENT(AZ::Debug::EventTraceDrillerSetupBus, SetThreadName, AZStd::this_thread::get_id(), name); - AZStd::lock_guard lock(g_lockThreadDumpList); + AZStd::scoped_lock lock(g_lockThreadDumpList); DWORD id = GetCurrentThreadId(); if (g_nDebugThreads == sizeof(g_idDebugThreads) / sizeof(g_idDebugThreads[0])) { @@ -180,7 +180,7 @@ void MarkThisThreadForDebugging(const char* name) void UnmarkThisThreadFromDebugging() { - AZStd::lock_guard lock(g_lockThreadDumpList); + AZStd::scoped_lock lock(g_lockThreadDumpList); DWORD id = GetCurrentThreadId(); for (int i = g_nDebugThreads - 1; i >= 0; i--) { diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index 2417c58d4f..d248274b1d 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -810,13 +810,13 @@ void CLog::PushAssetScopeName(const char* sAssetType, const char* sName) SAssetScopeInfo as; as.sType = sAssetType; as.sName = sName; - AZStd::lock_guard scope_lock(m_assetScopeQueueLock); + AZStd::scoped_lock scope_lock(m_assetScopeQueueLock); m_assetScopeQueue.push_back(as); } void CLog::PopAssetScopeName() { - AZStd::lock_guard scope_lock(m_assetScopeQueueLock); + AZStd::scoped_lock scope_lock(m_assetScopeQueueLock); assert(!m_assetScopeQueue.empty()); if (!m_assetScopeQueue.empty()) { @@ -827,7 +827,7 @@ void CLog::PopAssetScopeName() ////////////////////////////////////////////////////////////////////////// const char* CLog::GetAssetScopeString() { - AZStd::lock_guard scope_lock(m_assetScopeQueueLock); + AZStd::scoped_lock scope_lock(m_assetScopeQueueLock); m_assetScopeString.clear(); for (size_t i = 0; i < m_assetScopeQueue.size(); i++) @@ -1450,7 +1450,7 @@ void CLog::Update() { if (!m_threadSafeMsgQueue.empty()) { - AZStd::lock_guard lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it) + AZStd::scoped_lock lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it) // Must be called from main thread SLogMsg msg; while (m_threadSafeMsgQueue.try_pop(msg)) diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp index b59f697467..5a137d1664 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp @@ -133,19 +133,20 @@ void SRemoteServer::StopServer() AZ::AzSock::CloseSocket(m_socket); m_socket = SOCKET_ERROR; { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { it->pClient->StopClient(); } } AZStd::unique_lock lock(m_mutex); - m_stopCondition.wait(lock, [this] { return m_clients.empty(); });} + m_stopCondition.wait(lock, [this] { return m_clients.empty(); }); +} ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::ClientDone(SRemoteClient* pClient) { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { if (it->pClient == pClient) @@ -253,7 +254,7 @@ void SRemoteServer::Run() continue; } - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); SRemoteClient* pClient = new SRemoteClient(this); m_clients.push_back(SRemoteClientInfo(pClient)); pClient->StartClient(sClient); @@ -266,7 +267,7 @@ void SRemoteServer::Run() ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::AddEvent(IRemoteEvent* pEvent) { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { it->pEvents->push_back(pEvent->Clone()); @@ -277,7 +278,7 @@ void SRemoteServer::AddEvent(IRemoteEvent* pEvent) ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::GetEvents(TEventBuffer& buffer) { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); buffer = m_eventBuffer; m_eventBuffer.clear(); } @@ -287,7 +288,7 @@ bool SRemoteServer::WriteBuffer(SRemoteClient* pClient, char* buffer, int& size { IRemoteEvent* pEvent = nullptr; { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { if (it->pClient == pClient) @@ -330,7 +331,7 @@ bool SRemoteServer::ReadBuffer(const char* buffer, int data) { if (event->GetType() != eCET_Noop) { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); m_eventBuffer.push_back(event); } else From c3ee798acc817aadc7b1bab8e51e67c3c31cfbf4 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 14:18:10 -0700 Subject: [PATCH 039/101] [redcode/crythread-2nd-pass] updated condition variable handling in Remote Console runtime to cut out extra unlock/lock Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp index 5a137d1664..a4e7bd24fa 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp @@ -132,14 +132,12 @@ void SRemoteServer::StopServer() m_bAcceptClients = false; AZ::AzSock::CloseSocket(m_socket); m_socket = SOCKET_ERROR; - { - AZStd::scoped_lock lock(m_mutex); - for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) - { - it->pClient->StopClient(); - } - } + AZStd::unique_lock lock(m_mutex); + for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) + { + it->pClient->StopClient(); + } m_stopCondition.wait(lock, [this] { return m_clients.empty(); }); } From 11d5009f466d394b4f71a3f791f7073e2b65a00f Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 12 Aug 2021 16:31:39 -0500 Subject: [PATCH 040/101] Fixed creating entities in the viewport logic to use hit test detection. Signed-off-by: Chris Galvan --- Code/Editor/EditorViewportWidget.cpp | 3 +- .../SandboxIntegration.cpp | 2 +- Code/Editor/Viewport.cpp | 42 +++++++++++-------- Code/Editor/Viewport.h | 2 + 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 9ef20e02fb..28e8cce33e 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2697,8 +2697,7 @@ void EditorViewportWidget::RestoreViewportAfterGameMode() QString( tr("When leaving \" Game Mode \" the engine will automatically restore your camera position to the default position before you " "had entered Game mode.

If you dislike this setting you can always change this anytime in the global " - "preferences.

")) - .arg(EditorPreferencesGeneralRestoreViewportCameraSettingName); + "preferences.

")); QString restoreOnExitGameModePopupDisabledRegKey("Editor/AutoHide/ViewportCameraRestoreOnExitGameMode"); // Read the popup disabled registry value diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 2ed2a30f08..66c57361be 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -1452,7 +1452,7 @@ void SandboxIntegrationManager::ContextMenu_NewEntity() if (view) { const QPoint viewPoint(m_contextMenuViewPoint.GetX(), m_contextMenuViewPoint.GetY()); - worldPosition = LYVec3ToAZVec3(view->SnapToGrid(view->ViewToWorld(viewPoint))); + worldPosition = view->GetHitLocation(viewPoint); } CreateNewEntityAtPosition(worldPosition); diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 2bc1b21216..873f555c80 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -46,24 +46,7 @@ void QtViewport::BuildDragDropContext(AzQtComponents::ViewportDragContext& conte PreWidgetRendering(); // required so that the current render cam is set. - Vec3 pos = Vec3(ZERO); - HitContext hit; - if (HitTest(pt, hit)) - { - pos = hit.raySrc + hit.rayDir * hit.dist; - pos = SnapToGrid(pos); - } - else - { - bool hitTerrain; - pos = ViewToWorld(pt, &hitTerrain); - if (hitTerrain) - { - pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y); - } - pos = SnapToGrid(pos); - } - context.m_hitLocation = AZ::Vector3(pos.x, pos.y, pos.z); + context.m_hitLocation = GetHitLocation(pt); PostWidgetRendering(); } @@ -1154,6 +1137,29 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) return false; } +AZ::Vector3 QtViewport::GetHitLocation(const QPoint& point) +{ + Vec3 pos = Vec3(ZERO); + HitContext hit; + if (HitTest(point, hit)) + { + pos = hit.raySrc + hit.rayDir * hit.dist; + pos = SnapToGrid(pos); + } + else + { + bool hitTerrain; + pos = ViewToWorld(point, &hitTerrain); + if (hitTerrain) + { + pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y); + } + pos = SnapToGrid(pos); + } + + return AZ::Vector3(pos.x, pos.y, pos.z); +} + ////////////////////////////////////////////////////////////////////////// void QtViewport::SetZoomFactor(float fZoomFactor) { diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index 823b8c77b1..6b5bfb5c34 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -201,6 +201,7 @@ public: //! Performs hit testing of 2d point in view to find which object hit. virtual bool HitTest(const QPoint& point, HitContext& hitInfo) = 0; + virtual AZ::Vector3 GetHitLocation(const QPoint& point) = 0; virtual void MakeConstructionPlane(int axis) = 0; @@ -436,6 +437,7 @@ public: //! Performs hit testing of 2d point in view to find which object hit. bool HitTest(const QPoint& point, HitContext& hitInfo) override; + AZ::Vector3 GetHitLocation(const QPoint& point) override; //! Do 2D hit testing of line in world space. // pToCameraDistance is an optional output parameter in which distance from the camera to the line is returned. From 3fe5901a77519ceb135243f58d70144096ba0848 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Wed, 11 Aug 2021 23:25:41 -0700 Subject: [PATCH 041/101] Fixing a crash when unparenting prefab instance in a new level Signed-off-by: mnaumov --- .../PrefabEditorEntityOwnershipService.cpp | 2 +- .../Prefab/PrefabPublicHandler.cpp | 36 +++++++++++++------ .../Prefab/PrefabSystemComponent.cpp | 18 ++++++++++ .../Prefab/PrefabSystemComponent.h | 2 ++ .../Prefab/PrefabSystemComponentInterface.h | 2 ++ 5 files changed, 48 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index b5cf5fb878..127f04424b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -202,7 +202,7 @@ namespace AzToolsFramework m_rootInstance->SetTemplateId(templateId); m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GenerateRelativePath(filename)); m_rootInstance->SetContainerEntityName("Level"); - m_prefabSystemComponent->PropagateTemplateChanges(templateId); + m_prefabSystemComponent->PropagateTemplateChangesDown(templateId); return true; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 69efe33d72..85fe30c252 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -482,22 +482,36 @@ namespace AzToolsFramework AZStd::unique_ptr& sourceInstance, TemplateId targetTemplateId, UndoSystem::URSequencePoint* undoBatch) { LinkReference nestedInstanceLink = m_prefabSystemComponentInterface->FindLink(sourceInstance->GetLinkId()); - AZ_Assert( - nestedInstanceLink.has_value(), - "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); + if (!nestedInstanceLink) + { + AZ_Assert( + false, + "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); + return; + } PrefabDomReference nestedInstanceLinkDom = nestedInstanceLink->get().GetLinkDom(); - AZ_Assert( - nestedInstanceLinkDom.has_value(), - "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " - "CreatePrefab operation."); + + if (!nestedInstanceLinkDom) + { + AZ_Assert( + false, + "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); + return; + } PrefabDomValueReference nestedInstanceLinkPatches = PrefabDomUtils::FindPrefabDomValue(nestedInstanceLinkDom->get(), PrefabDomUtils::PatchesName); - AZ_Assert( - nestedInstanceLinkPatches.has_value(), - "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " - "CreatePrefab operation."); + + if (!nestedInstanceLinkPatches) + { + AZ_Assert( + false, + "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); + return; + } PrefabDom patchesCopyForUndoSupport; patchesCopyForUndoSupport.CopyFrom(nestedInstanceLinkPatches->get(), patchesCopyForUndoSupport.GetAllocator()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index bfdb6b79f2..b75f50198c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -153,6 +153,24 @@ namespace AzToolsFramework } } + void PrefabSystemComponent::PropagateTemplateChangesDown(TemplateId templateId, InstanceOptionalReference instanceToExclude) + { + PropagateTemplateChanges(templateId, instanceToExclude); + + auto templateIterator = m_templateIdMap.find(templateId); + if (templateIterator != m_templateIdMap.end()) + { + for (LinkId linkId : templateIterator->second.GetLinks()) + { + auto linkIterator = m_linkIdMap.find(linkId); + if (linkIterator != m_linkIdMap.end()) + { + PropagateTemplateChangesDown(linkIterator->second.GetSourceTemplateId(), instanceToExclude); + } + } + } + } + void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) { auto templateToUpdate = FindTemplate(templateId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index 04457b5a97..ccc17af133 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -213,6 +213,8 @@ namespace AzToolsFramework void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; + void PropagateTemplateChangesDown(TemplateId templateIdd, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; + /** * Updates all Instances owned by a Template. * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 0c758a21af..9792ec0fab 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -53,6 +53,8 @@ namespace AzToolsFramework virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; + //! Propagates template changes recursively down to its dependents + virtual void PropagateTemplateChangesDown(TemplateId templateIdd, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; virtual AZStd::unique_ptr InstantiatePrefab(AZ::IO::PathView filePath) = 0; virtual AZStd::unique_ptr InstantiatePrefab(const TemplateId& templateId) = 0; From 8f21563ba95d042fc8263eacdd9821c4a93ab4f9 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Thu, 12 Aug 2021 14:37:01 -0700 Subject: [PATCH 042/101] Undoing old changes and storing linkId to prefabDom Signed-off-by: mnaumov --- .../PrefabEditorEntityOwnershipService.cpp | 2 +- .../Prefab/Instance/InstanceSerializer.cpp | 7 +++++++ .../Prefab/PrefabSystemComponent.cpp | 18 ------------------ .../Prefab/PrefabSystemComponent.h | 2 -- .../Prefab/PrefabSystemComponentInterface.h | 2 -- 5 files changed, 8 insertions(+), 23 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 127f04424b..b5cf5fb878 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -202,7 +202,7 @@ namespace AzToolsFramework m_rootInstance->SetTemplateId(templateId); m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GenerateRelativePath(filename)); m_rootInstance->SetContainerEntityName("Level"); - m_prefabSystemComponent->PropagateTemplateChangesDown(templateId); + m_prefabSystemComponent->PropagateTemplateChanges(templateId); return true; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp index b5a354ee74..89e0136b12 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp @@ -81,6 +81,13 @@ namespace AzToolsFramework result.Combine(resultInstances); } + { + AZ::ScopedContextPath subPathSource(context, "m_linkId"); + + result = ContinueStoringToJsonObjectField( + outputValue, "LinkId", &(instance->m_linkId), &InvalidLinkId, azrtti_typeid(), context); + } + return context.Report(result, result.GetProcessing() == JSR::Processing::Completed ? "Successfully stored Instance information for Prefab." : "Failed to store Instance information for Prefab."); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index b75f50198c..bfdb6b79f2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -153,24 +153,6 @@ namespace AzToolsFramework } } - void PrefabSystemComponent::PropagateTemplateChangesDown(TemplateId templateId, InstanceOptionalReference instanceToExclude) - { - PropagateTemplateChanges(templateId, instanceToExclude); - - auto templateIterator = m_templateIdMap.find(templateId); - if (templateIterator != m_templateIdMap.end()) - { - for (LinkId linkId : templateIterator->second.GetLinks()) - { - auto linkIterator = m_linkIdMap.find(linkId); - if (linkIterator != m_linkIdMap.end()) - { - PropagateTemplateChangesDown(linkIterator->second.GetSourceTemplateId(), instanceToExclude); - } - } - } - } - void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) { auto templateToUpdate = FindTemplate(templateId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index ccc17af133..04457b5a97 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -213,8 +213,6 @@ namespace AzToolsFramework void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; - void PropagateTemplateChangesDown(TemplateId templateIdd, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; - /** * Updates all Instances owned by a Template. * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 9792ec0fab..0c758a21af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -53,8 +53,6 @@ namespace AzToolsFramework virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; - //! Propagates template changes recursively down to its dependents - virtual void PropagateTemplateChangesDown(TemplateId templateIdd, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; virtual AZStd::unique_ptr InstantiatePrefab(AZ::IO::PathView filePath) = 0; virtual AZStd::unique_ptr InstantiatePrefab(const TemplateId& templateId) = 0; From c8cd3b1923971bf0b17b0b0fbcb7ad8d44c699ea Mon Sep 17 00:00:00 2001 From: mnaumov Date: Thu, 12 Aug 2021 14:39:15 -0700 Subject: [PATCH 043/101] reverting another file Signed-off-by: mnaumov --- .../Prefab/PrefabPublicHandler.cpp | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 85fe30c252..69efe33d72 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -482,36 +482,22 @@ namespace AzToolsFramework AZStd::unique_ptr& sourceInstance, TemplateId targetTemplateId, UndoSystem::URSequencePoint* undoBatch) { LinkReference nestedInstanceLink = m_prefabSystemComponentInterface->FindLink(sourceInstance->GetLinkId()); - if (!nestedInstanceLink) - { - AZ_Assert( - false, - "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); - return; - } + AZ_Assert( + nestedInstanceLink.has_value(), + "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); PrefabDomReference nestedInstanceLinkDom = nestedInstanceLink->get().GetLinkDom(); - - if (!nestedInstanceLinkDom) - { - AZ_Assert( - false, - "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " - "CreatePrefab operation."); - return; - } + AZ_Assert( + nestedInstanceLinkDom.has_value(), + "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); PrefabDomValueReference nestedInstanceLinkPatches = PrefabDomUtils::FindPrefabDomValue(nestedInstanceLinkDom->get(), PrefabDomUtils::PatchesName); - - if (!nestedInstanceLinkPatches) - { - AZ_Assert( - false, - "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " - "CreatePrefab operation."); - return; - } + AZ_Assert( + nestedInstanceLinkPatches.has_value(), + "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); PrefabDom patchesCopyForUndoSupport; patchesCopyForUndoSupport.CopyFrom(nestedInstanceLinkPatches->get(), patchesCopyForUndoSupport.GetAllocator()); From 8f05c7aa2f9d63a46e5350a19587cf273492eee5 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:42:18 -0700 Subject: [PATCH 044/101] Several build fixes --- .../Mac/AzFramework/Windowing/NativeWindow_Mac.mm | 2 +- .../iOS/AzFramework/Windowing/NativeWindow_ios.mm | 2 +- .../GridMate/Session/LANSession_Android.cpp | 1 + .../iOS/GridMate/Session/LANSession_iOS.cpp | 1 + Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm | 1 + .../Platform/Windows/Launcher_Windows.cpp | 1 + Code/Legacy/CryCommon/AppleSpecific.h | 15 +++++++++++++++ Code/Legacy/CryCommon/CryLibrary.h | 2 +- Code/Legacy/CryCommon/MacSpecific.h | 2 ++ .../Scheduler/TestImpactProcessScheduler.cpp | 2 +- .../Enumeration/TestImpactTestEnumerator.cpp | 2 +- Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp | 1 + 12 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm index 2f9e3ab934..f9eef9170a 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm @@ -34,7 +34,7 @@ namespace AzFramework bool GetFullScreenState() const override; void SetFullScreenState(bool fullScreenState) override; bool CanToggleFullScreenState() const override { return true; } - uint32_t GetMainDisplayRefreshRate() const override; + uint32_t GetMainDisplayRefreshRate() const; private: static NSWindowStyleMask ConvertToNSWindowStyleMask(const WindowStyleMasks& styleMasks); diff --git a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm index 3c829ec055..83e176b9ef 100644 --- a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm +++ b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm @@ -27,7 +27,7 @@ namespace AzFramework const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) override; NativeWindowHandle GetWindowHandle() const override; - uint32_t GetMainDisplayRefreshRate() const override; + uint32_t GetMainDisplayRefreshRate() const; private: UIWindow* m_nativeWindow; diff --git a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp index 05fb56dfc1..3fa2a369a6 100644 --- a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp +++ b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace GridMate { diff --git a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp index 05fb56dfc1..3fa2a369a6 100644 --- a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp +++ b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace GridMate { diff --git a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm index cfba0d8aac..cbd5a043e1 100644 --- a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm @@ -10,6 +10,7 @@ #include #include <../Common/Apple/Launcher_Apple.h> #include <../Common/UnixLike/Launcher_UnixLike.h> +#include #if AZ_TESTS_ENABLED diff --git a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp index 5cc3070cdb..44426f6d01 100644 --- a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp +++ b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp @@ -9,6 +9,7 @@ #include #include +#include int APIENTRY WinMain([[maybe_unused]] HINSTANCE hInstance, [[maybe_unused]] HINSTANCE hPrevInstance, [[maybe_unused]] LPSTR lpCmdLine, [[maybe_unused]] int nCmdShow) { diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index c572250b26..cd3146403a 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -226,6 +226,21 @@ typedef uint64 __uint64; #define _PTRDIFF_T_DEFINED 1 +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + long long QuadPart; +} LARGE_INTEGER; + #define _A_RDONLY (0x01) /* Read only file */ #define _A_HIDDEN (0x02) /* Hidden file */ #define _A_SUBDIR (0x10) /* Subdirectory */ diff --git a/Code/Legacy/CryCommon/CryLibrary.h b/Code/Legacy/CryCommon/CryLibrary.h index 787085af00..a034a2a04b 100644 --- a/Code/Legacy/CryCommon/CryLibrary.h +++ b/Code/Legacy/CryCommon/CryLibrary.h @@ -49,7 +49,7 @@ */ #include -#include +#include #include #define INJECT_ENVIRONMENT_FUNCTION "InjectEnvironment" diff --git a/Code/Legacy/CryCommon/MacSpecific.h b/Code/Legacy/CryCommon/MacSpecific.h index 0533a1b556..1bc8c8a34b 100644 --- a/Code/Legacy/CryCommon/MacSpecific.h +++ b/Code/Legacy/CryCommon/MacSpecific.h @@ -26,4 +26,6 @@ typedef uint64_t threadID; +#define VK_CONTROL 0 + #endif // CRYINCLUDE_CRYCOMMON_MACSPECIFIC_H diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp index a7e20a76f7..94df662a1d 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp @@ -230,7 +230,7 @@ namespace TestImpact processInFlight.m_process = LaunchProcess(AZStd::move(processInfo)); processInFlight.m_startTime = createTime; } - catch (ProcessException& e) + catch ([[maybe_unused]] ProcessException& e) { AZ_Warning("ProcessScheduler", false, e.what()); createResult = LaunchResult::Failure; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp index e564b93f6c..756b1c75d6 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp @@ -169,7 +169,7 @@ namespace TestImpact WriteFileContents(SerializeTestEnumeration(enumeration.value()), jobInfo->GetCache()->m_file); } } - catch (const Exception& e) + catch ([[maybe_unused]] const Exception& e) { AZ_Warning("Enumerate", false, e.what()); enumerations[jobId] = AZStd::nullopt; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp index df0961564d..0065ea724e 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include From f0ff8da1d772a74c6c880c7a003ccf57f2c13473 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:51:54 -0700 Subject: [PATCH 045/101] [redcode/crythread-2nd-pass] post merge duplicates removed Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm | 2 -- Code/Legacy/CryCommon/AppleSpecific.h | 15 --------------- 2 files changed, 17 deletions(-) diff --git a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm index 3396200b87..cbd5a043e1 100644 --- a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm @@ -12,8 +12,6 @@ #include <../Common/UnixLike/Launcher_UnixLike.h> #include -#include - #if AZ_TESTS_ENABLED int main(int argc, char* argv[]) diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index 92fa318b87..cd3146403a 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -473,21 +473,6 @@ typedef HANDLE HMENU; #endif //__cplusplus -typedef union _LARGE_INTEGER -{ - struct - { - DWORD LowPart; - LONG HighPart; - }; - struct - { - DWORD LowPart; - LONG HighPart; - } u; - long long QuadPart; -} LARGE_INTEGER; - extern bool QueryPerformanceCounter(LARGE_INTEGER*); extern bool QueryPerformanceFrequency(LARGE_INTEGER* frequency); From 30fee96c435cae1276a6457d287382f610f62f23 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 12 Aug 2021 22:11:18 -0500 Subject: [PATCH 046/101] Moved material editor document system buses and system components to atom tools framework Renamed document related buses and components to have generic names Added a base document class with default implementation from which other application specific documents can be derived to work with the document system Added document factory function registration to the document system request bus so that each application can specify the type of document it creates Updated all comments and messaging to only refer to documents, not materials or material documents Updated material editor and shader management console to conform to the new buses This will provide a first pass of a common interface for a document management system that can be shared by multiple applications Corrected status bar message copy and paste errors Updated all test scripts to use the new buses Signed-off-by: Guthrie Adams --- .../atom_utils/material_editor_utils.py | 26 +- .../Document/AtomToolsDocument.h | 71 +++ .../AtomToolsDocumentNotificationBus.h} | 8 +- .../Document/AtomToolsDocumentRequestBus.h | 95 ++++ .../AtomToolsDocumentSystemRequestBus.h} | 20 +- .../AtomToolsDocumentSystemSettings.h | 30 + .../Code/Source/AtomToolsFrameworkModule.cpp | 3 + .../Source/Document/AtomToolsDocument.cpp | 154 ++++++ .../AtomToolsDocumentSystemComponent.cpp | 511 ++++++++++++++++++ .../AtomToolsDocumentSystemComponent.h | 92 ++++ .../AtomToolsDocumentSystemSettings.cpp | 47 ++ .../Code/atomtoolsframework_files.cmake | 9 + .../Core/MaterialDocumentFactoryRequestBus.h | 36 -- .../MaterialDocumentNotificationBus.h | 86 --- .../Document/MaterialDocumentRequestBus.h | 76 +-- .../Atom/Document/MaterialDocumentSettings.h | 3 +- .../Code/Source/Document/MaterialDocument.cpp | 62 +-- .../Code/Source/Document/MaterialDocument.h | 34 +- .../Document/MaterialDocumentModule.cpp | 4 +- .../Document/MaterialDocumentSettings.cpp | 5 +- .../MaterialDocumentSystemComponent.cpp | 465 +--------------- .../MaterialDocumentSystemComponent.h | 57 +- .../Code/Source/MaterialEditorApplication.cpp | 4 +- .../Code/Source/MaterialEditorApplication.h | 2 +- .../Viewport/MaterialViewportRenderer.cpp | 4 +- .../Viewport/MaterialViewportRenderer.h | 16 +- .../Viewport/MaterialViewportSettings.cpp | 2 +- .../Source/Window/MaterialBrowserWidget.cpp | 26 +- .../Source/Window/MaterialBrowserWidget.h | 8 +- .../MaterialEditorBrowserInteractions.cpp | 54 +- .../Source/Window/MaterialEditorWindow.cpp | 89 ++- .../Code/Source/Window/MaterialEditorWindow.h | 6 +- .../Window/MaterialEditorWindowSettings.cpp | 2 +- .../MaterialInspector/MaterialInspector.cpp | 46 +- .../MaterialInspector/MaterialInspector.h | 14 +- .../Window/SettingsDialog/SettingsWidget.cpp | 23 +- .../Window/SettingsDialog/SettingsWidget.h | 5 +- .../Code/materialeditordocument_files.cmake | 2 - .../Scripts/GenerateAllMaterialScreenshots.py | 4 +- ...haderManagementConsoleDocumentRequestBus.h | 55 +- ...anagementConsoleDocumentSystemRequestBus.h | 62 --- .../ShaderManagementConsoleDocument.cpp | 165 +----- .../ShaderManagementConsoleDocument.h | 54 +- .../ShaderManagementConsoleDocumentModule.cpp | 4 +- ...nagementConsoleDocumentSystemComponent.cpp | 331 +----------- ...ManagementConsoleDocumentSystemComponent.h | 35 +- .../ShaderManagementConsoleApplication.cpp | 6 +- .../ShaderManagementConsoleApplication.h | 2 +- ...erManagementConsoleBrowserInteractions.cpp | 30 +- .../ShaderManagementConsoleBrowserWidget.cpp | 43 +- .../ShaderManagementConsoleBrowserWidget.h | 7 +- .../Window/ShaderManagementConsoleWindow.cpp | 79 ++- .../Window/ShaderManagementConsoleWindow.h | 6 +- ...ShaderManagementConsoleWindowComponent.cpp | 23 +- .../Code/shadermanagementconsole_files.cmake | 2 - ...hadermanagementconsoledocument_files.cmake | 8 +- .../GenerateShaderVariantListForMaterials.py | 2 +- 57 files changed, 1397 insertions(+), 1718 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h rename Gems/Atom/Tools/{ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h => AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h} (94%) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h rename Gems/Atom/Tools/{MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h => AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h} (80%) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Core/MaterialDocumentFactoryRequestBus.h delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py index 1d72885504..ef0a592df0 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py @@ -47,28 +47,28 @@ def open_material(file_path): """ :return: uuid of material document opened """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path) + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path) def is_open(document_id): """ :return: bool """ - return materialeditor.MaterialDocumentRequestBus(bus.Event, "IsOpen", document_id) + return azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "IsOpen", document_id) def save_document(document_id): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id) + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id) def save_document_as_copy(document_id, target_path): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus( + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus( bus.Broadcast, "SaveDocumentAsCopy", document_id, target_path ) @@ -77,7 +77,7 @@ def save_document_as_child(document_id, target_path): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus( + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus( bus.Broadcast, "SaveDocumentAsChild", document_id, target_path ) @@ -86,39 +86,39 @@ def save_all(): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments") + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments") def close_document(document_id): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id) + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id) def close_all_documents(): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments") + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments") def close_all_except_selected(document_id): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id) + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id) def get_property(document_id, property_name): """ :return: property value or invalid value if the document is not open or the property_name can't be found """ - return materialeditor.MaterialDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name) + return azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name) def set_property(document_id, property_name, value): - materialeditor.MaterialDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value) + azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value) def is_pane_visible(pane_name): @@ -175,7 +175,7 @@ def wait_for_condition(function, timeout_in_seconds=1.0): with Timeout(timeout_in_seconds) as t: while True: try: - atomtools.general.idle_wait_frames(1) + azlmbr.atomtools.general.idle_wait_frames(1) except Exception: print("WARNING: Couldn't wait for frame") @@ -269,6 +269,6 @@ class ScreenshotHelper: def capture_screenshot(file_path): - return ScreenshotHelper(atomtools.general.idle_wait_frames).capture_screenshot_blocking( + return ScreenshotHelper(azlmbr.atomtools.general.idle_wait_frames).capture_screenshot_blocking( os.path.join(file_path) ) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h new file mode 100644 index 0000000000..390a08e5b1 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h @@ -0,0 +1,71 @@ +/* + * 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 +#include + +namespace AtomToolsFramework +{ + /** + * AtomToolsDocument provides an API for modifying and saving documents. + */ + class AtomToolsDocument + : public AtomToolsDocumentRequestBus::Handler + { + public: + AZ_RTTI(AtomToolsDocument, "{8992DF74-88EC-438C-B280-6E71D4C0880B}"); + AZ_CLASS_ALLOCATOR(AtomToolsDocument, AZ::SystemAllocator, 0); + AZ_DISABLE_COPY(AtomToolsDocument); + + AtomToolsDocument(); + virtual ~AtomToolsDocument(); + + const AZ::Uuid& GetId() const; + + //////////////////////////////////////////////////////////////////////// + // AtomToolsDocumentRequestBus::Handler implementation + AZStd::string_view GetAbsolutePath() const override; + AZStd::string_view GetRelativePath() const override; + const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override; + const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override; + bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; + void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; + bool Open(AZStd::string_view loadPath) override; + bool Rebuild() override; + bool Save() override; + bool SaveAsCopy(AZStd::string_view savePath) override; + bool SaveAsChild(AZStd::string_view savePath) override; + bool Close() override; + bool IsOpen() const override; + bool IsModified() const override; + bool IsSavable() const override; + bool CanUndo() const override; + bool CanRedo() const override; + bool Undo() override; + bool Redo() override; + bool BeginEdit() override; + bool EndEdit() override; + //////////////////////////////////////////////////////////////////////// + + protected: + + // Unique id of this document + AZ::Uuid m_id = AZ::Uuid::CreateRandom(); + + // Relative path to the material source file + AZStd::string m_relativePath; + + // Absolute path to the material source file + AZStd::string m_absolutePath; + + AZStd::any m_invalidValue; + + AtomToolsFramework::DynamicProperty m_invalidProperty; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h similarity index 94% rename from Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h rename to Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h index 68325beabb..9c3a536333 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h @@ -13,9 +13,9 @@ #include #include -namespace ShaderManagementConsole +namespace AtomToolsFramework { - class ShaderManagementConsoleDocumentNotifications + class AtomToolsDocumentNotifications : public AZ::EBusTraits { public: @@ -79,5 +79,5 @@ namespace ShaderManagementConsole virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} }; - using ShaderManagementConsoleDocumentNotificationBus = AZ::EBus; -} // namespace ShaderManagementConsole + using AtomToolsDocumentNotificationBus = AZ::EBus; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h new file mode 100644 index 0000000000..42fcab95ae --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h @@ -0,0 +1,95 @@ +/* + * 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 +#include +#include + +namespace AtomToolsFramework +{ + class AtomToolsDocumentRequests + : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; + typedef AZ::Uuid BusIdType; + + //! Get absolute path of document + virtual AZStd::string_view GetAbsolutePath() const = 0; + + //! Get relative path of document + virtual AZStd::string_view GetRelativePath() const = 0; + + //! Return property value + //! If the document is not open or the id can't be found, an invalid value is returned instead. + virtual const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const = 0; + + //! Returns a property object + //! If the document is not open or the id can't be found, an invalid property is returned. + virtual const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const = 0; + + //! Returns whether a property group is visible + //! If the document is not open or the id can't be found, returns false. + virtual bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const = 0; + + //! Modify document property value + virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0; + + //! Load document and related data + //! @param loadPath absolute path of document to load + virtual bool Open(AZStd::string_view loadPath) = 0; + + //! Reload document preserving edits + virtual bool Rebuild() = 0; + + //! Save document to file + virtual bool Save() = 0; + + //! Save document copy + //! @param savePath absolute path where document is saved + virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; + + //! Save document to a new source file derived from of the open document + //! @param savePath absolute path where document is saved + virtual bool SaveAsChild(AZStd::string_view savePath) = 0; + + //! Close document and reset its data + virtual bool Close() = 0; + + //! Document is loaded + virtual bool IsOpen() const = 0; + + //! Document has changes pending + virtual bool IsModified() const = 0; + + //! Can the document be saved + virtual bool IsSavable() const = 0; + + //! Returns true if there are reversible modifications to the document + virtual bool CanUndo() const = 0; + + //! Returns true if there are changes that were reversed and can be re-applied to the document + virtual bool CanRedo() const = 0; + + //! Restores the previous state of the document + virtual bool Undo() = 0; + + //! Restores the next state of the document + virtual bool Redo() = 0; + + //! Signal that editing is about to begin, like beginning to drag a slider control + virtual bool BeginEdit() = 0; + + //! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control + virtual bool EndEdit() = 0; + }; + + using AtomToolsDocumentRequestBus = AZ::EBus; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h similarity index 80% rename from Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h rename to Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h index 47fa5dab85..f751915a9a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h @@ -10,19 +10,21 @@ #include -namespace MaterialEditor +namespace AtomToolsFramework { - static const char* MaterialExtension = "material"; - static const char* MaterialTypeExtension = "materialtype"; + class AtomToolsDocument; - //! MaterialDocumentSystemRequestBus provides high level file requests for menus, scripts, etc. - class MaterialDocumentSystemRequests + //! AtomToolsDocumentSystemRequestBus provides high level requests for menus, scripts, etc. + class AtomToolsDocumentSystemRequests : public AZ::EBusTraits { public: static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + //! Register a document factory function used to create specific document types + virtual void RegisterDocumentType(AZStd::function documentCreator) = 0; + //! Create a document object //! @return Uuid of new document, or null Uuid if failed virtual AZ::Uuid CreateDocument() = 0; @@ -37,8 +39,6 @@ namespace MaterialEditor virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0; //! Create a new document by specifying a source and prompting the user for destination path. - //! If the source file is a material type then this results in creating a new material based on that type. - //! If the source file is a material this results in creating a child material with the source file as its parent. //! @param sourcePath document to open. //! @param targetPath location where document is saved. //! @return unique id of new document if successful, otherwise null Uuid @@ -64,7 +64,7 @@ namespace MaterialEditor //! @param targetPath location where document is saved. virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; - //! Save the specified document to a different file, referencing the original material as its parent + //! Save the specified document to a different file, referencing the original document as its parent //! @param documentId unique id of document to save //! @param targetPath location where document is saved. virtual bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; @@ -73,6 +73,6 @@ namespace MaterialEditor virtual bool SaveAllDocuments() = 0; }; - using MaterialDocumentSystemRequestBus = AZ::EBus; + using AtomToolsDocumentSystemRequestBus = AZ::EBus; -} // namespace MaterialEditor +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h new file mode 100644 index 0000000000..9b4c1d77fe --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h @@ -0,0 +1,30 @@ +/* + * 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 + +#if !defined(Q_MOC_RUN) +#include +#include +#include +#include +#endif + +namespace AtomToolsFramework +{ + struct AtomToolsDocumentSystemSettings + : public AZ::UserSettings + { + AZ_RTTI(AtomToolsDocumentSystemSettings, "{9E576D4F-A74A-4326-9135-C07284D0A3B9}", AZ::UserSettings); + AZ_CLASS_ALLOCATOR(AtomToolsDocumentSystemSettings, AZ::SystemAllocator, 0); + + static void Reflect(AZ::ReflectContext* context); + + bool m_showReloadDocumentPrompt = true; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp index b601596032..21a185b290 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp @@ -8,6 +8,7 @@ #include #include +#include #include namespace AtomToolsFramework @@ -16,6 +17,7 @@ namespace AtomToolsFramework { m_descriptors.insert(m_descriptors.end(), { AtomToolsFrameworkSystemComponent::CreateDescriptor(), + AtomToolsDocumentSystemComponent::CreateDescriptor(), AtomToolsMainWindowSystemComponent::CreateDescriptor(), }); } @@ -24,6 +26,7 @@ namespace AtomToolsFramework { return AZ::ComponentTypeList{ azrtti_typeid(), + azrtti_typeid(), azrtti_typeid(), }; } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp new file mode 100644 index 0000000000..c3216c6d9d --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -0,0 +1,154 @@ +/* + * 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 +#include + +namespace AtomToolsFramework +{ + AtomToolsDocument::AtomToolsDocument() + { + AtomToolsDocumentRequestBus::Handler::BusConnect(m_id); + AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); + } + + AtomToolsDocument::~AtomToolsDocument() + { + AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); + AtomToolsDocumentRequestBus::Handler::BusDisconnect(); + } + + const AZ::Uuid& AtomToolsDocument::GetId() const + { + return m_id; + } + + AZStd::string_view AtomToolsDocument::GetAbsolutePath() const + { + return m_absolutePath; + } + + AZStd::string_view AtomToolsDocument::GetRelativePath() const + { + return m_relativePath; + } + + const AZStd::any& AtomToolsDocument::GetPropertyValue(const AZ::Name& propertyFullName) const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return m_invalidValue; + } + + const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty(const AZ::Name& propertyFullName) const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return m_invalidProperty; + } + + bool AtomToolsDocument::IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + void AtomToolsDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + } + + bool AtomToolsDocument::Open(AZStd::string_view loadPath) + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Rebuild() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Save() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::SaveAsCopy(AZStd::string_view savePath) + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + + bool AtomToolsDocument::SaveAsChild(AZStd::string_view savePath) + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Close() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::IsOpen() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::IsModified() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::IsSavable() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::CanUndo() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::CanRedo() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Undo() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Redo() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::BeginEdit() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::EndEdit() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp new file mode 100644 index 0000000000..fa7280068e --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -0,0 +1,511 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +#include +#include +#include +AZ_POP_DISABLE_WARNING + +namespace AtomToolsFramework +{ + AtomToolsDocumentSystemComponent::AtomToolsDocumentSystemComponent() + { + } + + void AtomToolsDocumentSystemComponent::Reflect(AZ::ReflectContext* context) + { + AtomToolsDocumentSystemSettings::Reflect(context); + + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class() + ->Version(0); + + if (AZ::EditContext* ec = serialize->GetEditContext()) + { + ec->Class("AtomToolsDocumentSystemComponent", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System")) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ; + } + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->EBus("AtomToolsDocumentSystemRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("CreateDocument", &AtomToolsDocumentSystemRequestBus::Events::CreateDocument) + ->Event("DestroyDocument", &AtomToolsDocumentSystemRequestBus::Events::DestroyDocument) + ->Event("OpenDocument", &AtomToolsDocumentSystemRequestBus::Events::OpenDocument) + ->Event("CreateDocumentFromFile", &AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile) + ->Event("CloseDocument", &AtomToolsDocumentSystemRequestBus::Events::CloseDocument) + ->Event("CloseAllDocuments", &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments) + ->Event("CloseAllDocumentsExcept", &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept) + ->Event("SaveDocument", &AtomToolsDocumentSystemRequestBus::Events::SaveDocument) + ->Event("SaveDocumentAsCopy", &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy) + ->Event("SaveDocumentAsChild", &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild) + ->Event("SaveAllDocuments", &AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments) + ; + + behaviorContext->EBus("AtomToolsDocumentRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("GetAbsolutePath", &AtomToolsDocumentRequestBus::Events::GetAbsolutePath) + ->Event("GetRelativePath", &AtomToolsDocumentRequestBus::Events::GetRelativePath) + ->Event("GetPropertyValue", &AtomToolsDocumentRequestBus::Events::GetPropertyValue) + ->Event("SetPropertyValue", &AtomToolsDocumentRequestBus::Events::SetPropertyValue) + ->Event("Open", &AtomToolsDocumentRequestBus::Events::Open) + ->Event("Rebuild", &AtomToolsDocumentRequestBus::Events::Rebuild) + ->Event("Close", &AtomToolsDocumentRequestBus::Events::Close) + ->Event("Save", &AtomToolsDocumentRequestBus::Events::Save) + ->Event("SaveAsChild", &AtomToolsDocumentRequestBus::Events::SaveAsChild) + ->Event("SaveAsCopy", &AtomToolsDocumentRequestBus::Events::SaveAsCopy) + ->Event("IsOpen", &AtomToolsDocumentRequestBus::Events::IsOpen) + ->Event("IsModified", &AtomToolsDocumentRequestBus::Events::IsModified) + ->Event("IsSavable", &AtomToolsDocumentRequestBus::Events::IsSavable) + ->Event("CanUndo", &AtomToolsDocumentRequestBus::Events::CanUndo) + ->Event("CanRedo", &AtomToolsDocumentRequestBus::Events::CanRedo) + ->Event("Undo", &AtomToolsDocumentRequestBus::Events::Undo) + ->Event("Redo", &AtomToolsDocumentRequestBus::Events::Redo) + ->Event("BeginEdit", &AtomToolsDocumentRequestBus::Events::BeginEdit) + ->Event("EndEdit", &AtomToolsDocumentRequestBus::Events::EndEdit) + ; + } + } + + void AtomToolsDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); + } + + void AtomToolsDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); + } + + void AtomToolsDocumentSystemComponent::Init() + { + } + + void AtomToolsDocumentSystemComponent::Activate() + { + m_documentMap.clear(); + m_settings = AZ::UserSettings::CreateFind(AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL); + AtomToolsDocumentSystemRequestBus::Handler::BusConnect(); + AtomToolsDocumentNotificationBus::Handler::BusConnect(); + } + + void AtomToolsDocumentSystemComponent::Deactivate() + { + AZ::TickBus::Handler::BusDisconnect(); + AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsDocumentSystemRequestBus::Handler::BusDisconnect(); + m_documentMap.clear(); + } + + void AtomToolsDocumentSystemComponent::RegisterDocumentType(AZStd::function documentCreator) + { + m_documentCreator = documentCreator; + } + + AZ::Uuid AtomToolsDocumentSystemComponent::CreateDocument() + { + if (!m_documentCreator) + { + AZ_Error("AtomToolsDocument", false, "Failed to create new document"); + return AZ::Uuid::CreateNull(); + } + + AZStd::unique_ptr document(m_documentCreator()); + if (!document) + { + AZ_Error("AtomToolsDocument", false, "Failed to create new document"); + return AZ::Uuid::CreateNull(); + } + + AZ::Uuid documentId = document->GetId(); + m_documentMap.emplace(documentId, document.release()); + return documentId; + } + + bool AtomToolsDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId) + { + return m_documentMap.erase(documentId) != 0; + } + + void AtomToolsDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId) + { + m_documentIdsToReopen.insert(documentId); + if (!AZ::TickBus::Handler::BusIsConnected()) + { + AZ::TickBus::Handler::BusConnect(); + } + } + + void AtomToolsDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId) + { + m_documentIdsToRebuild.insert(documentId); + if (!AZ::TickBus::Handler::BusIsConnected()) + { + AZ::TickBus::Handler::BusConnect(); + } + } + + void AtomToolsDocumentSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) + { + for (const AZ::Uuid& documentId : m_documentIdsToReopen) + { + AZStd::string documentPath; + AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + + if (m_settings->m_showReloadDocumentPrompt && + (QMessageBox::question(QApplication::activeWindow(), + QString("Document was externally modified"), + QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) + { + continue; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool openResult = false; + AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, documentPath); + if (!openResult) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); + } + } + + for (const AZ::Uuid& documentId : m_documentIdsToRebuild) + { + AZStd::string documentPath; + AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + + if (m_settings->m_showReloadDocumentPrompt && + (QMessageBox::question(QApplication::activeWindow(), + QString("Document dependencies have changed"), + QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) + { + continue; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool openResult = false; + AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Rebuild); + if (!openResult) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); + } + } + + m_documentIdsToRebuild.clear(); + m_documentIdsToReopen.clear(); + AZ::TickBus::Handler::BusDisconnect(); + } + + AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath) + { + return OpenDocumentImpl(sourcePath, true); + } + + AZ::Uuid AtomToolsDocumentSystemComponent::CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) + { + const AZ::Uuid documentId = OpenDocumentImpl(sourcePath, false); + if (documentId.IsNull()) + { + return AZ::Uuid::CreateNull(); + } + + if (!SaveDocumentAsChild(documentId, targetPath)) + { + CloseDocument(documentId); + return AZ::Uuid::CreateNull(); + } + + // Send document open notification after creating new one + AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); + return documentId; + } + + bool AtomToolsDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) + { + bool isOpen = false; + AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsDocumentRequestBus::Events::IsOpen); + if (!isOpen) + { + // immediately destroy unopened documents + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); + return true; + } + + AZStd::string documentPath; + AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + + bool isModified = false; + AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsDocumentRequestBus::Events::IsModified); + if (isModified) + { + auto selection = QMessageBox::question(QApplication::activeWindow(), + QString("Document has unsaved changes"), + QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (selection == QMessageBox::Cancel) + { + AZ_TracePrintf("AtomToolsDocument", "Close document canceled: %s", documentPath.c_str()); + return false; + } + if (selection == QMessageBox::Yes) + { + if (!SaveDocument(documentId)) + { + AZ_Error("AtomToolsDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str()); + return false; + } + } + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool closeResult = true; + AtomToolsDocumentRequestBus::EventResult(closeResult, documentId, &AtomToolsDocumentRequestBus::Events::Close); + if (!closeResult) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be closed"), + QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return false; + } + + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); + return true; + } + + bool AtomToolsDocumentSystemComponent::CloseAllDocuments() + { + bool result = true; + auto documentMap = m_documentMap; + for (const auto& documentPair : documentMap) + { + if (!CloseDocument(documentPair.first)) + { + result = false; + } + } + + return result; + } + + bool AtomToolsDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) + { + bool result = true; + auto documentMap = m_documentMap; + for (const auto& documentPair : documentMap) + { + if (documentPair.first != documentId) + { + if (!CloseDocument(documentPair.first)) + { + result = false; + } + } + } + + return result; + } + + bool AtomToolsDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) + { + AZStd::string saveDocumentPath; + AtomToolsDocumentRequestBus::EventResult(saveDocumentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) + { + return false; + } + + const QFileInfo saveInfo(saveDocumentPath.c_str()); + if (saveInfo.exists() && !saveInfo.isWritable()) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); + return false; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; + AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Save); + if (!result) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return false; + } + + return true; + } + + bool AtomToolsDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) + { + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) + { + return false; + } + + const QFileInfo saveInfo(saveDocumentPath.c_str()); + if (saveInfo.exists() && !saveInfo.isWritable()) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); + return false; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; + AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); + if (!result) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return false; + } + + return true; + } + + bool AtomToolsDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) + { + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) + { + return false; + } + + const QFileInfo saveInfo(saveDocumentPath.c_str()); + if (saveInfo.exists() && !saveInfo.isWritable()) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); + return false; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; + AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsChild, saveDocumentPath); + if (!result) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return false; + } + + return true; + } + + bool AtomToolsDocumentSystemComponent::SaveAllDocuments() + { + bool result = true; + for (const auto& documentPair : m_documentMap) + { + if (!SaveDocument(documentPair.first)) + { + result = false; + } + } + + return result; + } + + AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) + { + AZStd::string requestedPath = sourcePath; + if (requestedPath.empty()) + { + return AZ::Uuid::CreateNull(); + } + + if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); + return AZ::Uuid::CreateNull(); + } + + // Determine if the file is already open and select it + if (checkIfAlreadyOpen) + { + for (const auto& documentPair : m_documentMap) + { + AZStd::string openDocumentPath; + AtomToolsDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + if (openDocumentPath == requestedPath) + { + AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); + return documentPair.first; + } + } + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + AZ::Uuid documentId = AZ::Uuid::CreateNull(); + AtomToolsDocumentSystemRequestBus::BroadcastResult(documentId, &AtomToolsDocumentSystemRequestBus::Events::CreateDocument); + if (documentId.IsNull()) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be created"), + QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return AZ::Uuid::CreateNull(); + } + + traceRecorder.GetDump().clear(); + + bool openResult = false; + AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, requestedPath); + if (!openResult) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); + return AZ::Uuid::CreateNull(); + } + + return documentId; + } +} diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h new file mode 100644 index 0000000000..9c556a07e7 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h @@ -0,0 +1,92 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +#include +#include +AZ_POP_DISABLE_WARNING + +namespace AtomToolsFramework +{ + //! AtomToolsDocumentSystemComponent is the central component of the Material Editor Core gem + class AtomToolsDocumentSystemComponent + : public AZ::Component + , private AZ::TickBus::Handler + , private AtomToolsDocumentNotificationBus::Handler + , private AtomToolsDocumentSystemRequestBus::Handler + { + public: + AZ_COMPONENT(AtomToolsDocumentSystemComponent, "{343A3383-6A59-4343-851B-BF84FC6CB18E}"); + + AtomToolsDocumentSystemComponent(); + ~AtomToolsDocumentSystemComponent() = default; + AtomToolsDocumentSystemComponent(const AtomToolsDocumentSystemComponent&) = delete; + AtomToolsDocumentSystemComponent& operator=(const AtomToolsDocumentSystemComponent&) = delete; + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + private: + //////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Init() override; + void Activate() override; + void Deactivate() override; + //////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // AtomToolsDocumentNotificationBus::Handler overrides... + void OnDocumentDependencyModified(const AZ::Uuid& documentId) override; + void OnDocumentExternallyModified(const AZ::Uuid& documentId) override; + ////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // AZ::TickBus::Handler overrides... + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // AtomToolsDocumentSystemRequestBus::Handler overrides... + void RegisterDocumentType(AZStd::function documentCreator) override; + AZ::Uuid CreateDocument() override; + bool DestroyDocument(const AZ::Uuid& documentId) override; + AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; + AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) override; + bool CloseDocument(const AZ::Uuid& documentId) override; + bool CloseAllDocuments() override; + bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override; + bool SaveDocument(const AZ::Uuid& documentId) override; + bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; + bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; + bool SaveAllDocuments() override; + //////////////////////////////////////////////////////////////////////// + + AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); + + AZStd::intrusive_ptr m_settings; + AZStd::function m_documentCreator; + AZStd::unordered_map> m_documentMap; + AZStd::unordered_set m_documentIdsToRebuild; + AZStd::unordered_set m_documentIdsToReopen; + const size_t m_maxMessageBoxLineCount = 15; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp new file mode 100644 index 0000000000..94af43e524 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp @@ -0,0 +1,47 @@ +/* + * 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 +#include +#include + +namespace AtomToolsFramework +{ + void AtomToolsDocumentSystemSettings::Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("showReloadDocumentPrompt", &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt) + ; + + if (auto editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "AtomToolsDocumentSystemSettings", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt, "Show Reload Document Prompt", "") + ; + } + } + + if (auto behaviorContext = azrtti_cast(context)) + { + behaviorContext->Class("AtomToolsDocumentSystemSettings") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Constructor() + ->Constructor() + ->Property("showReloadDocumentPrompt", BehaviorValueProperty(&AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt)) + ; + } + } +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 8eb82778e3..cd056f5fcf 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -11,6 +11,11 @@ set(FILES Include/AtomToolsFramework/Communication/LocalServer.h Include/AtomToolsFramework/Communication/LocalSocket.h Include/AtomToolsFramework/Debug/TraceRecorder.h + Include/AtomToolsFramework/Document/AtomToolsDocument.h + Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h + Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h + Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h + Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h Include/AtomToolsFramework/Inspector/InspectorWidget.h @@ -32,6 +37,10 @@ set(FILES Source/Communication/LocalServer.cpp Source/Communication/LocalSocket.cpp Source/Debug/TraceRecorder.cpp + Source/Document/AtomToolsDocument.cpp + Source/Document/AtomToolsDocumentSystemSettings.cpp + Source/Document/AtomToolsDocumentSystemComponent.cpp + Source/Document/AtomToolsDocumentSystemComponent.h Source/DynamicProperty/DynamicProperty.cpp Source/DynamicProperty/DynamicPropertyGroup.cpp Source/Inspector/InspectorWidget.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Core/MaterialDocumentFactoryRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Core/MaterialDocumentFactoryRequestBus.h deleted file mode 100644 index e936d5159b..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Core/MaterialDocumentFactoryRequestBus.h +++ /dev/null @@ -1,36 +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 - -#include -#include -#include - -namespace MaterialEditor -{ - //! MaterialDocumentFactoryRequestBus provides a factory interface for creating and destroying material documents (in memory) - class MaterialDocumentFactoryRequests - : public AZ::EBusTraits - { - public: - // Only a single handler is allowed - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - - //! Create a material document object - //! @return Uuid of new material document, or null Uuid if failed - virtual AZ::Uuid CreateDocument() = 0; - - //! Destroy a material document object with the specified id - //! @return true if Uuid was found and removed, otherwise false - virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0; - }; - - using MaterialDocumentFactoryRequestBus = AZ::EBus; - -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h deleted file mode 100644 index 963a348697..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h +++ /dev/null @@ -1,86 +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 - -#include -#include - -#include -#include - -#include -#include - -namespace MaterialEditor -{ - class MaterialDocumentNotifications - : public AZ::EBusTraits - { - public: - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - - //! Signal that a document was created - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentCreated([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was destroyed - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentDestroyed([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was opened - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentOpened([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was closed - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentClosed([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was saved - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentSaved([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was selected - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentSelected([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was modified - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentModified([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document dependency was modified - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentDependencyModified([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was modified externally - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentExternallyModified([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document undo state was updated - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentUndoStateChanged([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a property changed - //! @param documentId unique id of document for which the notification is sent - //! @param property object containing the property value and configuration that was modified - virtual void OnDocumentPropertyValueModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} - - //! Signal that the property configuration has been changed. - //! @param documentId unique id of document for which the notification is sent - //! @param property object containing the property value and configuration that was modified - virtual void OnDocumentPropertyConfigModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} - - //! Signal that the property group visibility has been changed. - //! @param documentId unique id of document for which the notification is sent - //! @param groupId id of the group that changed - //! @param visible whether the property group is visible - virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} - }; - - using MaterialDocumentNotificationBus = AZ::EBus; -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h index 515cc44edc..c95aa4f215 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h @@ -7,15 +7,10 @@ */ #pragma once +#include #include #include -#include - #include -#include - -#include -#include namespace AZ { @@ -39,12 +34,6 @@ namespace MaterialEditor static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; typedef AZ::Uuid BusIdType; - //! Get absolute path of document - virtual AZStd::string_view GetAbsolutePath() const = 0; - - //! Get relative path of document - virtual AZStd::string_view GetRelativePath() const = 0; - //! Get material asset created by MaterialDocument virtual AZ::Data::Asset GetAsset() const = 0; @@ -56,69 +45,6 @@ namespace MaterialEditor //! Get the internal material type source data virtual const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const = 0; - - //! Return property value - //! If the document is not open or the id can't be found, an invalid value is returned instead. - virtual const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const = 0; - - //! Returns a property object - //! If the document is not open or the id can't be found, an invalid property is returned. - virtual const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const = 0; - - //! Returns whether a property group is visible - //! If the document is not open or the id can't be found, returns false. - virtual bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const = 0; - - //! Modify material property value - virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0; - - //! Load document and related data - //! @param loadPath Absolute path of document to load - virtual bool Open(AZStd::string_view loadPath) = 0; - - //! Reload document preserving edits - virtual bool Rebuild() = 0; - - //! Save document to file - virtual bool Save() = 0; - - //! Save document copy - //! @param savePath Absolute path where document is saved - virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; - - //! Save material to a new source file as a child of the open material - //! @param savePath Absolute path where material is saved - virtual bool SaveAsChild(AZStd::string_view savePath) = 0; - - //! Close document and reset its data - virtual bool Close() = 0; - - //! Document is loaded - virtual bool IsOpen() const = 0; - - //! Document has changes pending - virtual bool IsModified() const = 0; - - //! Can the document be saved - virtual bool IsSavable() const = 0; - - //! Returns true if there are reversible modifications to the document - virtual bool CanUndo() const = 0; - - //! Returns true if there are changes that were reversed and can be re-applied to the document - virtual bool CanRedo() const = 0; - - //! Restores the previous state of the document - virtual bool Undo() = 0; - - //! Restores the next state of the document - virtual bool Redo() = 0; - - //! Signal that editing is about to begin, like beginning to drag a slider control - virtual bool BeginEdit() = 0; - - //! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control - virtual bool EndEdit() = 0; }; using MaterialDocumentRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSettings.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSettings.h index d9c835b14b..5f39c50717 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSettings.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSettings.h @@ -20,12 +20,11 @@ namespace MaterialEditor struct MaterialDocumentSettings : public AZ::UserSettings { - AZ_RTTI(MaterialDocumentSettings, "{FA4F4BF3-BF39-4753-AAF7-AF383B868881}", AZ::UserSettings); + AZ_RTTI(MaterialDocumentSettings, "{12E8461F-65AD-4AD2-8A1D-82C3B1183522}", AZ::UserSettings); AZ_CLASS_ALLOCATOR(MaterialDocumentSettings, AZ::SystemAllocator, 0); static void Reflect(AZ::ReflectContext* context); - bool m_showReloadDocumentPrompt = true; AZStd::string m_defaultMaterialTypeName = "StandardPBR"; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index f2e012e158..298d38f650 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -6,53 +6,39 @@ * */ -#include -#include -#include #include #include +#include #include #include -#include #include #include +#include +#include +#include #include -#include -#include +#include #include #include #include +#include namespace MaterialEditor { MaterialDocument::MaterialDocument() + : AtomToolsFramework::AtomToolsDocument() { MaterialDocumentRequestBus::Handler::BusConnect(m_id); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentCreated, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); } MaterialDocument::~MaterialDocument() { - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); MaterialDocumentRequestBus::Handler::BusDisconnect(); Clear(); } - const AZ::Uuid& MaterialDocument::GetId() const - { - return m_id; - } - - AZStd::string_view MaterialDocument::GetAbsolutePath() const - { - return m_absolutePath; - } - - AZStd::string_view MaterialDocument::GetRelativePath() const - { - return m_relativePath; - } - AZ::Data::Asset MaterialDocument::GetAsset() const { return m_materialAsset; @@ -170,17 +156,17 @@ namespace MaterialEditor EditorMaterialFunctorResult result = RunEditorMaterialFunctors(dirtyFlags); for (const Name& changedPropertyGroupName : result.m_updatedPropertyGroups) { - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName)); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName)); } for (const Name& changedPropertyName : result.m_updatedProperties) { - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, GetProperty(changedPropertyName)); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, GetProperty(changedPropertyName)); } } } - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyValueModified, m_id, property); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyValueModified, m_id, property); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); } bool MaterialDocument::Open(AZStd::string_view loadPath) @@ -192,7 +178,7 @@ namespace MaterialEditor return false; } - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); return true; } @@ -222,7 +208,7 @@ namespace MaterialEditor RestorePropertyValues(propertyValuesToRestore); AZStd::swap(undoHistoryToRestore, m_undoHistory); AZStd::swap(undoHistoryIndexToRestore, m_undoHistoryIndex); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); return true; } @@ -285,7 +271,7 @@ namespace MaterialEditor AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", m_absolutePath.data()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); m_saveTriggeredInternally = true; return true; @@ -348,7 +334,7 @@ namespace MaterialEditor AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", normalizedSavePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); // If the document is saved to a new file we need to reopen the new document to update assets, paths, property deltas. if (!Open(normalizedSavePath)) @@ -424,7 +410,7 @@ namespace MaterialEditor AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", normalizedSavePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); // If the document is saved to a new file we need to reopen the new document to update assets, paths, property deltas. if (!Open(normalizedSavePath)) @@ -450,7 +436,7 @@ namespace MaterialEditor AZ_TracePrintf("MaterialDocument", "Material document closed: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentClosed, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); // Clearing after notification so paths are still available Clear(); @@ -496,7 +482,7 @@ namespace MaterialEditor // The history index is one beyond the last executed command. Decrement the index then execute undo. m_undoHistory[--m_undoHistoryIndex].first(); AZ_TracePrintf("MaterialDocument", "Material document undo: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); return true; } return false; @@ -509,7 +495,7 @@ namespace MaterialEditor // Execute the current redo command then move the history index to the next position. m_undoHistory[m_undoHistoryIndex++].second(); AZ_TracePrintf("MaterialDocument", "Material document redo: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); return true; } return false; @@ -557,7 +543,7 @@ namespace MaterialEditor // Assign the index to the end of history m_undoHistoryIndex = aznumeric_cast(m_undoHistory.size()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); } m_propertyValuesBeforeEdit.clear(); @@ -584,7 +570,7 @@ namespace MaterialEditor if (!m_saveTriggeredInternally) { AZ_TracePrintf("MaterialDocument", "Material document changed externally: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); } m_saveTriggeredInternally = false; } @@ -595,7 +581,7 @@ namespace MaterialEditor if (m_dependentAssetIds.find(asset->GetId()) != m_dependentAssetIds.end()) { AZ_TracePrintf("MaterialDocument", "Material document dependency changed: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 63d98259ad..09a1873dcf 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -18,8 +18,7 @@ #include #include #include - -#include +#include namespace MaterialEditor { @@ -27,7 +26,8 @@ namespace MaterialEditor * MaterialDocument provides an API for modifying and saving material document properties. */ class MaterialDocument - : public MaterialDocumentRequestBus::Handler + : public AtomToolsFramework::AtomToolsDocument + , public MaterialDocumentRequestBus::Handler , private AZ::TickBus::Handler , private AZ::Data::AssetBus::MultiHandler , private AzToolsFramework::AssetSystemBus::Handler @@ -40,16 +40,9 @@ namespace MaterialEditor MaterialDocument(); virtual ~MaterialDocument(); - const AZ::Uuid& GetId() const; - //////////////////////////////////////////////////////////////////////// - // MaterialDocumentRequestBus::Handler implementation - AZStd::string_view GetAbsolutePath() const override; - AZStd::string_view GetRelativePath() const override; - AZ::Data::Asset GetAsset() const override; - AZ::Data::Instance GetInstance() const override; - const AZ::RPI::MaterialSourceData* GetMaterialSourceData() const override; - const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const override; + // AtomToolsFramework::AtomToolsDocument + //////////////////////////////////////////////////////////////////////// const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override; const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override; bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; @@ -71,6 +64,14 @@ namespace MaterialEditor bool EndEdit() override; //////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// + // MaterialDocumentRequestBus::Handler implementation + AZ::Data::Asset GetAsset() const override; + AZ::Data::Instance GetInstance() const override; + const AZ::RPI::MaterialSourceData* GetMaterialSourceData() const override; + const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const override; + //////////////////////////////////////////////////////////////////////// + private: // Predicate for evaluating properties @@ -130,21 +131,12 @@ namespace MaterialEditor // @return names for the set of properties and groups that have been changed or need update. EditorMaterialFunctorResult RunEditorMaterialFunctors(AZ::RPI::MaterialPropertyFlags dirtyFlags); - // Unique id of this material document - AZ::Uuid m_id = AZ::Uuid::CreateRandom(); - // Underlying material asset AZ::Data::Asset m_materialAsset; // Material instance being edited AZ::Data::Instance m_materialInstance; - // Relative path to the material source file - AZStd::string m_relativePath; - - // Absolute path to the material source file - AZStd::string m_absolutePath; - // Asset used to open document AZ::Data::AssetId m_sourceAssetId; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp index 5780cd45c0..c721798cfd 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp @@ -7,10 +7,8 @@ */ #include -#include - -#include #include +#include namespace MaterialEditor { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSettings.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSettings.cpp index b0d6e35d7f..4823b8c67c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSettings.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSettings.cpp @@ -18,7 +18,6 @@ namespace MaterialEditor { serializeContext->Class() ->Version(1) - ->Field("showReloadDocumentPrompt", &MaterialDocumentSettings::m_showReloadDocumentPrompt) ->Field("defaultMaterialTypeName", &MaterialDocumentSettings::m_defaultMaterialTypeName) ; @@ -28,7 +27,6 @@ namespace MaterialEditor "MaterialDocumentSettings", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialDocumentSettings::m_showReloadDocumentPrompt, "Show Reload Document Prompt", "") ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialDocumentSettings::m_defaultMaterialTypeName, "Default Material Type Name", "") ; } @@ -39,10 +37,9 @@ namespace MaterialEditor behaviorContext->Class("MaterialDocumentSettings") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "render") + ->Attribute(AZ::Script::Attributes::Module, "materialeditor") ->Constructor() ->Constructor() - ->Property("showReloadDocumentPrompt", BehaviorValueProperty(&MaterialDocumentSettings::m_showReloadDocumentPrompt)) ->Property("defaultMaterialTypeName", BehaviorValueProperty(&MaterialDocumentSettings::m_defaultMaterialTypeName)) ; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp index 3ecabaabcc..9302b5ac5c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp @@ -6,40 +6,17 @@ * */ -#include - -#include #include #include -#include -#include -#include -#include -#include +#include #include #include #include -#include -#include -#include -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -#include -#include -#include -AZ_POP_DISABLE_WARNING +#include +#include namespace MaterialEditor { - MaterialDocumentSystemComponent::MaterialDocumentSystemComponent() - { - } - void MaterialDocumentSystemComponent::Reflect(AZ::ReflectContext* context) { MaterialDocumentSettings::Reflect(context); @@ -53,7 +30,7 @@ namespace MaterialEditor { ec->Class("MaterialDocumentSystemComponent", "Tool for editing Atom material files") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System")) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ; } @@ -61,66 +38,31 @@ namespace MaterialEditor if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("MaterialDocumentSystemRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("CreateDocument", &MaterialDocumentSystemRequestBus::Events::CreateDocument) - ->Event("DestroyDocument", &MaterialDocumentSystemRequestBus::Events::DestroyDocument) - ->Event("OpenDocument", &MaterialDocumentSystemRequestBus::Events::OpenDocument) - ->Event("CreateDocumentFromFile", &MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile) - ->Event("CloseDocument", &MaterialDocumentSystemRequestBus::Events::CloseDocument) - ->Event("CloseAllDocuments", &MaterialDocumentSystemRequestBus::Events::CloseAllDocuments) - ->Event("CloseAllDocumentsExcept", &MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept) - ->Event("SaveDocument", &MaterialDocumentSystemRequestBus::Events::SaveDocument) - ->Event("SaveDocumentAsCopy", &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsCopy) - ->Event("SaveDocumentAsChild", &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsChild) - ->Event("SaveAllDocuments", &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments) - ; - behaviorContext->EBus("MaterialDocumentRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("GetAbsolutePath", &MaterialDocumentRequestBus::Events::GetAbsolutePath) - ->Event("GetRelativePath", &MaterialDocumentRequestBus::Events::GetRelativePath) - ->Event("GetPropertyValue", &MaterialDocumentRequestBus::Events::GetPropertyValue) - ->Event("SetPropertyValue", &MaterialDocumentRequestBus::Events::SetPropertyValue) - ->Event("Open", &MaterialDocumentRequestBus::Events::Open) - ->Event("Rebuild", &MaterialDocumentRequestBus::Events::Rebuild) - ->Event("Close", &MaterialDocumentRequestBus::Events::Close) - ->Event("Save", &MaterialDocumentRequestBus::Events::Save) - ->Event("SaveAsChild", &MaterialDocumentRequestBus::Events::SaveAsChild) - ->Event("SaveAsCopy", &MaterialDocumentRequestBus::Events::SaveAsCopy) - ->Event("IsOpen", &MaterialDocumentRequestBus::Events::IsOpen) - ->Event("IsModified", &MaterialDocumentRequestBus::Events::IsModified) - ->Event("IsSavable", &MaterialDocumentRequestBus::Events::IsSavable) - ->Event("CanUndo", &MaterialDocumentRequestBus::Events::CanUndo) - ->Event("CanRedo", &MaterialDocumentRequestBus::Events::CanRedo) - ->Event("Undo", &MaterialDocumentRequestBus::Events::Undo) - ->Event("Redo", &MaterialDocumentRequestBus::Events::Redo) - ->Event("BeginEdit", &MaterialDocumentRequestBus::Events::BeginEdit) - ->Event("EndEdit", &MaterialDocumentRequestBus::Events::EndEdit) ; } } void MaterialDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc)); - required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("RPISystem", 0xf2add773)); + required.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); + required.push_back(AZ_CRC_CE("AssetProcessorToolsConnection")); + required.push_back(AZ_CRC_CE("AssetDatabaseService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("RPISystem")); } void MaterialDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("MaterialDocumentSystemService")); + provided.push_back(AZ_CRC_CE("MaterialDocumentSystemService")); } void MaterialDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("MaterialDocumentSystemService")); + incompatible.push_back(AZ_CRC_CE("MaterialDocumentSystemService")); } void MaterialDocumentSystemComponent::Init() @@ -129,388 +71,15 @@ namespace MaterialEditor void MaterialDocumentSystemComponent::Activate() { - m_documentMap.clear(); - m_settings = AZ::UserSettings::CreateFind(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL); - MaterialDocumentSystemRequestBus::Handler::BusConnect(); - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, + []() + { + return aznew MaterialDocument(); + }); } void MaterialDocumentSystemComponent::Deactivate() { - AZ::TickBus::Handler::BusDisconnect(); - MaterialDocumentNotificationBus::Handler::BusDisconnect(); - MaterialDocumentSystemRequestBus::Handler::BusDisconnect(); - m_documentMap.clear(); - } - - AZ::Uuid MaterialDocumentSystemComponent::CreateDocument() - { - auto document = AZStd::make_unique(); - if (!document) - { - AZ_Error("MaterialDocument", false, "Failed to create new document"); - return AZ::Uuid::CreateNull(); - } - - AZ::Uuid documentId = document->GetId(); - m_documentMap.emplace(documentId, document.release()); - return documentId; - } - - bool MaterialDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId) - { - return m_documentMap.erase(documentId) != 0; - } - - void MaterialDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId) - { - m_documentIdsToReopen.insert(documentId); - if (!AZ::TickBus::Handler::BusIsConnected()) - { - AZ::TickBus::Handler::BusConnect(); - } - } - - void MaterialDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId) - { - m_documentIdsToRebuild.insert(documentId); - if (!AZ::TickBus::Handler::BusIsConnected()) - { - AZ::TickBus::Handler::BusConnect(); - } - } - - void MaterialDocumentSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) - { - for (const AZ::Uuid& documentId : m_documentIdsToReopen) - { - AZStd::string documentPath; - MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - if (m_settings->m_showReloadDocumentPrompt && - (QMessageBox::question(QApplication::activeWindow(), - QString("Document was externally modified"), - QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), - QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) - { - continue; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool openResult = false; - MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, documentPath); - if (!openResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); - } - } - - for (const AZ::Uuid& documentId : m_documentIdsToRebuild) - { - AZStd::string documentPath; - MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - if (m_settings->m_showReloadDocumentPrompt && - (QMessageBox::question(QApplication::activeWindow(), - QString("Document dependencies have changed"), - QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), - QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) - { - continue; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool openResult = false; - MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Rebuild); - if (!openResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); - } - } - - m_documentIdsToRebuild.clear(); - m_documentIdsToReopen.clear(); - AZ::TickBus::Handler::BusDisconnect(); - } - - AZ::Uuid MaterialDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath) - { - return OpenDocumentImpl(sourcePath, true); - } - - AZ::Uuid MaterialDocumentSystemComponent::CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) - { - const AZ::Uuid documentId = OpenDocumentImpl(sourcePath, false); - if (documentId.IsNull()) - { - return AZ::Uuid::CreateNull(); - } - - if (!SaveDocumentAsChild(documentId, targetPath)) - { - CloseDocument(documentId); - return AZ::Uuid::CreateNull(); - } - - // Send document open notification after creating new material - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId); - return documentId; - } - - bool MaterialDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) - { - bool isOpen = false; - MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen); - if (!isOpen) - { - // immediately destroy unopened documents - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return true; - } - - AZStd::string documentPath; - MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); - if (isModified) - { - auto selection = QMessageBox::question(QApplication::activeWindow(), - QString("Document has unsaved changes"), - QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (selection == QMessageBox::Cancel) - { - AZ_TracePrintf("MaterialDocument", "Close document canceled: %s", documentPath.c_str()); - return false; - } - if (selection == QMessageBox::Yes) - { - if (!SaveDocument(documentId)) - { - AZ_Error("MaterialDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str()); - return false; - } - } - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool closeResult = true; - MaterialDocumentRequestBus::EventResult(closeResult, documentId, &MaterialDocumentRequestBus::Events::Close); - if (!closeResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be closed"), - QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return true; - } - - bool MaterialDocumentSystemComponent::CloseAllDocuments() - { - bool result = true; - auto documentMap = m_documentMap; - for (const auto& documentPair : documentMap) - { - if (!CloseDocument(documentPair.first)) - { - result = false; - } - } - - return result; - } - - bool MaterialDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) - { - bool result = true; - auto documentMap = m_documentMap; - for (const auto& documentPair : documentMap) - { - if (documentPair.first != documentId) - { - if (!CloseDocument(documentPair.first)) - { - result = false; - } - } - } - - return result; - } - - bool MaterialDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) - { - AZStd::string saveDocumentPath; - MaterialDocumentRequestBus::EventResult(saveDocumentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Save); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool MaterialDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) - { - AZStd::string saveDocumentPath = targetPath; - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool MaterialDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) - { - AZStd::string saveDocumentPath = targetPath; - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveDocumentPath); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool MaterialDocumentSystemComponent::SaveAllDocuments() - { - bool result = true; - for (const auto& documentPair : m_documentMap) - { - if (!SaveDocument(documentPair.first)) - { - result = false; - } - } - - return result; - } - - AZ::Uuid MaterialDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) - { - AZStd::string requestedPath = sourcePath; - if (requestedPath.empty()) - { - return AZ::Uuid::CreateNull(); - } - - if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); - return AZ::Uuid::CreateNull(); - } - - // Determine if the file is already open and select it - if (checkIfAlreadyOpen) - { - for (const auto& documentPair : m_documentMap) - { - AZStd::string openDocumentPath; - MaterialDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - if (openDocumentPath == requestedPath) - { - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); - return documentPair.first; - } - } - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - AZ::Uuid documentId = AZ::Uuid::CreateNull(); - MaterialDocumentSystemRequestBus::BroadcastResult(documentId, &MaterialDocumentSystemRequestBus::Events::CreateDocument); - if (documentId.IsNull()) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be created"), - QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return AZ::Uuid::CreateNull(); - } - - traceRecorder.GetDump().clear(); - - bool openResult = false; - MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, requestedPath); - if (!openResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return AZ::Uuid::CreateNull(); - } - - return documentId; } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h index 3b20f40b4f..af19956088 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h @@ -9,34 +9,17 @@ #pragma once #include -#include -#include -#include - -#include -#include -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -AZ_POP_DISABLE_WARNING namespace MaterialEditor { - //! MaterialDocumentSystemComponent is the central component of the Material Editor Core gem + //! MaterialDocumentSystemComponent class MaterialDocumentSystemComponent : public AZ::Component - , private AZ::TickBus::Handler - , private MaterialDocumentNotificationBus::Handler - , private MaterialDocumentSystemRequestBus::Handler { public: - AZ_COMPONENT(MaterialDocumentSystemComponent, "{58ABE0AE-2710-41E2-ADFD-E2D67407427D}"); + AZ_COMPONENT(MaterialDocumentSystemComponent, "{E011DA51-855D-45FA-87A3-1C1CD6379091}"); - MaterialDocumentSystemComponent(); + MaterialDocumentSystemComponent() = default; ~MaterialDocumentSystemComponent() = default; MaterialDocumentSystemComponent(const MaterialDocumentSystemComponent&) = delete; MaterialDocumentSystemComponent& operator=(const MaterialDocumentSystemComponent&) = delete; @@ -54,39 +37,5 @@ namespace MaterialEditor void Activate() override; void Deactivate() override; //////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // MaterialDocumentNotificationBus::Handler overrides... - void OnDocumentDependencyModified(const AZ::Uuid& documentId) override; - void OnDocumentExternallyModified(const AZ::Uuid& documentId) override; - ////////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // AZ::TickBus::Handler overrides... - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // MaterialDocumentSystemRequestBus::Handler overrides... - AZ::Uuid CreateDocument() override; - bool DestroyDocument(const AZ::Uuid& documentId) override; - AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; - AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) override; - bool CloseDocument(const AZ::Uuid& documentId) override; - bool CloseAllDocuments() override; - bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override; - bool SaveDocument(const AZ::Uuid& documentId) override; - bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; - bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; - bool SaveAllDocuments() override; - //////////////////////////////////////////////////////////////////////// - - AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); - - AZStd::intrusive_ptr m_settings; - AZStd::unordered_map> m_documentMap; - AZStd::unordered_set m_documentIdsToRebuild; - AZStd::unordered_set m_documentIdsToReopen; - const size_t m_maxMessageBoxLineCount = 15; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index bdd9e6fbaf..cec882cabb 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -7,9 +7,9 @@ */ #include -#include #include #include +#include #include #include #include @@ -68,7 +68,7 @@ namespace MaterialEditor const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } Base::ProcessCommandLine(commandLine); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index da691feff7..e91bce48f0 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -8,8 +8,8 @@ #pragma once -#include #include +#include namespace MaterialEditor { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index 23e37b2f7c..f98cdce91b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -243,7 +243,7 @@ namespace MaterialEditor OnFieldOfViewChanged(viewportSettings->m_fieldOfView); OnDisplayMapperOperationTypeChanged(viewportSettings->m_displayMapperOperationType); - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); MaterialViewportNotificationBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect(); AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId()); @@ -255,7 +255,7 @@ namespace MaterialEditor AzFramework::WindowSystemRequestBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); - MaterialDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); MaterialViewportNotificationBus::Handler::BusDisconnect(); AZ::Data::AssetBus::Handler::BusDisconnect(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h index 4efaf51d01..240d66fd43 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h @@ -8,16 +8,14 @@ #pragma once -#include -#include -#include - -#include -#include #include #include +#include #include - +#include +#include +#include +#include #include #include @@ -45,7 +43,7 @@ namespace MaterialEditor class MaterialViewportRenderer : public AZ::Data::AssetBus::Handler , public AZ::TickBus::Handler - , public MaterialDocumentNotificationBus::Handler + , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler , public MaterialViewportNotificationBus::Handler , public AZ::TransformNotificationBus::MultiHandler , public AzFramework::WindowSystemRequestBus::Handler @@ -60,7 +58,7 @@ namespace MaterialEditor private: - // MaterialDocumentNotificationBus::Handler interface overrides... + // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler interface overrides... void OnDocumentOpened(const AZ::Uuid& documentId) override; // MaterialViewportNotificationBus::Handler interface overrides... diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportSettings.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportSettings.cpp index 52f277d984..c2c35119c2 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportSettings.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportSettings.cpp @@ -54,7 +54,7 @@ namespace MaterialEditor behaviorContext->Class("MaterialViewportSettings") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "render") + ->Attribute(AZ::Script::Attributes::Module, "materialeditor") ->Constructor() ->Constructor() ->Property("enableGrid", BehaviorValueProperty(&MaterialViewportSettings::m_enableGrid)) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp index 20098f461b..4df76b4dac 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp @@ -7,9 +7,12 @@ */ #include -#include +#include +#include #include #include +#include +#include #include #include #include @@ -18,9 +21,8 @@ #include #include #include - -#include -#include +#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -91,14 +93,14 @@ namespace MaterialEditor } }); - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); } MaterialBrowserWidget::~MaterialBrowserWidget() { // Maintains the tree expansion state between runs m_ui->m_assetBrowserTreeViewWidget->SaveState(); - MaterialDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); } @@ -144,13 +146,13 @@ namespace MaterialEditor { if (entry) { - if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) + if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension)) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); } - else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) + else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension)) { - //ignore MaterialTypeExtension + //ignore AZ::RPI::MaterialTypeSourceData::Extension } else { @@ -163,7 +165,7 @@ namespace MaterialEditor void MaterialBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId) { AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); if (!absolutePath.empty()) { // Selecting a new asset in the browser is not guaranteed to happen immediately. @@ -230,4 +232,4 @@ namespace MaterialEditor } // namespace MaterialEditor -#include +#include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h index 2ded270af0..24a244bc3c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h @@ -9,15 +9,15 @@ #pragma once #if !defined(Q_MOC_RUN) -#include +#include #include #include #include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include #include +#include AZ_POP_DISABLE_WARNING #endif @@ -45,7 +45,7 @@ namespace MaterialEditor class MaterialBrowserWidget : public QWidget , protected AZ::TickBus::Handler - , protected MaterialDocumentNotificationBus::Handler + , protected AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: @@ -56,7 +56,7 @@ namespace MaterialEditor AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const; void OpenSelectedEntries(); - // MaterialDocumentNotificationBus::Handler implementation + // AtomToolsDocumentNotificationBus::Handler implementation void OnDocumentOpened(const AZ::Uuid& documentId) override; // AZ::TickBus::Handler diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp index b957c550e6..3440d9c316 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp @@ -6,32 +6,28 @@ * */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - #include -#include - -#include -#include - -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include namespace MaterialEditor { @@ -66,11 +62,11 @@ namespace MaterialEditor if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) { const auto source = azalias_cast(entry); - if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) + if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension)) { AddContextMenuActionsForMaterialSource(caller, menu, source); } - else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) + else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension)) { AddContextMenuActionsForMaterialTypeSource(caller, menu, source); } @@ -115,7 +111,7 @@ namespace MaterialEditor AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); }); @@ -157,7 +153,7 @@ namespace MaterialEditor { menu->addAction("Open", [entry]() { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); }); menu->addAction("Duplicate...", [entry, caller]() @@ -191,7 +187,7 @@ namespace MaterialEditor AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); }); @@ -258,7 +254,7 @@ namespace MaterialEditor !createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() && !createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty()) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(), createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData()); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index ffe5ec408a..ca938c3745 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -6,7 +6,11 @@ * */ +#include #include +#include +#include +#include #include #include #include @@ -15,11 +19,6 @@ #include #include #include - -#include -#include -#include - #include #include #include @@ -106,13 +105,13 @@ namespace MaterialEditor m_advancedDockManager->restoreState(windowState); } - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); OnDocumentOpened(AZ::Uuid::CreateNull()); } MaterialEditorWindow::~MaterialEditorWindow() { - MaterialDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); } @@ -150,7 +149,7 @@ namespace MaterialEditor void MaterialEditorWindow::closeEvent(QCloseEvent* closeEvent) { bool didClose = true; - MaterialDocumentSystemRequestBus::BroadcastResult(didClose, &MaterialDocumentSystemRequestBus::Events::CloseAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); if (!didClose) { closeEvent->ignore(); @@ -171,17 +170,17 @@ namespace MaterialEditor void MaterialEditorWindow::OnDocumentOpened(const AZ::Uuid& documentId) { bool isOpen = false; - MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen); bool isSavable = false; - MaterialDocumentRequestBus::EventResult(isSavable, documentId, &MaterialDocumentRequestBus::Events::IsSavable); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsSavable); bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); bool canUndo = false; - MaterialDocumentRequestBus::EventResult(canUndo, documentId, &MaterialDocumentRequestBus::Events::CanUndo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo); bool canRedo = false; - MaterialDocumentRequestBus::EventResult(canRedo, documentId, &MaterialDocumentRequestBus::Events::CanRedo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo); AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); @@ -238,7 +237,7 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Document closed: %1").arg(documentPath); + const QString status = QString("Document opened: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } } @@ -255,9 +254,9 @@ namespace MaterialEditor void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId) { bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); @@ -268,9 +267,9 @@ namespace MaterialEditor if (documentId == GetDocumentIdFromTab(m_tabWidget->currentIndex())) { bool canUndo = false; - MaterialDocumentRequestBus::EventResult(canUndo, documentId, &MaterialDocumentRequestBus::Events::CanUndo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo); bool canRedo = false; - MaterialDocumentRequestBus::EventResult(canRedo, documentId, &MaterialDocumentRequestBus::Events::CanRedo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo); m_actionUndo->setEnabled(canUndo); m_actionRedo->setEnabled(canRedo); } @@ -279,15 +278,15 @@ namespace MaterialEditor void MaterialEditorWindow::OnDocumentSaved(const AZ::Uuid& documentId) { bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document closed: %1").arg(documentPath); + const QString status = QString("Document saved: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } @@ -306,7 +305,7 @@ namespace MaterialEditor !createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() && !createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty()) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(), createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData()); } @@ -317,7 +316,7 @@ namespace MaterialEditor const AZStd::string filePath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData(); if (!filePath.empty()) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, filePath); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, filePath); } }, QKeySequence::Open); @@ -328,11 +327,11 @@ namespace MaterialEditor m_actionSave = m_menuFile->addAction("&Save", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Save); @@ -342,11 +341,11 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); bool result = false; - MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsCopy, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy, documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::SaveAs); @@ -356,21 +355,21 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); bool result = false; - MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsChild, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild, documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }); m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() { bool result = false; - MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Failed to save documents."); + const QString status = QString("Document save all failed."); m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -379,16 +378,16 @@ namespace MaterialEditor m_actionClose = m_menuFile->addAction("&Close", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }, QKeySequence::Close); m_actionCloseAll = m_menuFile->addAction("Close All", [this]() { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); }); m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); m_menuFile->addSeparator(); @@ -412,11 +411,11 @@ namespace MaterialEditor m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Undo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform undo on document: %1").arg(documentPath); + const QString status = QString("Document undo failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -424,11 +423,11 @@ namespace MaterialEditor m_actionRedo = m_menuEdit->addAction("&Redo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Redo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform redo on document: %1").arg(documentPath); + const QString status = QString("Document redo failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); @@ -501,19 +500,19 @@ namespace MaterialEditor // This should automatically clear the active document connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) { const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) { const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }); } QString MaterialEditorWindow::GetDocumentPath(const AZ::Uuid& documentId) const { AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Handler::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Handler::GetAbsolutePath); return absolutePath.c_str(); } @@ -529,15 +528,15 @@ namespace MaterialEditor const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select"; tabMenu.addAction(selectActionName, [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); tabMenu.addAction("Close", [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }); auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); closeOthersAction->setEnabled(tabBar->count() > 1); tabMenu.exec(QCursor::pos()); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index 43151b9c03..b7d0cbf8da 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -9,7 +9,7 @@ #pragma once #if !defined(Q_MOC_RUN) -#include +#include #include #include @@ -30,7 +30,7 @@ namespace MaterialEditor */ class MaterialEditorWindow : public AtomToolsFramework::AtomToolsMainWindow - , private MaterialDocumentNotificationBus::Handler + , private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: @@ -46,7 +46,7 @@ namespace MaterialEditor void LockViewportRenderTargetSize(uint32_t width, uint32_t height) override; void UnlockViewportRenderTargetSize() override; - // MaterialDocumentNotificationBus::Handler overrides... + // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides... void OnDocumentOpened(const AZ::Uuid& documentId) override; void OnDocumentClosed(const AZ::Uuid& documentId) override; void OnDocumentModified(const AZ::Uuid& documentId) override; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowSettings.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowSettings.cpp index 62a1b207de..71c71e8b75 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowSettings.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowSettings.cpp @@ -37,7 +37,7 @@ namespace MaterialEditor behaviorContext->Class("MaterialEditorWindowSettings") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "render") + ->Attribute(AZ::Script::Attributes::Module, "materialeditor") ->Constructor() ->Constructor() ; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp index ccf07c2136..28d7d3d3f5 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp @@ -6,17 +6,15 @@ * */ +#include #include #include #include #include - -#include - +#include #include #include #include - #include namespace MaterialEditor @@ -27,12 +25,12 @@ namespace MaterialEditor m_windowSettings = AZ::UserSettings::CreateFind( AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL); - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); } MaterialInspector::~MaterialInspector() { - MaterialDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); } @@ -69,9 +67,9 @@ namespace MaterialEditor m_documentId = documentId; bool isOpen = false; - MaterialDocumentRequestBus::EventResult(isOpen, m_documentId, &MaterialDocumentRequestBus::Events::IsOpen); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen); - MaterialDocumentRequestBus::EventResult(m_documentPath, m_documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(m_documentPath, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); if (!m_documentId.IsNull() && isOpen) { @@ -113,13 +111,13 @@ namespace MaterialEditor auto& group = m_groups[groupNameId]; AtomToolsFramework::DynamicProperty property; - MaterialDocumentRequestBus::EventResult( - property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("overview.materialType")); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::Name("overview.materialType")); group.m_properties.push_back(property); property = {}; - MaterialDocumentRequestBus::EventResult( - property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("overview.parentMaterial")); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::Name("overview.parentMaterial")); group.m_properties.push_back(property); // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties @@ -145,8 +143,8 @@ namespace MaterialEditor for (const auto& uvNamePair : uvNameMap) { AtomToolsFramework::DynamicProperty property; - MaterialDocumentRequestBus::EventResult( - property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::RPI::MaterialPropertyId(groupNameId, uvNamePair.m_shaderInput.ToString()).GetFullName()); group.m_properties.push_back(property); @@ -182,8 +180,8 @@ namespace MaterialEditor for (const auto& propertyDefinition : propertyListItr->second) { AtomToolsFramework::DynamicProperty property; - MaterialDocumentRequestBus::EventResult( - property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName()); group.m_properties.push_back(property); } @@ -196,8 +194,8 @@ namespace MaterialEditor AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); bool isGroupVisible = false; - MaterialDocumentRequestBus::EventResult( - isGroupVisible, m_documentId, &MaterialDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupNameId}); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + isGroupVisible, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupNameId}); SetGroupVisible(groupNameId, isGroupVisible); } } @@ -264,7 +262,7 @@ namespace MaterialEditor if (m_activeProperty != property) { m_activeProperty = property; - MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::BeginEdit); + AtomToolsFramework::AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::BeginEdit); } } } @@ -276,8 +274,8 @@ namespace MaterialEditor { if (m_activeProperty == property) { - MaterialDocumentRequestBus::Event( - m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue()); + AtomToolsFramework::AtomToolsDocumentRequestBus::Event( + m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue()); } } } @@ -292,10 +290,10 @@ namespace MaterialEditor { if (m_activeProperty == property) { - MaterialDocumentRequestBus::Event( - m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue()); + AtomToolsFramework::AtomToolsDocumentRequestBus::Event( + m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue()); - MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::EndEdit); + AtomToolsFramework::AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::EndEdit); m_activeProperty = nullptr; } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h index ccef72ea3f..845a8cb0f7 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h @@ -9,14 +9,12 @@ #pragma once #if !defined(Q_MOC_RUN) -#include -#include - +#include +#include #include #include - -#include -#include +#include +#include #endif namespace MaterialEditor @@ -25,7 +23,7 @@ namespace MaterialEditor //! The settings can be divided into cards, with each one showing a subset of properties. class MaterialInspector : public AtomToolsFramework::InspectorWidget - , public MaterialDocumentNotificationBus::Handler + , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler , public AzToolsFramework::IPropertyEditorNotify { Q_OBJECT @@ -52,7 +50,7 @@ namespace MaterialEditor void AddUvNamesGroup(); void AddPropertiesGroup(); - // MaterialDocumentNotificationBus::Handler implementation + // AtomToolsDocumentNotificationBus::Handler implementation void OnDocumentOpened(const AZ::Uuid& documentId) override; void OnDocumentPropertyValueModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) override; void OnDocumentPropertyConfigModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) override; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp index 22a85d84a7..e8254edb28 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp @@ -15,7 +15,9 @@ namespace MaterialEditor : AtomToolsFramework::InspectorWidget(parent) { m_documentSettings = - AZ::UserSettings::CreateFind(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL); + AZ::UserSettings::CreateFind(AZ_CRC_CE("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL); + m_documentSystemSettings = AZ::UserSettings::CreateFind( + AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL); } SettingsWidget::~SettingsWidget() @@ -26,23 +28,36 @@ namespace MaterialEditor void SettingsWidget::Populate() { AddGroupsBegin(); - AddDocumentGroup(); + AddDocumentSystemSettingsGroup(); + AddDocumentSettingsGroup(); AddGroupsEnd(); } - void SettingsWidget::AddDocumentGroup() + void SettingsWidget::AddDocumentSettingsGroup() { const AZStd::string groupNameId = "documentSettings"; const AZStd::string groupDisplayName = "Document Settings"; const AZStd::string groupDescription = "Document Settings"; - const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentGroup")); + const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSettingsGroup")); AddGroup( groupNameId, groupDisplayName, groupDescription, new AtomToolsFramework::InspectorPropertyGroupWidget( m_documentSettings.get(), nullptr, m_documentSettings->TYPEINFO_Uuid(), this, this, saveStateKey)); } + void SettingsWidget::AddDocumentSystemSettingsGroup() + { + const AZStd::string groupNameId = "documentSystemSettings"; + const AZStd::string groupDisplayName = "Document System Settings"; + const AZStd::string groupDescription = "Document System Settings"; + + const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup")); AddGroup( + groupNameId, groupDisplayName, groupDescription, + new AtomToolsFramework::InspectorPropertyGroupWidget( + m_documentSystemSettings.get(), nullptr, m_documentSystemSettings->TYPEINFO_Uuid(), this, this, saveStateKey)); + } + void SettingsWidget::Reset() { AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h index 56fc7fbebb..fea98eeda1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h @@ -10,6 +10,7 @@ #if !defined(Q_MOC_RUN) #include +#include #include #include #endif @@ -31,7 +32,8 @@ namespace MaterialEditor void Populate(); private: - void AddDocumentGroup(); + void AddDocumentSettingsGroup(); + void AddDocumentSystemSettingsGroup(); // AtomToolsFramework::InspectorRequestBus::Handler overrides... void Reset() override; @@ -46,5 +48,6 @@ namespace MaterialEditor void PropertySelectionChanged(AzToolsFramework::InstanceDataNode*, bool) override {} AZStd::intrusive_ptr m_documentSettings; + AZStd::intrusive_ptr m_documentSystemSettings; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditordocument_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditordocument_files.cmake index 0c657361f1..d86dd03749 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditordocument_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditordocument_files.cmake @@ -8,8 +8,6 @@ set(FILES Include/Atom/Document/MaterialDocumentModule.h - Include/Atom/Document/MaterialDocumentSystemRequestBus.h - Include/Atom/Document/MaterialDocumentNotificationBus.h Include/Atom/Document/MaterialDocumentRequestBus.h Include/Atom/Document/MaterialDocumentSettings.h Source/Document/MaterialDocumentModule.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py index 2116a3de6c..6708553e20 100755 --- a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py +++ b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py @@ -93,11 +93,11 @@ def ToRadians(degrees): return 3.14159 * degrees / 180.0; def OpenMaterial(filename): - documentId = azlmbr.materialeditor.MaterialDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'OpenDocument', os.path.join(g_materialTestFolder, filename)) + documentId = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'OpenDocument', os.path.join(g_materialTestFolder, filename)) return documentId def CloseMaterial(documentId): - azlmbr.materialeditor.MaterialDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'CloseDocument', documentId) + azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'CloseDocument', documentId) def SelectLightingPreset(presetName): azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, 'SelectLightingPresetByName', presetName) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h index ed002f65ed..d0e6aea5b9 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h @@ -7,14 +7,10 @@ */ #pragma once -#include -#include -#include -#include - -#include #include #include +#include +#include namespace ShaderManagementConsole { @@ -27,12 +23,6 @@ namespace ShaderManagementConsole static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; typedef AZ::Uuid BusIdType; - //! Get absolute path of document - virtual AZStd::string_view GetAbsolutePath() const = 0; - - //! Get relative path of document - virtual AZStd::string_view GetRelativePath() const = 0; - //! Get the number of options virtual size_t GetShaderOptionCount() const = 0; @@ -44,47 +34,6 @@ namespace ShaderManagementConsole //! Get the information for the shader variant at the specified index virtual const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const = 0; - - //! Load document and related data - //! @param loadPath Absolute path of document to load - virtual bool Open(AZStd::string_view loadPath) = 0; - - //! Save document to file - virtual bool Save() = 0; - - //! Save document copy - //! @param savePath Absolute path where document is saved - virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; - - //! Close document and reset its data - virtual bool Close() = 0; - - //! document is loaded - virtual bool IsOpen() const = 0; - - //! document has changes pending - virtual bool IsModified() const = 0; - - //! Can the document be saved - virtual bool IsSavable() const = 0; - - //! Returns true if there are reversible modifications to the document - virtual bool CanUndo() const = 0; - - //! Returns true if there are changes that were reversed and can be re-applied to the document - virtual bool CanRedo() const = 0; - - //! Restores the previous state of the document - virtual bool Undo() = 0; - - //! Restores the next state of the document - virtual bool Redo() = 0; - - //! Signal that editing is about to begin, like beginning to drag a slider control - virtual bool BeginEdit() = 0; - - //! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control - virtual bool EndEdit() = 0; }; using ShaderManagementConsoleDocumentRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h deleted file mode 100644 index 93c46f442f..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h +++ /dev/null @@ -1,62 +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 - -#include - -namespace ShaderManagementConsole -{ - //! ShaderManagementConsoleDocumentSystemRequestBus provides high level file requests for menus, scripts, etc. - class ShaderManagementConsoleDocumentSystemRequests - : public AZ::EBusTraits - { - public: - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - //! Create a document object - //! @return Uuid of new document, or null Uuid if failed - virtual AZ::Uuid CreateDocument() = 0; - - //! Destroy a document object with the specified id - //! @return true if Uuid was found and removed, otherwise false - virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0; - - //! Open a document for editing - //! @param sourcePath document to open. - //! @return unique id of new document if successful, otherwise null Uuid - virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0; - - //! Close the specified document - //! @param documentId unique id of document to close - virtual bool CloseDocument(const AZ::Uuid& documentId) = 0; - - //! Close all documents - virtual bool CloseAllDocuments() = 0; - - //! Close all documents except for documentId - //! @param documentId unique id of document to not close - virtual bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) = 0; - - //! Save the specified document - //! @param documentId unique id of document to save - virtual bool SaveDocument(const AZ::Uuid& documentId) = 0; - - //! Save the specified document to a different file - //! @param documentId unique id of document to save - //! @param targetPath location where document is saved. - virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; - - //! Save all documents - virtual bool SaveAllDocuments() = 0; - }; - - using ShaderManagementConsoleDocumentSystemRequestBus = AZ::EBus; - -} // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp index 9dae9c10cc..9a836c5c05 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp @@ -8,49 +8,32 @@ #include #include - -#include -#include - +#include #include #include #include +#include namespace ShaderManagementConsole { ShaderManagementConsoleDocument::ShaderManagementConsoleDocument() + : AtomToolsFramework::AtomToolsDocument() { ShaderManagementConsoleDocumentRequestBus::Handler::BusConnect(m_id); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentCreated, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); } ShaderManagementConsoleDocument::~ShaderManagementConsoleDocument() { - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); ShaderManagementConsoleDocumentRequestBus::Handler::BusDisconnect(); Clear(); } - const AZ::Uuid& ShaderManagementConsoleDocument::GetId() const - { - return m_id; - } - - AZStd::string_view ShaderManagementConsoleDocument::GetAbsolutePath() const - { - return m_absolutePath; - } - - AZStd::string_view ShaderManagementConsoleDocument::GetRelativePath() const - { - return m_relativePath; - } - size_t ShaderManagementConsoleDocument::GetShaderOptionCount() const { auto layout = m_shaderAsset->GetShaderOptionGroupLayout(); auto& shaderOptionDescriptors = layout->GetShaderOptions(); - return shaderOptionDescriptors.size(); } @@ -58,7 +41,6 @@ namespace ShaderManagementConsole { auto layout = m_shaderAsset->GetShaderOptionGroupLayout(); auto& shaderOptionDescriptors = layout->GetShaderOptions(); - return shaderOptionDescriptors[index]; } @@ -128,75 +110,12 @@ namespace ShaderManagementConsole return false; } - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); AZ_TracePrintf("ShaderManagementConsoleDocument", "Document loaded: '%s'", m_absolutePath.c_str()); return true; } - bool ShaderManagementConsoleDocument::Save() - { - if (!IsOpen()) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); - return false; - } - - if (!IsSavable()) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document can not be saved: '%s'.", m_absolutePath.c_str()); - return false; - } - - AZ_Error("ShaderManagementConsoleDocument", false, "%s is not implemented!", __FUNCTION__); - return false; - - // Auto add or checkout saved file - //AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - // m_absolutePath.c_str(), true, - // [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - - //ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id); - - //AZ_TracePrintf("ShaderManagementConsoleDocument", "Document saved: %s", m_absolutePath.data()); - //return true; - } - - bool ShaderManagementConsoleDocument::SaveAsCopy(AZStd::string_view savePath) - { - if (!IsOpen()) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); - return false; - } - - if (!IsSavable()) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document can not be saved: '%s'.", m_absolutePath.c_str()); - return false; - } - - AZStd::string normalizedSavePath = savePath; - if (!AzFramework::StringFunc::Path::Normalize(normalizedSavePath)) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document save path could not be normalized: '%s'.", normalizedSavePath.c_str()); - return false; - } - - AZ_Error("ShaderManagementConsoleDocument", false, "%s is not implemented!", __FUNCTION__); - return false; - - // Auto add or checkout saved file - //AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - // normalizedSavePath.c_str(), true, - // [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - - //ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id); - - //AZ_TracePrintf("ShaderManagementConsoleDocument", "Document saved: %s", normalizedSavePath.c_str()); - //return true; - } - bool ShaderManagementConsoleDocument::Close() { if (!IsOpen()) @@ -206,7 +125,7 @@ namespace ShaderManagementConsole } Clear(); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentClosed, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); AZ_TracePrintf("ShaderManagementConsoleDocument", "Document was closed"); return true; } @@ -216,81 +135,11 @@ namespace ShaderManagementConsole return !m_absolutePath.empty() && !m_relativePath.empty(); } - bool ShaderManagementConsoleDocument::IsModified() const - { - return false; - } - - bool ShaderManagementConsoleDocument::IsSavable() const - { - return true; - } - - bool ShaderManagementConsoleDocument::CanUndo() const - { - // Undo will only be allowed if something has been recorded and we're not at the beginning of history - return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex > 0; - } - - bool ShaderManagementConsoleDocument::CanRedo() const - { - // Redo will only be allowed if something has been recorded and we're not at the end of history - return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex < m_undoHistory.size(); - } - - bool ShaderManagementConsoleDocument::Undo() - { - if (CanUndo()) - { - // The history index is one beyond the last executed command. Decrement the index then execute undo. - m_undoHistory[--m_undoHistoryIndex].first(); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); - return true; - } - return false; - } - - bool ShaderManagementConsoleDocument::Redo() - { - if (CanRedo()) - { - // Execute the current redo command then move the history index to the next position. - m_undoHistory[m_undoHistoryIndex++].second(); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); - return true; - } - return false; - } - - bool ShaderManagementConsoleDocument::BeginEdit() - { - return true; - } - - bool ShaderManagementConsoleDocument::EndEdit() - { - // Wipe any state beyond the current history index - m_undoHistory.erase(m_undoHistory.begin() + m_undoHistoryIndex, m_undoHistory.end()); - - // Add undo and redo operations using lambdas that will capture property state and restore it when executed - m_undoHistory.emplace_back( - [this]() { /**/ }, - [this]() { /**/ }); - - // Assign the index to the end of history - m_undoHistoryIndex = aznumeric_cast(m_undoHistory.size()); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); - - return true; - } - void ShaderManagementConsoleDocument::Clear() { m_absolutePath.clear(); m_relativePath.clear(); m_shaderVariantListSourceData = {}; m_shaderAsset = {}; - m_undoHistory = {}; - m_undoHistoryIndex = {}; } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h index 3d1a88c62e..eb7d6b87a0 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h @@ -7,13 +7,12 @@ */ #pragma once -#include -#include - -#include -#include - #include +#include +#include +#include +#include +#include namespace ShaderManagementConsole { @@ -21,7 +20,8 @@ namespace ShaderManagementConsole * ShaderManagementConsoleDocument provides an API for modifying and saving document properties. */ class ShaderManagementConsoleDocument - : public ShaderManagementConsoleDocumentRequestBus::Handler + : public AtomToolsFramework::AtomToolsDocument + , public ShaderManagementConsoleDocumentRequestBus::Handler { public: AZ_RTTI(ShaderManagementConsoleDocument, "{DBA269AE-892B-415C-8FA1-166B94B0E045}"); @@ -31,29 +31,20 @@ namespace ShaderManagementConsole ShaderManagementConsoleDocument(); virtual ~ShaderManagementConsoleDocument(); - const AZ::Uuid& GetId() const; + //////////////////////////////////////////////////////////////////////// + // AtomToolsFramework::AtomToolsDocument + //////////////////////////////////////////////////////////////////////// + bool Open(AZStd::string_view loadPath) override; + bool Close() override; + bool IsOpen() const override; + //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // ShaderManagementConsoleDocumentRequestBus::Handler implementation - AZStd::string_view GetAbsolutePath() const override; - AZStd::string_view GetRelativePath() const override; size_t GetShaderOptionCount() const override; const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const override; size_t GetShaderVariantCount() const override; const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const override; - bool Open(AZStd::string_view loadPath) override; - bool Save() override; - bool SaveAsCopy(AZStd::string_view savePath) override; - bool Close() override; - bool IsOpen() const override; - bool IsModified() const override; - bool IsSavable() const override; - bool CanUndo() const override; - bool CanRedo() const override; - bool Undo() override; - bool Redo() override; - bool BeginEdit() override; - bool EndEdit() override; //////////////////////////////////////////////////////////////////////// private: @@ -67,28 +58,11 @@ namespace ShaderManagementConsole using UndoRedoHistory = AZStd::vector; void Clear(); - - // Unique id of this document - AZ::Uuid m_id = AZ::Uuid::CreateRandom(); - - // Relative path to the document - AZStd::string m_relativePath; - - // Absolute path to the document - AZStd::string m_absolutePath; // Source data for shader variant list AZ::RPI::ShaderVariantListSourceData m_shaderVariantListSourceData; // Shader asset for the corresponding shader variant list AZ::Data::Asset m_shaderAsset; - - // Variables needed for tracking the undo and redo state of this document - - // Container of undo commands - UndoRedoHistory m_undoHistory; - - // The current position in the undo redo history - int m_undoHistoryIndex = 0; }; } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp index 4987b0528f..a9415fd85b 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp @@ -7,10 +7,8 @@ */ #include -#include - -#include #include +#include namespace ShaderManagementConsole { diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp index f06aae29d7..55b800067a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp @@ -6,41 +6,16 @@ * */ -#include - -#include -#include +#include +#include #include #include #include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -#include -#include -AZ_POP_DISABLE_WARNING +#include +#include namespace ShaderManagementConsole { - ShaderManagementConsoleDocumentSystemComponent::ShaderManagementConsoleDocumentSystemComponent() - { - } - void ShaderManagementConsoleDocumentSystemComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serialize = azrtti_cast(context)) @@ -52,7 +27,7 @@ namespace ShaderManagementConsole { ec->Class("ShaderManagementConsoleDocumentSystemComponent", "Manages documents") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System")) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ; } @@ -60,64 +35,35 @@ namespace ShaderManagementConsole if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("ShaderManagementConsoleDocumentSystemRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("CreateDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CreateDocument) - ->Event("DestroyDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument) - ->Event("OpenDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument) - ->Event("CloseDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument) - ->Event("CloseAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments) - ->Event("CloseAllDocumentsExcept", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept) - ->Event("SaveDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument) - ->Event("SaveDocumentAsCopy", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy) - ->Event("SaveAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments) - ; - behaviorContext->EBus("ShaderManagementConsoleDocumentRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("GetAbsolutePath", &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath) - ->Event("GetRelativePath", &ShaderManagementConsoleDocumentRequestBus::Events::GetRelativePath) ->Event("GetShaderOptionCount", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionCount) ->Event("GetShaderOptionDescriptor", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor) ->Event("GetShaderVariantCount", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount) ->Event("GetShaderVariantInfo", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantInfo) - ->Event("Open", &ShaderManagementConsoleDocumentRequestBus::Events::Open) - ->Event("Close", &ShaderManagementConsoleDocumentRequestBus::Events::Close) - ->Event("Save", &ShaderManagementConsoleDocumentRequestBus::Events::Save) - ->Event("SaveAsCopy", &ShaderManagementConsoleDocumentRequestBus::Events::SaveAsCopy) - ->Event("IsOpen", &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen) - ->Event("IsModified", &ShaderManagementConsoleDocumentRequestBus::Events::IsModified) - ->Event("IsSavable", &ShaderManagementConsoleDocumentRequestBus::Events::IsSavable) - ->Event("CanUndo", &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo) - ->Event("CanRedo", &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo) - ->Event("Undo", &ShaderManagementConsoleDocumentRequestBus::Events::Undo) - ->Event("Redo", &ShaderManagementConsoleDocumentRequestBus::Events::Redo) - ->Event("BeginEdit", &ShaderManagementConsoleDocumentRequestBus::Events::BeginEdit) - ->Event("EndEdit", &ShaderManagementConsoleDocumentRequestBus::Events::EndEdit) ; } } void ShaderManagementConsoleDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc)); - required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("RPISystem", 0xf2add773)); + required.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); + required.push_back(AZ_CRC_CE("AssetProcessorToolsConnection")); + required.push_back(AZ_CRC_CE("AssetDatabaseService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("RPISystem")); } void ShaderManagementConsoleDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("ShaderManagementConsoleDocumentSystemService")); + provided.push_back(AZ_CRC_CE("ShaderManagementConsoleDocumentSystemService")); } void ShaderManagementConsoleDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("ShaderManagementConsoleDocumentSystemService")); + incompatible.push_back(AZ_CRC_CE("ShaderManagementConsoleDocumentSystemService")); } void ShaderManagementConsoleDocumentSystemComponent::Init() @@ -126,256 +72,15 @@ namespace ShaderManagementConsole void ShaderManagementConsoleDocumentSystemComponent::Activate() { - m_documentMap.clear(); - ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, + []() + { + return aznew ShaderManagementConsoleDocument(); + }); } void ShaderManagementConsoleDocumentSystemComponent::Deactivate() { - ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusDisconnect(); - m_documentMap.clear(); - } - - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::CreateDocument() - { - auto document = AZStd::make_unique(); - if (!document) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Failed to create new document"); - return AZ::Uuid::CreateNull(); - } - - AZ::Uuid documentId = document->GetId(); - m_documentMap.emplace(documentId, document.release()); - return documentId; - } - - bool ShaderManagementConsoleDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId) - { - return m_documentMap.erase(documentId) != 0; - } - - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath) - { - return OpenDocumentImpl(sourcePath, true); - } - - bool ShaderManagementConsoleDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) - { - bool isOpen = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen); - if (!isOpen) - { - // immediately destroy unopened documents - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return true; - } - - AZStd::string documentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - - bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); - if (isModified) - { - auto selection = QMessageBox::question(QApplication::activeWindow(), - QString("Document has unsaved changes"), - QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (selection == QMessageBox::Cancel) - { - AZ_TracePrintf("ShaderManagementConsoleDocument", "Close document canceled: %s", documentPath.c_str()); - return false; - } - if (selection == QMessageBox::Yes) - { - if (!SaveDocument(documentId)) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str()); - return false; - } - } - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool closeResult = true; - ShaderManagementConsoleDocumentRequestBus::EventResult(closeResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Close); - if (!closeResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be closed"), - QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return true; - } - - bool ShaderManagementConsoleDocumentSystemComponent::CloseAllDocuments() - { - bool result = true; - auto documentMap = m_documentMap; - for (const auto& documentPair : documentMap) - { - if (!CloseDocument(documentPair.first)) - { - result = false; - } - } - - return result; - } - - bool ShaderManagementConsoleDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) - { - bool result = true; - auto documentMap = m_documentMap; - for (const auto& documentPair : documentMap) - { - if (documentPair.first != documentId) - { - if (!CloseDocument(documentPair.first)) - { - result = false; - } - } - } - - return result; - } - - bool ShaderManagementConsoleDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) - { - AZStd::string saveDocumentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(saveDocumentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Save); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool ShaderManagementConsoleDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) - { - AZStd::string saveDocumentPath = targetPath; - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool ShaderManagementConsoleDocumentSystemComponent::SaveAllDocuments() - { - bool result = true; - for (const auto& documentPair : m_documentMap) - { - if (!SaveDocument(documentPair.first)) - { - result = false; - } - } - - return result; - } - - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) - { - AZStd::string requestedPath = sourcePath; - if (requestedPath.empty()) - { - return AZ::Uuid::CreateNull(); - } - - if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); - return AZ::Uuid::CreateNull(); - } - - // Determine if the file is already open and select it - if (checkIfAlreadyOpen) - { - for (const auto& documentPair : m_documentMap) - { - AZStd::string openDocumentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - if (openDocumentPath == requestedPath) - { - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); - return documentPair.first; - } - } - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - AZ::Uuid documentId = AZ::Uuid::CreateNull(); - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(documentId, &ShaderManagementConsoleDocumentSystemRequestBus::Events::CreateDocument); - if (documentId.IsNull()) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be created"), - QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return AZ::Uuid::CreateNull(); - } - - traceRecorder.GetDump().clear(); - - bool openResult = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(openResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Open, requestedPath); - if (!openResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return AZ::Uuid::CreateNull(); - } - - return documentId; } } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h index 05c61ce058..1ee825f6de 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h @@ -9,28 +9,17 @@ #pragma once #include -#include - -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { - //! ShaderManagementConsoleDocumentSystemComponent is the central component of the Shader Management Console Core gem + //! ShaderManagementConsoleDocumentSystemComponent class ShaderManagementConsoleDocumentSystemComponent : public AZ::Component - , private ShaderManagementConsoleDocumentSystemRequestBus::Handler { public: - AZ_COMPONENT(ShaderManagementConsoleDocumentSystemComponent, "{58ABE0AE-2710-41E2-ADFD-E2D67407427D}"); + AZ_COMPONENT(ShaderManagementConsoleDocumentSystemComponent, "{1610159D-59DC-48B1-B2D1-FCE7AFD3B012}"); - ShaderManagementConsoleDocumentSystemComponent(); + ShaderManagementConsoleDocumentSystemComponent() = default; ~ShaderManagementConsoleDocumentSystemComponent() = default; ShaderManagementConsoleDocumentSystemComponent(const ShaderManagementConsoleDocumentSystemComponent&) = delete; ShaderManagementConsoleDocumentSystemComponent& operator =(const ShaderManagementConsoleDocumentSystemComponent&) = delete; @@ -48,23 +37,5 @@ namespace ShaderManagementConsole void Activate() override; void Deactivate() override; //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides... - AZ::Uuid CreateDocument() override; - bool DestroyDocument(const AZ::Uuid& documentId) override; - AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; - bool CloseDocument(const AZ::Uuid& documentId) override; - bool CloseAllDocuments() override; - bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override; - bool SaveDocument(const AZ::Uuid& documentId) override; - bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; - bool SaveAllDocuments() override; - //////////////////////////////////////////////////////////////////////// - - AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); - - AZStd::unordered_map> m_documentMap; - const size_t m_maxMessageBoxLineCount = 15; }; } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 313522a256..3d07a0de15 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -7,8 +7,8 @@ */ #include -#include #include +#include #include #include #include @@ -66,8 +66,8 @@ namespace ShaderManagementConsole const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast( - &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } Base::ProcessCommandLine(commandLine); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 24b2020dad..6596429577 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -8,8 +8,8 @@ #pragma once -#include #include +#include namespace ShaderManagementConsole { diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserInteractions.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserInteractions.cpp index c0b9f5502c..b82d348df3 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserInteractions.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserInteractions.cpp @@ -6,28 +6,24 @@ * */ -#include -#include -#include -#include -#include -#include - -#include - +#include +#include +#include #include - +#include #include +#include #include #include -#include #include -#include +#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include namespace ShaderManagementConsole { @@ -80,7 +76,7 @@ namespace ShaderManagementConsole { if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath().c_str()); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath().c_str()); } else { diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.cpp index 588dccca1b..eb863a195a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.cpp @@ -6,26 +6,21 @@ * */ -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include #include - -#include - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -85,14 +80,14 @@ namespace ShaderManagementConsole }); AssetBrowserModelNotificationBus::Handler::BusConnect(); - ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); } ShaderManagementConsoleBrowserWidget::~ShaderManagementConsoleBrowserWidget() { // Maintains the tree expansion state between runs m_ui->m_assetBrowserTreeViewWidget->SaveState(); - ShaderManagementConsoleDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); AssetBrowserModelNotificationBus::Handler::BusDisconnect(); } @@ -150,7 +145,7 @@ namespace ShaderManagementConsole { if (AzFramework::StringFunc::Path::IsExtension(sourceEntry->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, sourceEntry->GetFullPath()); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, sourceEntry->GetFullPath()); } else { @@ -192,7 +187,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId) { AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); if (!absolutePath.empty()) { m_pathToSelect = absolutePath; @@ -203,4 +198,4 @@ namespace ShaderManagementConsole } // namespace ShaderManagementConsole -#include +#include diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h index d251ab26f9..73a2a24aa9 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h @@ -9,11 +9,10 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include -#include #include #include -#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -44,7 +43,7 @@ namespace ShaderManagementConsole class ShaderManagementConsoleBrowserWidget : public QWidget , public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler - , public ShaderManagementConsoleDocumentNotificationBus::Handler + , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: @@ -64,7 +63,7 @@ namespace ShaderManagementConsole // AssetBrowserModelNotificationBus::Handler implementation void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override; - // ShaderManagementConsoleDocumentNotificationBus::Handler implementation + // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler implementation void OnDocumentOpened(const AZ::Uuid& documentId) override; }; } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 34487e0cb5..0b4802640b 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -13,12 +13,11 @@ #include #include #include - #include #include - #include -#include +#include +#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT @@ -62,19 +61,19 @@ namespace ShaderManagementConsole // Restore geometry and show the window mainWindowWrapper->showFromSettings(); - ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); OnDocumentOpened(AZ::Uuid::CreateNull()); } ShaderManagementConsoleWindow::~ShaderManagementConsoleWindow() { - ShaderManagementConsoleDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); } void ShaderManagementConsoleWindow::closeEvent(QCloseEvent* closeEvent) { bool didClose = true; - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(didClose, &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); if (!didClose) { closeEvent->ignore(); @@ -88,17 +87,17 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::OnDocumentOpened(const AZ::Uuid& documentId) { bool isOpen = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen); bool isSavable = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isSavable, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsSavable); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsSavable); bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); bool canUndo = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(canUndo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo); bool canRedo = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(canRedo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo); AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); @@ -150,7 +149,7 @@ namespace ShaderManagementConsole const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Document closed: %1").arg(documentPath); + const QString status = QString("Document opened: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } } @@ -167,9 +166,9 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId) { bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); @@ -180,9 +179,9 @@ namespace ShaderManagementConsole if (documentId == GetDocumentIdFromTab(m_tabWidget->currentIndex())) { bool canUndo = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(canUndo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo); bool canRedo = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(canRedo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo); m_actionUndo->setEnabled(canUndo); m_actionRedo->setEnabled(canRedo); } @@ -191,15 +190,15 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::OnDocumentSaved(const AZ::Uuid& documentId) { bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document closed: %1").arg(documentPath); + const QString status = QString("Document saved: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } @@ -217,7 +216,7 @@ namespace ShaderManagementConsole const AZStd::string filePath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData(); if (!filePath.empty()) { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, filePath); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, filePath); } }, QKeySequence::Open); @@ -228,11 +227,11 @@ namespace ShaderManagementConsole m_actionSave = m_menuFile->addAction("&Save", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Save); @@ -242,21 +241,21 @@ namespace ShaderManagementConsole const QString documentPath = GetDocumentPath(documentId); bool result = false; - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy, documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::SaveAs); m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() { bool result = false; - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Failed to save documents."); + const QString status = QString("Document save all failed."); m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -265,16 +264,16 @@ namespace ShaderManagementConsole m_actionClose = m_menuFile->addAction("&Close", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }, QKeySequence::Close); m_actionCloseAll = m_menuFile->addAction("Close All", [this]() { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); }); m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); m_menuFile->addSeparator(); @@ -298,11 +297,11 @@ namespace ShaderManagementConsole m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform undo on document: %1").arg(documentPath); + const QString status = QString("Document undo failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -310,11 +309,11 @@ namespace ShaderManagementConsole m_actionRedo = m_menuEdit->addAction("&Redo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform redo on document: %1").arg(documentPath); + const QString status = QString("Document redo failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); @@ -366,19 +365,19 @@ namespace ShaderManagementConsole // This should automatically clear the active document connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) { const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) { const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }); } QString ShaderManagementConsoleWindow::GetDocumentPath(const AZ::Uuid& documentId) const { AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Handler::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Handler::GetAbsolutePath); return absolutePath.c_str(); } @@ -394,15 +393,15 @@ namespace ShaderManagementConsole const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select"; tabMenu.addAction(selectActionName, [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); tabMenu.addAction("Close", [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }); auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); closeOthersAction->setEnabled(tabBar->count() > 1); tabMenu.exec(QCursor::pos()); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index 7f3f772961..2b682f6c09 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -9,9 +9,9 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include #include +#include #include #include @@ -31,7 +31,7 @@ namespace ShaderManagementConsole */ class ShaderManagementConsoleWindow : public AtomToolsFramework::AtomToolsMainWindow - , private ShaderManagementConsoleDocumentNotificationBus::Handler + , private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: @@ -43,7 +43,7 @@ namespace ShaderManagementConsole ~ShaderManagementConsoleWindow(); private: - // ShaderManagementConsoleDocumentNotificationBus::Handler overrides... + // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides... void OnDocumentOpened(const AZ::Uuid& documentId) override; void OnDocumentClosed(const AZ::Uuid& documentId) override; void OnDocumentModified(const AZ::Uuid& documentId) override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp index a89cdfddb8..a59712d572 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp @@ -6,25 +6,20 @@ * */ -#include - -#include -#include -#include - #include - -#include -#include +#include +#include +#include +#include +#include #include - +#include +#include #include #include #include - -#include -#include -#include +#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsole_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsole_files.cmake index 6442df4832..e832ba2784 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsole_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsole_files.cmake @@ -10,7 +10,5 @@ set(FILES Source/main.cpp Source/ShaderManagementConsoleApplication.cpp Source/ShaderManagementConsoleApplication.h - Include/Atom/Document/ShaderManagementConsoleDocumentModule.h - Source/Document/ShaderManagementConsoleDocumentModule.cpp ../Scripts/GenerateShaderVariantListForMaterials.py ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsoledocument_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsoledocument_files.cmake index e703f5efcc..220d2895ac 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsoledocument_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsoledocument_files.cmake @@ -7,11 +7,11 @@ # set(FILES - Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h - Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h + Include/Atom/Document/ShaderManagementConsoleDocumentModule.h Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h - Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp - Source/Document/ShaderManagementConsoleDocumentSystemComponent.h Source/Document/ShaderManagementConsoleDocument.cpp Source/Document/ShaderManagementConsoleDocument.h + Source/Document/ShaderManagementConsoleDocumentModule.cpp + Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp + Source/Document/ShaderManagementConsoleDocumentSystemComponent.h ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Scripts/GenerateShaderVariantListForMaterials.py b/Gems/Atom/Tools/ShaderManagementConsole/Scripts/GenerateShaderVariantListForMaterials.py index 6c5e8df3dd..7bd65568ed 100755 --- a/Gems/Atom/Tools/ShaderManagementConsole/Scripts/GenerateShaderVariantListForMaterials.py +++ b/Gems/Atom/Tools/ShaderManagementConsole/Scripts/GenerateShaderVariantListForMaterials.py @@ -153,7 +153,7 @@ def main(): azlmbr.shader.SaveShaderVariantListSourceData(shaderVariantListFilePath, shaderVariantList) # Open the document in shader management console - result = azlmbr.shadermanagementconsole.ShaderManagementConsoleDocumentSystemRequestBus( + result = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus( azlmbr.bus.Broadcast, 'OpenDocument', shaderVariantListFilePath From 4cf384c2c555919e9e234c02c4d87fa0aef21840 Mon Sep 17 00:00:00 2001 From: moudgils <47460854+moudgils@users.noreply.github.com> Date: Thu, 12 Aug 2021 21:12:41 -0700 Subject: [PATCH 047/101] Fix minor typo (#3095) Signed-off-by: moudgils --- .../Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm | 4 ++-- .../Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm index f9eef9170a..272faeb4c1 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm @@ -34,7 +34,7 @@ namespace AzFramework bool GetFullScreenState() const override; void SetFullScreenState(bool fullScreenState) override; bool CanToggleFullScreenState() const override { return true; } - uint32_t GetMainDisplayRefreshRate() const; + uint32_t GetDisplayRefreshRate() const override; private: static NSWindowStyleMask ConvertToNSWindowStyleMask(const WindowStyleMasks& styleMasks); @@ -142,7 +142,7 @@ namespace AzFramework return nativeMask ? nativeMask : defaultMask; } - uint32_t NativeWindowImpl_Darwin::GetMainDisplayRefreshRate() const + uint32_t NativeWindowImpl_Darwin::GetDisplayRefreshRate() const { return m_mainDisplayRefreshRate; } diff --git a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm index 83e176b9ef..0486ca1b92 100644 --- a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm +++ b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm @@ -27,7 +27,7 @@ namespace AzFramework const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) override; NativeWindowHandle GetWindowHandle() const override; - uint32_t GetMainDisplayRefreshRate() const; + uint32_t GetDisplayRefreshRate() const override; private: UIWindow* m_nativeWindow; @@ -66,7 +66,7 @@ namespace AzFramework return m_nativeWindow; } - uint32_t NativeWindowImpl_Ios::GetMainDisplayRefreshRate() const + uint32_t NativeWindowImpl_Ios::GetDisplayRefreshRate() const { return m_mainDisplayRefreshRate; } From 364ac5150272c2931a1df36e277af8a913d1e00c Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 13 Aug 2021 00:19:43 -0500 Subject: [PATCH 048/101] Removed errors from unimplemented status functions Updated shader management console trace messages Renamed document rebuild function to reopen Signed-off-by: Guthrie Adams --- .../AtomToolsFramework/Document/AtomToolsDocument.h | 2 +- .../Document/AtomToolsDocumentRequestBus.h | 4 ++-- .../Code/Source/Document/AtomToolsDocument.cpp | 7 +------ .../Document/AtomToolsDocumentSystemComponent.cpp | 10 +++++----- .../Code/Source/Document/MaterialDocument.cpp | 2 +- .../Code/Source/Document/MaterialDocument.h | 2 +- .../Document/ShaderManagementConsoleDocument.cpp | 4 ++-- 7 files changed, 13 insertions(+), 18 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h index 390a08e5b1..565c9f00a3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h @@ -37,7 +37,7 @@ namespace AtomToolsFramework bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; bool Open(AZStd::string_view loadPath) override; - bool Rebuild() override; + bool Reopen() override; bool Save() override; bool SaveAsCopy(AZStd::string_view savePath) override; bool SaveAsChild(AZStd::string_view savePath) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h index 42fcab95ae..a8ef7852ea 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h @@ -46,8 +46,8 @@ namespace AtomToolsFramework //! @param loadPath absolute path of document to load virtual bool Open(AZStd::string_view loadPath) = 0; - //! Reload document preserving edits - virtual bool Rebuild() = 0; + //! Reopen document preserving edits + virtual bool Reopen() = 0; //! Save document to file virtual bool Save() = 0; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp index c3216c6d9d..48212fe154 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -67,7 +67,7 @@ namespace AtomToolsFramework return false; } - bool AtomToolsDocument::Rebuild() + bool AtomToolsDocument::Reopen() { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; @@ -100,31 +100,26 @@ namespace AtomToolsFramework bool AtomToolsDocument::IsOpen() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } bool AtomToolsDocument::IsModified() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } bool AtomToolsDocument::IsSavable() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } bool AtomToolsDocument::CanUndo() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } bool AtomToolsDocument::CanRedo() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index fa7280068e..5652e9fe23 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -79,7 +79,7 @@ namespace AtomToolsFramework ->Event("GetPropertyValue", &AtomToolsDocumentRequestBus::Events::GetPropertyValue) ->Event("SetPropertyValue", &AtomToolsDocumentRequestBus::Events::SetPropertyValue) ->Event("Open", &AtomToolsDocumentRequestBus::Events::Open) - ->Event("Rebuild", &AtomToolsDocumentRequestBus::Events::Rebuild) + ->Event("Reopen", &AtomToolsDocumentRequestBus::Events::Reopen) ->Event("Close", &AtomToolsDocumentRequestBus::Events::Close) ->Event("Save", &AtomToolsDocumentRequestBus::Events::Save) ->Event("SaveAsChild", &AtomToolsDocumentRequestBus::Events::SaveAsChild) @@ -168,7 +168,7 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId) { - m_documentIdsToRebuild.insert(documentId); + m_documentIdsToReopen.insert(documentId); if (!AZ::TickBus::Handler::BusIsConnected()) { AZ::TickBus::Handler::BusConnect(); @@ -204,7 +204,7 @@ namespace AtomToolsFramework } } - for (const AZ::Uuid& documentId : m_documentIdsToRebuild) + for (const AZ::Uuid& documentId : m_documentIdsToReopen) { AZStd::string documentPath; AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); @@ -221,7 +221,7 @@ namespace AtomToolsFramework AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool openResult = false; - AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Rebuild); + AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Reopen); if (!openResult) { QMessageBox::critical( @@ -231,7 +231,7 @@ namespace AtomToolsFramework } } - m_documentIdsToRebuild.clear(); + m_documentIdsToReopen.clear(); m_documentIdsToReopen.clear(); AZ::TickBus::Handler::BusDisconnect(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 298d38f650..11834beb73 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -182,7 +182,7 @@ namespace MaterialEditor return true; } - bool MaterialDocument::Rebuild() + bool MaterialDocument::Reopen() { // Store history and property changes that should be reapplied after reload auto undoHistoryToRestore = m_undoHistory; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 09a1873dcf..d732680b7b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -48,7 +48,7 @@ namespace MaterialEditor bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; bool Open(AZStd::string_view loadPath) override; - bool Rebuild() override; + bool Reopen() override; bool Save() override; bool SaveAsCopy(AZStd::string_view savePath) override; bool SaveAsChild(AZStd::string_view savePath) override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp index 9a836c5c05..2b7767635e 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp @@ -112,7 +112,7 @@ namespace ShaderManagementConsole AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); - AZ_TracePrintf("ShaderManagementConsoleDocument", "Document loaded: '%s'", m_absolutePath.c_str()); + AZ_TracePrintf("ShaderManagementConsoleDocument", "Document opened: '%s'\n", m_absolutePath.c_str()); return true; } @@ -126,7 +126,7 @@ namespace ShaderManagementConsole Clear(); AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); - AZ_TracePrintf("ShaderManagementConsoleDocument", "Document was closed"); + AZ_TracePrintf("ShaderManagementConsoleDocument", "Document closed\n"); return true; } From 706333466e2137f11ba96105907f75291722d4c3 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 12 Aug 2021 23:58:51 -0700 Subject: [PATCH 049/101] Addressing PR feedback and making PassBuilder error if referenced shader isn't found Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Source/RPI.Builders/Pass/PassBuilder.cpp | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index a803ecf31a..f74792049f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -70,16 +70,16 @@ namespace AZ // Helper class to pass parameters to the AddDependency and FindReferencedAssets functions below struct FindPassReferenceAssetParams { - void* passAssetObject; + void* passAssetObject = nullptr; Uuid passAssetUuid; - SerializeContext* serializeContext; - AZStd::string_view passAssetSourceFile; // File path of the pass asset - AZStd::string_view dependencySourceFile; // File pass of the asset the pass asset depends on - const char* jobKey; // Job key for adding job dependency + SerializeContext* serializeContext = nullptr; + AZStd::string_view passAssetSourceFile; // File path of the pass asset + AZStd::string_view dependencySourceFile; // File pass of the asset the pass asset depends on + const char* jobKey = nullptr; // Job key for adding job dependency }; // Helper function to get a file reference and create a corresponding job dependency - void AddDependency(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) + bool AddDependency(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) { AZStd::string_view& file = params.dependencySourceFile; AZ::Data::AssetInfo sourceInfo; @@ -95,6 +95,12 @@ namespace AZ jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; job->m_jobDependencyList.push_back(jobDependency); AZ_TracePrintf(PassBuilderName, "Creating job dependency on file [%s] \n", file.data()); + return true; + } + else + { + AZ_Error(PassBuilderName, false, "Could not find referenced file [%s]", file.data()); + return false; } } @@ -104,7 +110,7 @@ namespace AZ SerializeContext::ErrorHandler errorLogger; errorLogger.Reset(); - bool foundProblems = false; + bool success = true; // This callback will check whether the given element is an asset reference. If so, it will add it to the list of asset references auto beginCallback = [&](void* ptr, const SerializeContext::ClassData* classData, [[maybe_unused]] const SerializeContext::ClassElement* classElement) @@ -123,7 +129,8 @@ namespace AZ if (job != nullptr) // Create Job Phase { params.dependencySourceFile = path; - AddDependency(params, job); + bool dependencyAddedSuccessfully = AddDependency(params, job); + success = dependencyAddedSuccessfully && success; } else // Process Job Phase { @@ -136,7 +143,7 @@ namespace AZ else { AZ_Error(PassBuilderName, false, "Could not get AssetId for [%s]", assetReference->m_filePath.c_str()); - foundProblems = true; + success = false; } } } @@ -162,7 +169,7 @@ namespace AZ , nullptr ); - return !foundProblems; + return success; } // --- Code related to dependency shader asset handling --- From 4dd39c392979db451abbb22b1f4bae6220a7ed27 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 13 Aug 2021 09:55:06 +0100 Subject: [PATCH 050/101] Address commit re-run corner case. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf.py | 47 ++++++---- .../tiaf_persistent_storage.py | 90 +++++++++++++++---- .../tiaf_persistent_storage_local.py | 13 ++- .../tiaf_persistent_storage_s3.py | 17 ++-- 4 files changed, 124 insertions(+), 43 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index 6a43ad3c70..28de00d6ba 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -87,7 +87,7 @@ class TestImpact: try: # Attempt to generate a diff between the src and dst commits - logger.error(f"Source '{self._src_commit}' and destination '{self._dst_commit}' will be diff'd.") + logger.info(f"Source '{self._src_commit}' and destination '{self._dst_commit}' will be diff'd.") diff_path = pathlib.Path(pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{self._instance_id}.diff")) self._repo.create_diff_file(self._src_commit, self._dst_commit, diff_path, multi_branch) except RuntimeError as e: @@ -219,28 +219,37 @@ class TestImpact: try: # Persistent storage location if s3_bucket: - persistent_storage = PersistentStorageS3(self._config, suite, s3_bucket, s3_top_level_dir, self._source_of_truth_branch) + persistent_storage = PersistentStorageS3(self._config, suite, self._dst_commit, s3_bucket, s3_top_level_dir, self._source_of_truth_branch) else: - persistent_storage = PersistentStorageLocal(self._config, suite) + persistent_storage = PersistentStorageLocal(self._config, suite, self._dst_commit) except SystemError as e: logger.warning(f"The persistent storage encountered an irrecoverable error, test impact analysis will be disabled: '{e}'") persistent_storage = None if persistent_storage: - # Flag to signify whether or not this is a re-run (multiple runs of the same commit) - # Right now, we don't fully support re-runs but in the future we will have an extra subfolder for each commit hash with the - # last run hash that was used for the first run for the commit so we can retreive the same reference point for building the - # change list to ensure each subsequent run is using the same data but for the time being, just perform a regular run - is_rerun = False + + # Flag for corner case where: + # 1. TIAF was already run previously for this commit. + # 2. There was no last commit hash when TIAF last ran on this commit (due to no coverage data existing get for this branch) + # 3. TIAF has not been run on any other commits between the run for this commit and the last run for this commit. + # The above results in TIAF being stuck in a state of generating an empty change list (and thus doing no work until another + # commit comes in) which is problematic if the commit needs to be re-run for whatever reason so in these conditions we revert + # back to a regular test run until another commit comes in + cannot_rerun_with_instrumentation = False + if persistent_storage.has_historic_data: logger.info("Historic data found.") self._src_commit = persistent_storage.last_commit_hash - # Perform some basic sanity checks on the commit hashes to ensure confidence in the integrity of the environment - if self._src_commit == self._dst_commit: - logger.info(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}', implying this is a re-run. A regular sequence will instead be performed.") - persistent_storage = None - is_rerun = True + # Check to see if this is a re-run for this commit before any other changes have come in + if persistent_storage.is_repeat_sequence: + if persistent_storage.can_rerun_sequence: + logger.info(f"This sequence is being re-run before any other changes have come in so the last commit '{persistent_storage.this_commit_last_commit_hash}' used for the previous sequence will be used instead.") + self._src_commit = persistent_storage.this_commit_last_commit_hash + else: + logger.info(f"This sequence is being re-run before any other changes have come in but there is no useful historic data. A regular sequence will be performed instead.") + persistent_storage = None + cannot_rerun_with_instrumentation = True else: self._attempt_to_generate_change_list() else: @@ -268,7 +277,7 @@ class TestImpact: args.append(f"--changelist={self._change_list_path}") logger.info(f"Change list is set to '{self._change_list_path}'.") else: - if self._is_source_of_truth_branch and not is_rerun: + if self._is_source_of_truth_branch and not cannot_rerun_with_instrumentation: # Use seed sequence (instrumented all tests) for coverage updating branches so we can generate the coverage bed for future sequences sequence_type = "seed" # We always continue after test failures when seeding to ensure we capture the coverage for all test targets @@ -314,14 +323,18 @@ class TestImpact: logger.info(f"Args: {unpacked_args}") runtime_result = subprocess.run([str(self._tiaf_bin)] + args) report = None - + # If the sequence completed (with or without failures) we will update the historical meta-data if runtime_result.returncode == 0 or runtime_result.returncode == 7: logger.info("Test impact analysis runtime returned successfully.") - if self._is_source_of_truth_branch and persistent_storage is not None: - persistent_storage.update_and_store_historic_data(self._dst_commit) + + # Get the sequence report the runtime generated with open(report_file) as json_file: report = json.load(json_file) + + # Attempt to store the historic data for this branch and sequence + if self._is_source_of_truth_branch and persistent_storage is not None: + persistent_storage.update_and_store_historic_data() else: logger.error(f"The test impact analysis runtime returned with error: '{runtime_result.returncode}'.") diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index 1ee3ac7e8c..3fff05b549 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -15,23 +15,39 @@ logger = get_logger(__file__) # Abstraction for the persistent storage required by TIAF to store and retrieve the branch coverage data and other meta-data class PersistentStorage(ABC): - def __init__(self, config: dict, suite: str): + + WORKSPACE_KEY = "workspace" + LAST_RUNS_KEY = "last_runs" + ACTIVE_KEY = "active" + ROOT_KEY = "root" + RELATIVE_PATHS_KEY = "relative_paths" + TEST_IMPACT_DATA_FILES_KEY = "test_impact_data_files" + LAST_COMMIT_HASH_KEY = "last_commit_hash" + COVERAGE_DATA_KEY = "coverage_data" + + def __init__(self, config: dict, suite: str, commit: str): """ Initializes the persistent storage into a state for which there is no historic data available. @param config: The runtime configuration to obtain the data file paths from. @param suite: The test suite for which the historic data will be obtained for. + @param commit: The commit hash for this build. """ # Work on the assumption that there is no historic meta-data (a valid state to be in, should none exist) self._last_commit_hash = None self._has_historic_data = False + self._has_previous_last_commit_hash = False + self._this_commit_hash = commit + self._this_commit_hash_last_commit_hash = None + self._historic_data = None + logger.info(f"Attempting to access persistent storage for the commit {self._this_commit_hash}") try: # The runtime expects the coverage data to be in the location specified in the config file (unless overridden with # the --datafile command line argument, which the TIAF scripts do not do) - self._active_workspace = pathlib.Path(config["workspace"]["active"]["root"]) - unpacked_coverage_data_file = config["workspace"]["active"]["relative_paths"]["test_impact_data_files"][suite] + self._active_workspace = pathlib.Path(config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.ROOT_KEY]) + unpacked_coverage_data_file = config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.RELATIVE_PATHS_KEY][self.TEST_IMPACT_DATA_FILES_KEY][suite] except KeyError as e: raise SystemError(f"The config does not contain the key {str(e)}.") @@ -45,17 +61,36 @@ class PersistentStorage(ABC): """ self._has_historic_data = False + self._has_previous_last_commit_hash = False try: - historic_data = json.loads(historic_data_json) - self._last_commit_hash = historic_data["last_commit_hash"] + self._historic_data = json.loads(historic_data_json) + + # Last commit hash for this branch + self._last_commit_hash = self._historic_data[self.LAST_COMMIT_HASH_KEY] logger.info(f"Last commit hash '{self._last_commit_hash}' found.") + if self.LAST_RUNS_KEY in self._historic_data: + # Last commit hash for the sequence that was run for this commit previously (if any) + if self._this_commit_hash in self._historic_data[self.LAST_RUNS_KEY]: + # 'None' is a valid value for the previously used last commit hash if there was no coverage data at that time + self._this_commit_hash_last_commit_hash = self._historic_data[self.LAST_RUNS_KEY][self._this_commit_hash] + self._has_previous_last_commit_hash = self._this_commit_hash_last_commit_hash is not None + + if self._has_previous_last_commit_hash: + logger.info(f"Last commit hash '{self._this_commit_hash_last_commit_hash}' was used previously for this commit.") + else: + logger.info(f"Prior sequence data found for this commit but it is empty (there was no coverage data vailable at that time).") + else: + logger.info(f"No prior sequence data found for commit '{self._this_commit_hash}', this is the first sequence for this commit.") + else: + logger.info(f"No prior sequence data found for any commits.") + # Create the active workspace directory where the coverage data file will be placed and unpack the coverage data so # it is accessible by the runtime self._active_workspace.mkdir(exist_ok=True) with open(self._unpacked_coverage_data_file, "w", newline='\n') as coverage_data: - coverage_data.write(historic_data["coverage_data"]) + coverage_data.write(self._historic_data[self.COVERAGE_DATA_KEY]) self._has_historic_data = True except json.JSONDecodeError: @@ -65,20 +100,31 @@ class PersistentStorage(ABC): except EnvironmentError as e: logger.error(f"There was a problem the coverage data file '{self._unpacked_coverage_data_file}': '{e}'.") - def _pack_historic_data(self, last_commit_hash: str): + def _pack_historic_data(self): """ Packs the current historic data into a JSON file for serializing. - @param last_commit_hash: The commit hash to associate the coverage data (and any other meta data) with. - @return: The packed historic data in JSON format. + @return: The packed historic data in JSON format. """ try: # Attempt to read the existing coverage data if self._unpacked_coverage_data_file.is_file(): + if not self._historic_data: + self._historic_data = {} + + # Last commit hash for this branch + self._historic_data[self.LAST_COMMIT_HASH_KEY] = self._this_commit_hash + + # Last commit hash for this commit + if not self.LAST_RUNS_KEY in self._historic_data: + self._historic_data[self.LAST_RUNS_KEY] = {} + self._historic_data[self.LAST_RUNS_KEY][self._this_commit_hash] = self._last_commit_hash + + # Coverage data for this branch with open(self._unpacked_coverage_data_file, "r") as coverage_data: - historic_data = {"last_commit_hash": last_commit_hash, "coverage_data": coverage_data.read()} - return json.dumps(historic_data) + self._historic_data[self.COVERAGE_DATA_KEY] = coverage_data.read() + return json.dumps(self._historic_data) else: logger.info(f"No coverage data exists at location '{self._unpacked_coverage_data_file}'.") except EnvironmentError as e: @@ -97,16 +143,14 @@ class PersistentStorage(ABC): """ pass - def update_and_store_historic_data(self, last_commit_hash: str): + def update_and_store_historic_data(self): """ Updates the historic data and stores it in the designated persistent storage location. - - @param last_commit_hash: The commit hash to associate the coverage data (and any other meta data) with. """ - historic_data_json = self._pack_historic_data(last_commit_hash) + historic_data_json = self._pack_historic_data() if historic_data_json: - logger.info(f"Attempting to store historic data with new last commit hash '{last_commit_hash}'...") + logger.info(f"Attempting to store historic data with new last commit hash '{self._this_commit_hash}'...") self._store_historic_data(historic_data_json) logger.info("The historic data was successfully stored.") @@ -119,4 +163,16 @@ class PersistentStorage(ABC): @property def last_commit_hash(self): - return self._last_commit_hash \ No newline at end of file + return self._last_commit_hash + + @property + def is_repeat_sequence(self): + return self._last_commit_hash == self._this_commit_hash + + @property + def this_commit_last_commit_hash(self): + return self._this_commit_hash_last_commit_hash + + @property + def can_rerun_sequence(self): + return self._has_previous_last_commit_hash \ No newline at end of file diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py index ba9b58fbf3..c72fafc580 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py @@ -15,19 +15,24 @@ logger = get_logger(__file__) # Implementation of local persistent storage class PersistentStorageLocal(PersistentStorage): - def __init__(self, config: str, suite: str): + + HISTORIC_KEY = "historic" + DATA_KEY = "data" + + def __init__(self, config: str, suite: str, commit: str): """ Initializes the persistent storage with any local historic data available. @param config: The runtime config file to obtain the data file paths from. @param suite: The test suite for which the historic data will be obtained for. + @param commit: The commit hash for this build. """ - super().__init__(config, suite) + super().__init__(config, suite, commit) try: # Attempt to obtain the local persistent data location specified in the runtime config file - self._historic_workspace = pathlib.Path(config["workspace"]["historic"]["root"]) - historic_data_file = pathlib.Path(config["workspace"]["historic"]["relative_paths"]["data"]) + self._historic_workspace = pathlib.Path(config[self.WORKSPACE_KEY][self.HISTORIC_KEY][self.ROOT_KEY]) + historic_data_file = pathlib.Path(config[self.WORKSPACE_KEY][self.HISTORIC_KEY][self.RELATIVE_PATHS_KEY][self.DATA_KEY]) # Attempt to unpack the local historic data file self._historic_data_file = self._historic_workspace.joinpath(historic_data_file) diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py index 1a279855ea..074caf73a1 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py @@ -18,16 +18,23 @@ logger = get_logger(__file__) # Implementation of s3 bucket persistent storage class PersistentStorageS3(PersistentStorage): - def __init__(self, config: dict, suite: str, s3_bucket: str, root_dir: str, branch: str): + + META_KEY = "meta" + BUILD_CONFIG_KEY = "build_config" + + def __init__(self, config: dict, suite: str, commit: str, s3_bucket: str, root_dir: str, branch: str): """ Initializes the persistent storage with the specified s3 bucket. @param config: The runtime config file to obtain the data file paths from. @param suite: The test suite for which the historic data will be obtained for. + @param commit: The commit hash for this build. @param s3_bucket: The s3 bucket to use for storing nd retrieving historic data. + @param root_dir: The root directory to use for the historic data object. + @branch branch: The branch to retrieve the historic data for. """ - super().__init__(config, suite) + super().__init__(config, suite, commit) try: # We store the historic data as compressed JSON @@ -37,8 +44,8 @@ class PersistentStorageS3(PersistentStorage): historic_data_file = f"historic_data.{object_extension}" # The location of the data is in the form // so the build config of each branch gets its own historic data - self._dir = f'{root_dir}/{branch}/{config["meta"]["build_config"]}' - self._historic_data_key = f'{self._dir}/{historic_data_file}' + self._historic_data_dir = f'{root_dir}/{branch}/{config[self.META_KEY][self.BUILD_CONFIG_KEY]}' + self._historic_data_key = f'{self._historic_data_dir}/{historic_data_file}' logger.info(f"Attempting to retrieve historic data for branch '{branch}' at location '{self._historic_data_key}' on bucket '{s3_bucket}'...") self._s3 = boto3.resource("s3") @@ -49,7 +56,7 @@ class PersistentStorageS3(PersistentStorage): logger.info(f"Historic data found for branch '{branch}'.") # Archive the existing object with the name of the existing last commit hash - #archive_key = f"{self._dir}/archive/{self._last_commit_hash}.{object_extension}" + #archive_key = f"{self._historic_data_dir}/archive/{self._last_commit_hash}.{object_extension}" #logger.info(f"Archiving existing historic data to '{archive_key}' in bucket '{self._bucket.name}'...") #self._bucket.copy({"Bucket": self._bucket.name, "Key": self._historic_data_key}, archive_key) #logger.info(f"Archiving complete.") From a1d855a920f2f741a2aff48b4251b84628598e78 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 13 Aug 2021 10:03:09 +0100 Subject: [PATCH 051/101] Invert corner case flag for readability. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index 28de00d6ba..e8faef30e3 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -235,7 +235,7 @@ class TestImpact: # The above results in TIAF being stuck in a state of generating an empty change list (and thus doing no work until another # commit comes in) which is problematic if the commit needs to be re-run for whatever reason so in these conditions we revert # back to a regular test run until another commit comes in - cannot_rerun_with_instrumentation = False + can_rerun_with_instrumentation = True if persistent_storage.has_historic_data: logger.info("Historic data found.") @@ -249,7 +249,7 @@ class TestImpact: else: logger.info(f"This sequence is being re-run before any other changes have come in but there is no useful historic data. A regular sequence will be performed instead.") persistent_storage = None - cannot_rerun_with_instrumentation = True + can_rerun_with_instrumentation = False else: self._attempt_to_generate_change_list() else: @@ -277,7 +277,7 @@ class TestImpact: args.append(f"--changelist={self._change_list_path}") logger.info(f"Change list is set to '{self._change_list_path}'.") else: - if self._is_source_of_truth_branch and not cannot_rerun_with_instrumentation: + if self._is_source_of_truth_branch and can_rerun_with_instrumentation: # Use seed sequence (instrumented all tests) for coverage updating branches so we can generate the coverage bed for future sequences sequence_type = "seed" # We always continue after test failures when seeding to ensure we capture the coverage for all test targets From 99b369198bb9a8b1e62e870b075031033a69b63e Mon Sep 17 00:00:00 2001 From: Kevin Y <88146293+kev197@users.noreply.github.com> Date: Fri, 13 Aug 2021 08:59:38 -0400 Subject: [PATCH 052/101] Typo fix in duplicate project progress window (#2969) Signed-off-by: Kevin Yu --- Code/Tools/ProjectManager/Source/ProjectUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp index 52900f1b28..fb0ea23ece 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp @@ -189,7 +189,7 @@ namespace O3DE::ProjectManager const QString copiedFileSizeString = locale.formattedDataSize(outCopiedFileSize); const QString totalFileSizeString = locale.formattedDataSize(totalSizeToCopy); - progressDialog->setLabelText(QString("Coping file %1 of %2 (%3 of %4) ...").arg(QString::number(outNumCopiedFiles), + progressDialog->setLabelText(QString("Copying file %1 of %2 (%3 of %4) ...").arg(QString::number(outNumCopiedFiles), QString::number(filesToCopyCount), copiedFileSizeString, totalFileSizeString)); From a55cb3e35fa4ac69f6082a101ac7faab66c75a27 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 13 Aug 2021 09:09:55 -0700 Subject: [PATCH 053/101] Fixed white-bar at bottom of Project Manager screen (#3091) Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com> --- Code/Tools/ProjectManager/Source/Application.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/Application.cpp b/Code/Tools/ProjectManager/Source/Application.cpp index c977698152..9ca107dae5 100644 --- a/Code/Tools/ProjectManager/Source/Application.cpp +++ b/Code/Tools/ProjectManager/Source/Application.cpp @@ -168,9 +168,13 @@ namespace O3DE::ProjectManager // the decoration wrapper is intended to remember window positioning and sizing auto wrapper = new AzQtComponents::WindowDecorationWrapper(); wrapper->setGuest(m_mainWindow.data()); + + // show the main window here to apply the stylesheet before restoring geometry or we + // can end up with empty white space at the bottom of the window until the frame is resized again + m_mainWindow->show(); + wrapper->enableSaveRestoreGeometry("O3DE", "ProjectManager", "mainWindowGeometry"); wrapper->showFromSettings(); - m_mainWindow->show(); qApp->setQuitOnLastWindowClosed(true); From 716089e803645f5b08f2b847d5e8c83d75a831e2 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Fri, 13 Aug 2021 09:57:40 -0700 Subject: [PATCH 054/101] More fixes and some temp debugging logs Signed-off-by: kberg-amzn --- .../LocalPredictionPlayerInputComponent.cpp | 59 +++++++------------ .../Source/Components/NetBindComponent.cpp | 6 +- 2 files changed, 25 insertions(+), 40 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index ca970de37b..72f5aa8e1c 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -66,6 +66,11 @@ namespace Multiplayer } } + inline double ConvertTimeMsToSeconds(AZ::TimeMs value) + { + return static_cast(static_cast(value)) / 1000.0; + } + void LocalPredictionPlayerInputComponent::LocalPredictionPlayerInputComponent::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); @@ -151,7 +156,7 @@ namespace Multiplayer } const AZ::TimeMs currentTimeMs = AZ::GetElapsedTimeMs(); - const double clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; + const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs); m_lastInputReceivedTimeMs = currentTimeMs; // Keep track of last inputs received, also allows us to update frame ids @@ -176,8 +181,8 @@ namespace Multiplayer if (m_clientBankedTime < sv_MaxBankTimeWindowSec) { // Client blends from previous frame to target so here we subtract blend factor to get to that state - const float blendFactor = AZStd::min(AZStd::max(0.f, input.GetHostBlendFactor()), 1.f); - const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * (1.f - blendFactor)); + const float blendFactor = AZStd::min(AZStd::max(0.f, input.GetHostBlendFactor()), 1.0f); + const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * (1.0f - blendFactor)); m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary { ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); @@ -259,7 +264,7 @@ namespace Multiplayer return; } - const float clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; + const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs); // Copy array so we can modify input ids NetworkInputMigrationVector inputArrayCopy = inputArray; @@ -334,7 +339,7 @@ namespace Multiplayer // If this correction is for a move outside our input history window, just start replaying from the oldest move we have available const uint32_t startReplayIndex = (inputHistorySize > historicalDelta) ? (inputHistorySize - historicalDelta) : 0; - const float clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; + const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs); for (uint32_t replayIndex = startReplayIndex; replayIndex < inputHistorySize; ++replayIndex) { // Reprocess the input for this frame @@ -405,9 +410,9 @@ namespace Multiplayer void LocalPredictionPlayerInputComponentController::UpdateAutonomous(AZ::TimeMs deltaTimeMs) { - const double deltaTime = static_cast(deltaTimeMs) / 1000.0; - const double inputRate = static_cast(static_cast(cl_InputRateMs)) / 1000.0; - const double maxRewindHistory = static_cast(static_cast(cl_MaxRewindHistoryMs)) / 1000.0; + const double deltaTime = ConvertTimeMsToSeconds(deltaTimeMs); + const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs); + const double maxRewindHistory = ConvertTimeMsToSeconds(cl_MaxRewindHistoryMs); #ifndef AZ_RELEASE_BUILD m_moveAccumulator += deltaTime * cl_DebugHackTimeMultiplier; @@ -415,13 +420,13 @@ namespace Multiplayer m_moveAccumulator += deltaTime; #endif - const uint32_t maxClientInputs = inputRate > 0.0 ? static_cast(maxRewindHistory / inputRate) : 0; + const uint32_t maxClientInputs = clientInputRateSec > 0.0 ? static_cast(maxRewindHistory / clientInputRateSec) : 0; IMultiplayer* multiplayer = GetMultiplayer(); INetworkTime* networkTime = GetNetworkTime(); - while (m_moveAccumulator >= inputRate) + while (m_moveAccumulator >= clientInputRateSec) { - m_moveAccumulator -= inputRate; + m_moveAccumulator -= clientInputRateSec; ++m_clientInputId; NetworkInputArray inputArray(GetEntityHandle()); @@ -433,10 +438,10 @@ namespace Multiplayer input.SetHostBlendFactor(multiplayer->GetCurrentBlendFactor()); // Allow components to form the input for this frame - GetNetBindComponent()->CreateInput(input, inputRate); + GetNetBindComponent()->CreateInput(input, clientInputRateSec); // Process the input for this frame - GetNetBindComponent()->ProcessInput(input, inputRate); + GetNetBindComponent()->ProcessInput(input, clientInputRateSec); AZLOG(NET_Prediction, "Processed InputId=%d", aznumeric_cast(m_clientInputId)); @@ -444,28 +449,6 @@ namespace Multiplayer AzNetworking::HashSerializer hashSerializer; GetNetBindComponent()->SerializeEntityCorrection(hashSerializer); - // In debug, send the entire client output state to the server to make it easier to debug desync issues - AzNetworking::PacketEncodingBuffer processInputResult; -#ifndef AZ_RELEASE_BUILD - if (cl_EnableDesyncDebugging) - { - AzNetworking::NetworkInputSerializer processInputResultSerializer(processInputResult.GetBuffer(), processInputResult.GetCapacity()); - GetNetBindComponent()->SerializeEntityCorrection(processInputResultSerializer); - processInputResult.Resize(processInputResultSerializer.GetSize()); - } -#endif - - // In debug, send the entire client output state to the server to make it easier to debug desync issues - AzNetworking::PacketEncodingBuffer processInputResult; -#ifndef AZ_RELEASE_BUILD - if (cl_EnableDesyncDebugging) - { - AzNetworking::NetworkInputSerializer processInputResultSerializer(processInputResult.GetBuffer(), static_cast(processInputResult.GetCapacity())); - GetNetBindComponent()->SerializeEntityCorrection(processInputResultSerializer); - processInputResult.Resize(processInputResultSerializer.GetSize()); - } -#endif - // Save this input and discard move history outside our client rewind window m_inputHistory.PushBack(input); while (m_inputHistory.Size() > maxClientInputs) @@ -508,7 +491,7 @@ namespace Multiplayer void LocalPredictionPlayerInputComponentController::UpdateBankedTime(AZ::TimeMs deltaTimeMs) { const double deltaTime = static_cast(deltaTimeMs) / 1000.0; - const double inputRate = static_cast(static_cast(cl_InputRateMs)) / 1000.0; + const double clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; const double maxRewindHistory = static_cast(static_cast(cl_MaxRewindHistoryMs)) / 1000.0; // Update banked time accumulator @@ -522,8 +505,8 @@ namespace Multiplayer NetworkInput& input = m_lastInputReceived[0]; { - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, AzNetworking::InvalidConnectionId); - GetNetBindComponent()->ProcessInput(input, inputRate); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, GetNetBindComponent()->GetOwningConnectionId()); + GetNetBindComponent()->ProcessInput(input, clientInputRateSec); } AZLOG(NET_Prediction, "Forced InputId=%d", aznumeric_cast(input.GetClientInputId())); diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index 070655e768..ef1bf8c8e8 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -274,8 +274,8 @@ namespace Multiplayer void NetBindComponent::CreateInput(NetworkInput& networkInput, float deltaTime) { - // Only autonomous or authority runs this logic - AZ_Assert(m_netEntityRole == NetEntityRole::Autonomous || m_netEntityRole == NetEntityRole::Authority, "Incorrect network role for input creation"); + // Only autonomous runs this logic + AZ_Assert(IsNetEntityRoleAutonomous(), "Incorrect network role for input creation"); for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector) { multiplayerComponent->GetController()->CreateInput(networkInput, deltaTime); @@ -284,6 +284,8 @@ namespace Multiplayer void NetBindComponent::ProcessInput(NetworkInput& networkInput, float deltaTime) { + AZ_TracePrintf("gathers", "Processing input, inputId=%d", static_cast(networkInput.GetClientInputId())); + m_isProcessingInput = true; // Only autonomous and authority runs this logic AZ_Assert((NetworkRoleHasController(m_netEntityRole)), "Incorrect network role for input processing"); From 9571a15769fc88c2713ca5ea6b834523b525c08e Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Fri, 13 Aug 2021 11:36:58 -0700 Subject: [PATCH 055/101] Atom/mriegger/explicit set pcf address mode (#3061) * Explicit setting the addressing mode for the pcf shadowing * Explicitly setting addressing mode for sampler --- .../Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli index d1a916dfac..67ccedd720 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli @@ -30,6 +30,9 @@ partial ShaderResourceGroup SceneSrg // Hardware PCF comparison sampler that is used when sampling the shadow maps SamplerComparisonState m_hwPcfSampler { + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; MagFilter = Linear; MinFilter = Linear; MipFilter = Point; From cd5081a7c3006d72b88dc196ffac0b3a66049673 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Fri, 13 Aug 2021 13:31:46 -0700 Subject: [PATCH 056/101] Fix byte alignment issue for index/vertex buffers (#3110) * Fix byte alignment issue for index/vertex buffers * Remove default alignment value when getting dynamic buffer Signed-off-by: abrmich --- .../Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp | 4 ++-- .../Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h | 4 ++-- .../Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h | 2 +- .../Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h | 2 +- .../Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp index 3a7d50d2a9..10d1bdc2c6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp @@ -196,7 +196,7 @@ namespace AZ { const size_t sourceByteSize = source.size() * sizeof(AuxGeomIndex); - RHI::Ptr dynamicBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(static_cast(sourceByteSize)); + RHI::Ptr dynamicBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(static_cast(sourceByteSize), RHI::Alignment::InputAssembly); if (!dynamicBuffer) { AZ_WarningOnce("AuxGeom", false, "Failed to allocate dynamic buffer of size %d.", sourceByteSize); @@ -211,7 +211,7 @@ namespace AZ { const size_t sourceByteSize = source.size() * sizeof(AuxGeomDynamicVertex); - RHI::Ptr dynamicBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(static_cast(sourceByteSize)); + RHI::Ptr dynamicBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(static_cast(sourceByteSize), RHI::Alignment::InputAssembly); if (!dynamicBuffer) { AZ_WarningOnce("AuxGeom", false, "Failed to allocate dynamic buffer of size %d.", sourceByteSize); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h index 0c13efbd4b..c50ba2dc9b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h @@ -25,8 +25,8 @@ namespace AZ //! DynamicBuffers are allocated by DynamicBufferAllocator. Check the description of DynamicBufferAllocator class for detail. //! The typical usage: //! // For every frame - //! auto buffer = DynamicDrawInterface::Get()->GetDynamicBuffer(size); - //! if (buffer) // the buffer could be empty if the allocation failed.e + //! auto buffer = DynamicDrawInterface::Get()->GetDynamicBuffer(size, RHI::Alignment::InputAssembly); + //! if (buffer) // the buffer could be empty if the allocation failed. //! { //! // write data to the buffer //! buffer->Write(data, size); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h index cc2125af95..23a93481fd 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h @@ -54,7 +54,7 @@ namespace AZ //! Get a DynamicBuffer from DynamicDrawSystem. //! The returned buffer will be invalidated every time the RPISystem's RenderTick is called - virtual RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment = 1) = 0; + virtual RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment) = 0; //! Draw a geometry to a scene with a given material virtual void DrawGeometry(Data::Instance material, const GeometryData& geometry, ScenePtr scene) = 0; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h index 4210bca1db..4a00566632 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h @@ -32,7 +32,7 @@ namespace AZ // DynamicDrawInterface overrides... RHI::Ptr CreateDynamicDrawContext() override; - RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment = 1) override; + RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment) override; void DrawGeometry(Data::Instance material, const GeometryData& geometry, ScenePtr scene) override; void AddDrawPacket(Scene* scene, AZStd::unique_ptr drawPacket) override; AZStd::vector GetDrawListsForPass(const RasterPass* pass) override; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp index 7ca2bdcee5..29f57d6e0f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp @@ -474,10 +474,10 @@ namespace AZ // Get dynamic buffers for vertex and index buffer. Skip draw if failed to allocate buffers uint32_t vertexDataSize = vertexCount * m_perVertexDataSize; RHI::Ptr vertexBuffer; - vertexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(vertexDataSize); + vertexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(vertexDataSize, RHI::Alignment::InputAssembly); uint32_t indexDataSize = indexCount * RHI::GetIndexFormatSize(indexFormat); - RHI::Ptr indexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(indexDataSize); + RHI::Ptr indexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(indexDataSize, RHI::Alignment::InputAssembly); if (indexBuffer == nullptr || vertexBuffer == nullptr) { @@ -572,7 +572,7 @@ namespace AZ // Get dynamic buffers for vertex and index buffer. Skip draw if failed to allocate buffers uint32_t vertexDataSize = vertexCount * m_perVertexDataSize; RHI::Ptr vertexBuffer; - vertexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(vertexDataSize); + vertexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(vertexDataSize, RHI::Alignment::InputAssembly); if (vertexBuffer == nullptr) { From 80aa4c42ce8082de578c8d3a78b1a95908aeea08 Mon Sep 17 00:00:00 2001 From: evanchia-ly-sdets <80914607+evanchia-ly-sdets@users.noreply.github.com> Date: Fri, 13 Aug 2021 13:41:56 -0700 Subject: [PATCH 057/101] moving smoke test to sandbox suite to investigate failures (#3109) Signed-off-by: evanchia --- .../Gem/PythonTests/smoke/CMakeLists.txt | 12 ++++++++++++ .../smoke/test_RemoteConsole_CPULoadLevel_Works.py | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt index 3fc4f3db0e..5374b0d318 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt @@ -73,5 +73,17 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AutomatedTesting.GameLauncher AutomatedTesting.Assets ) + ly_add_pytest( + NAME AutomatedTesting::LoadLevelCPU + TEST_SUITE sandbox + PATH ${CMAKE_CURRENT_LIST_DIR}/test_RemoteConsole_CPULoadLevel_Works.py + TIMEOUT 100 + RUNTIME_DEPENDENCIES + AZ::AssetProcessor + AZ::PythonBindingsExample + Legacy::Editor + AutomatedTesting.GameLauncher + AutomatedTesting.Assets + ) endif() diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py index 6522514f2f..701dcfab10 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py @@ -24,7 +24,7 @@ from ly_remote_console.remote_console_commands import ( @pytest.mark.parametrize("launcher_platform", ["windows"]) @pytest.mark.parametrize("project", ["AutomatedTesting"]) @pytest.mark.parametrize("level", ["Simple"]) -@pytest.mark.SUITE_smoke +@pytest.mark.SUITE_sandbox class TestRemoteConsoleLoadLevelWorks(object): @pytest.fixture def remote_console_instance(self, request): From 63a78b906ad04e3fc19d0dfb570f5e7173303e11 Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Fri, 13 Aug 2021 14:16:34 -0700 Subject: [PATCH 058/101] fixes light component GPU test AttributeError (I forgot to update atom_component_helper to atom_constants since constants were split from hydra functions into a new module) (#3115) Signed-off-by: jromnoa --- .../hydra_GPUTest_LightComponent.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py index 08f921e68b..8063445608 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py @@ -23,8 +23,7 @@ import azlmbr.legacy.general as general sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) import editor_python_test_tools.hydra_editor_utils as hydra -from atom_renderer.atom_utils import screenshot_utils -from atom_renderer.atom_utils import atom_component_helper +from atom_renderer.atom_utils import atom_component_helper, atom_constants, screenshot_utils from editor_python_test_tools.editor_test_helper import EditorTestHelper helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper") @@ -92,7 +91,7 @@ def area_light_test(): 'SetComponentProperty', light_component_id_pair, LIGHT_TYPE_PROPERTY, - atom_component_helper.LIGHT_TYPES['capsule'] + atom_constants.LIGHT_TYPES['capsule'] ) # Update color and take screenshot in game mode @@ -118,7 +117,7 @@ def area_light_test(): 'SetComponentProperty', light_component_id_pair, LIGHT_TYPE_PROPERTY, - atom_component_helper.LIGHT_TYPES['spot_disk'] + atom_constants.LIGHT_TYPES['spot_disk'] ) area_light_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 90.0, 0.0, 0.0) azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", area_light.id, area_light_rotation) @@ -131,7 +130,7 @@ def area_light_test(): 'SetComponentProperty', light_component_id_pair, LIGHT_TYPE_PROPERTY, - atom_component_helper.LIGHT_TYPES['sphere'] + atom_constants.LIGHT_TYPES['sphere'] ) general.idle_wait(1.0) screenshot_utils.take_screenshot_game_mode("AreaLight_5", area_light_entity_name) @@ -210,7 +209,7 @@ def spot_light_test(): 'SetComponentProperty', light_component_type, LIGHT_TYPE_PROPERTY, - atom_component_helper.LIGHT_TYPES['spot_disk'] + atom_constants.LIGHT_TYPES['spot_disk'] ) general.idle_wait(1.0) From 906042359243d215cd05303f732a3422a8fa20a1 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 13 Aug 2021 16:20:08 -0500 Subject: [PATCH 059/101] Settings registry notification deadlock fix (#3065) * Added a StealHandlers function to AZ Event The StealHandlers function is able to take all the handlers from an AZ Event parameter and register them with the current AZ Event This allows stealing handlers from expiring AZ Events, which is useful for a lock and swap algorithm for thread safety. 1. Lock persistent AZ::Event 2. Swap persistent AZ::Event with local AZ::Event 3. Unlock persistent AZ::Event - Other threads can now add to this AZ::Event 4. Invoke handlers from local AZ::Event 5. Relock persistent AZ::Event 5. Swap local AZ::Event with persistent AZ::Event 6. Local AZ::Event now contains handlers that were added when the lock was free 7. Persistent AZ::Event now steals from local AZ::Event 8. Unlock persistent AZ::Event Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Separated SettingRegistry update/query mutex from Notifier update mutex The Settings Registry update/query mutex is also better scoped to reduce the amount of lock time. The Notifier mutex being separate allows the Settings Registry to signal a notification event without being under any mutex, by locking and swapping the notifier event with a local instance Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Renamed StealHandlers function to ClaimHandlers Replaced decltype keywords in ClaimHandlers to auto Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/EBus/Event.h | 6 + Code/Framework/AzCore/AzCore/EBus/Event.inl | 26 ++++ .../AzCore/Settings/SettingsRegistryImpl.cpp | 111 +++++++++++++----- .../AzCore/Settings/SettingsRegistryImpl.h | 5 +- Code/Framework/AzCore/Tests/EventTests.cpp | 31 +++++ 5 files changed, 151 insertions(+), 28 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/EBus/Event.h b/Code/Framework/AzCore/AzCore/EBus/Event.h index b3c29b63a2..00310f4dbc 100644 --- a/Code/Framework/AzCore/AzCore/EBus/Event.h +++ b/Code/Framework/AzCore/AzCore/EBus/Event.h @@ -58,6 +58,12 @@ namespace AZ Event& operator=(Event&& rhs); + //! Take the handlers registered with the other event + //! and move them to this event. The other will event + //! will be cleared after call + //! @param other event to move handlers + Event& ClaimHandlers(Event&& other); + //! Returns true if at least one handler is connected to this event. bool HasHandlerConnected() const; diff --git a/Code/Framework/AzCore/AzCore/EBus/Event.inl b/Code/Framework/AzCore/AzCore/EBus/Event.inl index dfb1781991..ffa8c8b9c5 100644 --- a/Code/Framework/AzCore/AzCore/EBus/Event.inl +++ b/Code/Framework/AzCore/AzCore/EBus/Event.inl @@ -207,6 +207,32 @@ namespace AZ } + template + auto Event::ClaimHandlers(Event&& other) -> Event& + { + auto handlers = AZStd::move(other.m_handlers); + auto addList = AZStd::move(other.m_addList); + other.m_freeList = {}; + other.m_updating = false; + + AZStd::array handlerContainers{ &handlers, &addList }; + for (AZStd::vector* handlerList : handlerContainers) + { + for (Handler* handler : *handlerList) + { + if (handler != nullptr) + { + handler->m_index = 0; + handler->m_event = this; + Connect(*handler); + } + } + } + + return *this; + } + + template bool Event::HasHandlerConnected() const { diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp index 0882e1b7f2..3dc2d4145e 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp @@ -20,7 +20,7 @@ namespace AZ { template - bool SettingsRegistryImpl::SetValueInternal(AZStd::string_view path, T value, SettingsRegistryInterface::Type type) + bool SettingsRegistryImpl::SetValueInternal(AZStd::string_view path, T value) { if (path.empty()) { @@ -56,7 +56,6 @@ namespace AZ static_assert(!AZStd::is_same_v, "SettingsRegistryImpl::SetValueInternal called with unsupported type."); } - m_notifiers.Signal(path, type); return true; } return false; @@ -157,11 +156,11 @@ namespace AZ // Setting to empty string to prevent assert path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointer(path.data(), path.length()); if (pointer.IsValid()) { + AZStd::scoped_lock lock(m_settingMutex); const rapidjson::Value* value = pointer.Get(m_settings); if (value) { @@ -207,7 +206,7 @@ namespace AZ { NotifyEventHandler notifyHandler{ callback }; { - AZStd::scoped_lock lock(m_settingMutex); + AZStd::scoped_lock lock(m_notifierMutex); notifyHandler.Connect(m_notifiers); } return notifyHandler; @@ -217,7 +216,7 @@ namespace AZ { NotifyEventHandler notifyHandler{ AZStd::move(callback) }; { - AZStd::scoped_lock lock(m_settingMutex); + AZStd::scoped_lock lock(m_notifierMutex); notifyHandler.Connect(m_notifiers); } return notifyHandler; @@ -225,10 +224,35 @@ namespace AZ void SettingsRegistryImpl::ClearNotifiers() { - AZStd::scoped_lock lock(m_settingMutex); + AZStd::scoped_lock lock(m_notifierMutex); m_notifiers.DisconnectAllHandlers(); } + void SettingsRegistryImpl::SignalNotifier(AZStd::string_view jsonPath, Type type) + { + // Move the Notifier AZ::Event to a local AZ::Event in order to allow + // the notifier handlers to be signaled outside of the notifier mutex + // This allows other threads to register notifiers while this thread + // is invoking the handlers + decltype(m_notifiers) localNotifierEvent; + { + AZStd::scoped_lock lock(m_notifierMutex); + localNotifierEvent = AZStd::move(m_notifiers); + } + + localNotifierEvent.Signal(jsonPath, type); + + { + // Swap the local handlers with the current m_notifiers which + // will contain any handlers added during the signaling of the + // local event + AZStd::scoped_lock lock(m_notifierMutex); + AZStd::swap(m_notifiers, localNotifierEvent); + // Append any added handlers to the m_notifier structure + m_notifiers.ClaimHandlers(AZStd::move(localNotifierEvent)); + } + } + SettingsRegistryInterface::Type SettingsRegistryImpl::GetType(AZStd::string_view path) const { if (path.empty()) @@ -239,11 +263,11 @@ namespace AZ path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointer(path.data(), path.length()); if (pointer.IsValid()) { + AZStd::scoped_lock lock(m_settingMutex); const rapidjson::Value* value = pointer.Get(m_settings); if (value) { @@ -316,11 +340,11 @@ namespace AZ // Setting to empty string to prevent assert path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointer(path.data(), path.length()); if (pointer.IsValid()) { + AZStd::scoped_lock lock(m_settingMutex); const rapidjson::Value* value = pointer.Get(m_settings); if (value) { @@ -333,32 +357,52 @@ namespace AZ bool SettingsRegistryImpl::Set(AZStd::string_view path, bool value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::Boolean); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::Boolean); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, s64 value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::Integer); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::Integer); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, u64 value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::Integer); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::Integer); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, double value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::FloatingPoint); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::FloatingPoint); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, AZStd::string_view value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::String); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::String); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, const char* value) @@ -376,7 +420,6 @@ namespace AZ path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointer(path.data(), path.length()); if (pointer.IsValid()) @@ -386,9 +429,10 @@ namespace AZ value, nullptr, valueTypeID, m_serializationSettings); if (jsonResult.GetProcessing() != JsonSerializationResult::Processing::Halted) { + AZStd::scoped_lock lock(m_settingMutex); rapidjson::Value& setting = pointer.Create(m_settings, m_settings.GetAllocator()); setting = AZStd::move(store); - m_notifiers.Signal(path, Type::Object); + SignalNotifier(path, Type::Object); return true; } } @@ -404,13 +448,13 @@ namespace AZ // Setting to empty string to prevent assert path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointerPath(path.data(), path.size()); if (!pointerPath.IsValid()) { return false; } + AZStd::scoped_lock lock(m_settingMutex); return pointerPath.Erase(m_settings); } @@ -540,7 +584,7 @@ namespace AZ return false; } - m_notifiers.Signal("", Type::Object); + SignalNotifier("", Type::Object); return true; } @@ -562,8 +606,6 @@ namespace AZ scratchBuffer = &buffer; } - AZStd::scoped_lock lock(m_settingMutex); - bool result = false; if (path[path.length()] == 0) { @@ -577,6 +619,8 @@ namespace AZ R"(Path "%.*s" is too long. Either make sure that the provided path is terminated or use a shorter path.)", static_cast(path.length()), path.data()); Pointer pointer(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/-"); + + AZStd::scoped_lock lock(m_settingMutex); Value pathValue(path.data(), aznumeric_caster(path.length()), m_settings.GetAllocator()); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Unable to read registry file."), m_settings.GetAllocator()) @@ -622,6 +666,7 @@ namespace AZ { AZ_Error("Settings Registry", false, "Folder path for the Setting Registry is too long: %.*s", static_cast(path.size()), path.data()); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Folder path for the Setting Registry is too long."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(path.data(), aznumeric_caster(path.length()), m_settings.GetAllocator()), m_settings.GetAllocator()); @@ -659,6 +704,7 @@ namespace AZ if (fileList.size() >= MaxRegistryFolderEntries) { AZ_Error("Settings Registry", false, "Too many files in registry folder."); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator()) @@ -678,7 +724,6 @@ namespace AZ SystemFile::FindFiles(folderPath.c_str(), callback); - AZStd::scoped_lock lock(m_settingMutex); if (!platform.empty()) { // Move the folderPath prefix back to the supplied path before the wildcard @@ -696,6 +741,7 @@ namespace AZ if (fileList.size() >= MaxRegistryFolderEntries) { AZ_Error("Settings Registry", false, "Too many files in registry folder."); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator()) @@ -923,6 +969,8 @@ namespace AZ collisionFound = true; AZ_Error("Settings Registry", false, R"(Two registry files in "%.*s" point to the same specialization: "%s" and "%s")", AZ_STRING_ARG(folderPath), lhs.m_relativePath.c_str(), rhs.m_relativePath.c_str()); + + AZStd::scoped_lock lock(m_settingMutex); historyPointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), @@ -1077,6 +1125,7 @@ namespace AZ } } + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Unable to parse registry file due to invalid json."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator()) @@ -1102,6 +1151,7 @@ namespace AZ R"(To merge the supplied settings registry file, the settings within it must be placed within a JSON Object '{}')" R"( in order to allow moving of its fields using the root-key as an anchor.)", path); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Cannot merge registry file with a root which is not a JSON Object," " an empty root key and a merge approach of JsonMergePatch. Otherwise the Settings Registry would be overridden." @@ -1118,6 +1168,7 @@ namespace AZ JsonSerializationResult::ResultCode mergeResult(JsonSerializationResult::Tasks::Merge); if (rootKey.empty()) { + AZStd::scoped_lock lock(m_settingMutex); mergeResult = JsonSerialization::ApplyPatch(m_settings, m_settings.GetAllocator(), jsonPatch, mergeApproach, m_applyPatchSettings); } else @@ -1125,6 +1176,7 @@ namespace AZ Pointer root(rootKey.data(), rootKey.length()); if (root.IsValid()) { + AZStd::scoped_lock lock(m_settingMutex); Value& rootValue = root.Create(m_settings, m_settings.GetAllocator()); mergeResult = JsonSerialization::ApplyPatch(rootValue, m_settings.GetAllocator(), jsonPatch, mergeApproach, m_applyPatchSettings); } @@ -1132,6 +1184,7 @@ namespace AZ { AZ_Error("Settings Registry", false, R"(Failed to root path "%.*s" is invalid.)", aznumeric_cast(rootKey.length()), rootKey.data()); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Invalid root key."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator()); @@ -1141,15 +1194,19 @@ namespace AZ if (mergeResult.GetProcessing() != JsonSerializationResult::Processing::Completed) { AZ_Error("Settings Registry", false, R"(Failed to fully merge registry file "%s".)", path); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Failed to fully merge registry file."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator()); return false; } - pointer.Create(m_settings, m_settings.GetAllocator()).SetString(path, m_settings.GetAllocator()); + { + AZStd::scoped_lock lock(m_settingMutex); + pointer.Create(m_settings, m_settings.GetAllocator()).SetString(path, m_settings.GetAllocator()); + } - m_notifiers.Signal("", Type::Object); + SignalNotifier("", Type::Object); return true; } diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h index 41a628cf22..4126e19322 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h @@ -89,7 +89,7 @@ namespace AZ using RegistryFileList = AZStd::fixed_vector; template - bool SetValueInternal(AZStd::string_view path, T value, SettingsRegistryInterface::Type type); + bool SetValueInternal(AZStd::string_view path, T value); template bool GetValueInternal(T& result, AZStd::string_view path) const; VisitResponse Visit(Visitor& visitor, StackedString& path, AZStd::string_view valueName, @@ -100,8 +100,11 @@ namespace AZ const rapidjson::Pointer& historyPointer, AZStd::string_view folderPath); bool ExtractFileDescription(RegistryFile& output, const char* filename, const Specializations& specializations); bool MergeSettingsFileInternal(const char* path, Format format, AZStd::string_view rootKey, AZStd::vector& scratchBuffer); + + void SignalNotifier(AZStd::string_view jsonPath, Type type); mutable AZStd::recursive_mutex m_settingMutex; + mutable AZStd::recursive_mutex m_notifierMutex; NotifyEvent m_notifiers; rapidjson::Document m_settings; JsonSerializerSettings m_serializationSettings; diff --git a/Code/Framework/AzCore/Tests/EventTests.cpp b/Code/Framework/AzCore/Tests/EventTests.cpp index 358c1a62ae..aaa70344e7 100644 --- a/Code/Framework/AzCore/Tests/EventTests.cpp +++ b/Code/Framework/AzCore/Tests/EventTests.cpp @@ -240,6 +240,37 @@ namespace UnitTest static_assert(!AZStd::is_copy_assignable_v>, "AZ Events should not be copy assignable"); } + TEST_F(EventTests, TestClaimHandlers_TakesAllSourceHandlers) + { + AZ::Event<> testEvent1; + AZ::Event<> testEvent2; + + int32_t handlerInvokeCount{}; + auto handlerCallback = [&handlerInvokeCount]() + { + ++handlerInvokeCount; + }; + AZ::Event<>::Handler testHandler1(handlerCallback); + AZ::Event<>::Handler testHandler2(handlerCallback); + + testHandler1.Connect(testEvent1); + testHandler2.Connect(testEvent2); + + EXPECT_TRUE(testEvent1.HasHandlerConnected()); + EXPECT_TRUE(testEvent2.HasHandlerConnected()); + + testEvent1.ClaimHandlers(AZStd::move(testEvent2)); + EXPECT_TRUE(testEvent1.HasHandlerConnected()); + EXPECT_FALSE(testEvent2.HasHandlerConnected()); + + // testEvent1 should have both handlers + testEvent1.Signal(); + EXPECT_EQ(2, handlerInvokeCount); + // testEvent2 should have neither of the handlers + testEvent2.Signal(); + EXPECT_EQ(2, handlerInvokeCount); + } + TEST_F(EventTests, HandlerMoveAssignment_ProperlyDisconnectsFromOldEvent) { AZ::Event<> testEvent1; From 093a03cfbc98993d799883d9426ef3a7fda1a6a8 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 15:58:01 -0700 Subject: [PATCH 060/101] fix for non-unity mac build (#3118) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Util/StringHelpers.cpp | 2 -- Code/Editor/Util/StringHelpers.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Code/Editor/Util/StringHelpers.cpp b/Code/Editor/Util/StringHelpers.cpp index 6c819270bd..d0999d6ae2 100644 --- a/Code/Editor/Util/StringHelpers.cpp +++ b/Code/Editor/Util/StringHelpers.cpp @@ -10,8 +10,6 @@ #include "StringHelpers.h" #include "Util.h" -#include - int StringHelpers::CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1) { const size_t minLength = Util::getMin(str0.length(), str1.length()); diff --git a/Code/Editor/Util/StringHelpers.h b/Code/Editor/Util/StringHelpers.h index b5c84d7fe3..8a0883b24c 100644 --- a/Code/Editor/Util/StringHelpers.h +++ b/Code/Editor/Util/StringHelpers.h @@ -12,7 +12,7 @@ #pragma once #include -#include +#include namespace StringHelpers { From 693b205747809ab0b6804fdd6975654e37c17cc4 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Fri, 13 Aug 2021 16:56:27 -0700 Subject: [PATCH 061/101] Removing debug code, and fixing vector/array not respecting replication record dirty bits Signed-off-by: kberg-amzn --- .../Code/Source/AutoGen/AutoComponent_Source.jinja | 11 +++++------ .../Code/Source/Components/NetBindComponent.cpp | 2 -- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index d2be2f682a..56ab828ffe 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -643,16 +643,15 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re const uint32_t lastBit = static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'End') }}); {% endif %} -{% if Property.attrib['IsRewindable']|booleanTrue %} AzNetworking::FixedSizeBitsetView deltaRecord(replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}, firstBit, lastBit - firstBit + 1); - m_{{ LowerFirst(Property.attrib['Name']) }}.Serialize(serializer, deltaRecord); -{% else %} + if (deltaRecord.AnySet()) + { {% if Property.attrib['Container'] == 'Vector' %} - serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); + serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); {% elif Property.attrib['Container'] == 'Array' %} - serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); + serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); {% endif %} -{% endif %} + } } {% else %} Multiplayer::SerializeNetworkPropertyHelper diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index dfe2b6b561..d8e8a765ce 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -284,8 +284,6 @@ namespace Multiplayer void NetBindComponent::ProcessInput(NetworkInput& networkInput, float deltaTime) { - AZ_TracePrintf("gathers", "Processing input, inputId=%d", static_cast(networkInput.GetClientInputId())); - m_isProcessingInput = true; // Only autonomous and authority runs this logic AZ_Assert((NetworkRoleHasController(m_netEntityRole)), "Incorrect network role for input processing"); From 87ae7e865365707ba7d7fc453fdd0c43b34f489a Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Fri, 13 Aug 2021 18:22:40 -0700 Subject: [PATCH 062/101] Fix android gradle scripts to prevent cmake_dependencies.._gamelauncher from being wiped out of the APK Update gradle script generation to correct task dependencies (#3120) - copyNativeArtifacts must run after syncLYLayoutMode - syncLYLayoutMode must must after externalNativeBuild Signed-off-by: Steve Pham --- .../Tools/Platform/Android/android_support.py | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/cmake/Tools/Platform/Android/android_support.py b/cmake/Tools/Platform/Android/android_support.py index d820eb1d8c..77c8a37a35 100755 --- a/cmake/Tools/Platform/Android/android_support.py +++ b/cmake/Tools/Platform/Android/android_support.py @@ -372,9 +372,12 @@ CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_FORMAT_STR = """ }} compile{config}Sources.dependsOn copyNativeArtifacts{config} +""" + +CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_DEPENDENCY_FORMAT_STR = """ copyNativeArtifacts{config}.mustRunAfter {{ - tasks.findAll {{ task->task.name.contains('externalNativeBuild{config}') }} + tasks.findAll {{ task->task.name.contains('syncLYLayoutMode{config}') }} }} """ @@ -383,7 +386,13 @@ CUSTOM_APPLY_ASSET_LAYOUT_TASK_FORMAT_STR = """ workingDir '{working_dir}' commandLine '{python_full_path}', 'layout_tool.py', '--project-path', '{project_path}', '-p', 'Android', '-a', '{asset_type}', '-m', '{asset_mode}', '--create-layout-root', '-l', '{asset_layout_folder}' }} + compile{config}Sources.dependsOn syncLYLayoutMode{config} + + syncLYLayoutMode{config}.mustRunAfter {{ + tasks.findAll {{ task->task.name.contains('externalNativeBuild{config}') }} + }} + """ @@ -832,25 +841,28 @@ class AndroidProjectGenerator(object): asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), file_includes='Test.Assets/**/*.*') else: - # Copy over settings registry files from the Registry folder with build output directory gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] = \ + CUSTOM_APPLY_ASSET_LAYOUT_TASK_FORMAT_STR.format(working_dir=common.normalize_path_for_settings(self.engine_root / 'cmake/Tools'), + python_full_path=common.normalize_path_for_settings(self.engine_root / 'python' / PYTHON_SCRIPT), + asset_type=self.asset_type, + project_path=self.project_path.as_posix(), + asset_mode=self.asset_mode if native_config != 'Release' else 'PAK', + asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), + config=native_config) + # Copy over settings registry files from the Registry folder with build output directory + gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] += \ CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_FORMAT_STR.format(config=native_config, config_lower=native_config_lower, asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), file_includes='**/Registry/*.setreg') - - if self.include_assets_in_apk: - if not self.is_test_project: + if self.include_assets_in_apk: + # This is a dependency of the layout sync only if we are including assets in the APK gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] += \ - CUSTOM_APPLY_ASSET_LAYOUT_TASK_FORMAT_STR.format(working_dir=common.normalize_path_for_settings(self.engine_root / 'cmake/Tools'), - python_full_path=common.normalize_path_for_settings(self.engine_root / 'python' / PYTHON_SCRIPT), - asset_type=self.asset_type, - project_path=self.project_path.as_posix(), - asset_mode=self.asset_mode if native_config != 'Release' else 'PAK', - asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), - config=native_config) - else: - gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] = '' + CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_DEPENDENCY_FORMAT_STR.format(config=native_config) + + + + if self.signing_config: gradle_build_env[f'SIGNING_{native_config_upper}_CONFIG'] = f'signingConfig signingConfigs.{native_config_lower}' if self.signing_config else '' else: From 2fa9a831b3d09240d786d0636a173f9c9d169fd7 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 13 Aug 2021 20:26:49 -0500 Subject: [PATCH 063/101] AtomTools: prepend asterisk to denote modified document tabs Appending is standard and preferred but the tabs elide from the end (instead of middle) and cut it off Signed-off-by: Guthrie Adams --- .../Code/Source/Window/AtomToolsMainWindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index 55bec32dc7..e869e0eb98 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -199,8 +199,10 @@ namespace AtomToolsFramework { if (documentId == GetDocumentIdFromTab(tabIndex)) { - // We use an asterisk appended to the file name to denote modified document - const AZStd::string modifiedLabel = isModified ? label + " *" : label; + // We use an asterisk prepended to the file name to denote modified document + // Appending is standard and preferred but the tabs elide from the + // end (instead of middle) and cut it off + const AZStd::string modifiedLabel = isModified ? "* " + label : label; m_tabWidget->setTabText(tabIndex, modifiedLabel.c_str()); m_tabWidget->setTabToolTip(tabIndex, toolTip.c_str()); m_tabWidget->repaint(); From 83f6cb813ae42e0e8420a48f791d5c52f3f3178c Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Fri, 13 Aug 2021 18:38:48 -0700 Subject: [PATCH 064/101] Fix Non-Unity compile error with Atom Sample Viewer and the Atom Gem (#3119) Signed-off-by: spham-amzn --- Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h index 7c77838330..454a6d4086 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include From e633b5bdc70ca5b4ea3bb8cc7cd55e7e0acd3e8d Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 13 Aug 2021 19:43:38 -0700 Subject: [PATCH 065/101] Addressing Ronald's feedback Signed-off-by: mnaumov --- .../Prefab/Instance/InstanceSerializer.cpp | 3 +++ .../AzToolsFramework/Prefab/PrefabDomUtils.cpp | 6 ++++++ .../AzToolsFramework/Prefab/PrefabDomUtils.h | 12 +++++++++++- .../AzToolsFramework/Prefab/PrefabLoader.cpp | 2 +- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp index 89e0136b12..af42919637 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace AzToolsFramework { @@ -81,6 +82,8 @@ namespace AzToolsFramework result.Combine(resultInstances); } + PrefabDomUtils::LinkIdMetadata** linkIdMetadata = context.GetMetadata().Find(); + if (linkIdMetadata && *linkIdMetadata) { AZ::ScopedContextPath subPathSource(context, "m_linkId"); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index 86983d7912..c58cb21295 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -64,6 +64,12 @@ namespace AzToolsFramework settings.m_keepDefaults = true; } + if ((flags & StoreInstanceFlags::StoreLinkIds) != StoreInstanceFlags::None) + { + LinkIdMetadata linkIdMetadata; + settings.m_metadata.Add(&linkIdMetadata); + } + AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h index e773b581dd..fe38eb9e0f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h @@ -45,7 +45,11 @@ namespace AzToolsFramework //! By default an instance will be stored with default values. In cases where we want to store less json without defaults //! such as saving to disk, this flag will control that behavior. - StripDefaultValues = 1 << 0 + StripDefaultValues = 1 << 0, + + //! We do not save linkIds to file. However when loading a level we want to temporarily save + //! linkIds to instance dom so any nested prefabs will have linkIds correctly set. + StoreLinkIds = 1 << 1 }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreInstanceFlags); @@ -138,6 +142,12 @@ namespace AzToolsFramework [[maybe_unused]] const AZStd::string_view printMessage, [[maybe_unused]] const AzToolsFramework::Prefab::PrefabDomValue& prefabDomValue); + //! An empty struct for passing to JsonSerializerSettings.m_metadata that is consumed by InstanceSerializer::Store. + //! If present in metadata, linkIds will be stored to instance dom. + struct LinkIdMetadata + { + AZ_RTTI(LinkIdMetadata, "{8FF7D299-14E3-41D4-90C5-393A240FAE7C}"); + }; } // namespace PrefabDomUtils } // namespace Prefab } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index ea54c9d10c..2b16134744 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -300,7 +300,7 @@ namespace AzToolsFramework } PrefabDom storedPrefabDom(&loadedTemplateDom->get().GetAllocator()); - if (!PrefabDomUtils::StoreInstanceInPrefabDom(loadedPrefabInstance, storedPrefabDom)) + if (!PrefabDomUtils::StoreInstanceInPrefabDom(loadedPrefabInstance, storedPrefabDom, PrefabDomUtils::StoreInstanceFlags::StoreLinkIds)) { return false; } From 9aa391bf7413d15f3814cb6115eac95163733fa1 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 13 Aug 2021 16:54:57 -0700 Subject: [PATCH 066/101] Fixing Level Save As Signed-off-by: mnaumov --- .../PrefabEditorEntityOwnershipService.cpp | 36 ++----------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index b5cf5fb878..7df1e1b5c1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -219,42 +219,10 @@ namespace AzToolsFramework bool PrefabEditorEntityOwnershipService::SaveToStream(AZ::IO::GenericStream& stream, AZStd::string_view filename) { AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename); - AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath); m_rootInstance->SetTemplateSourcePath(relativePath); - - if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) - { - m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent()); - HandleEntitiesAdded({ m_rootInstance->m_containerEntity.get() }); - - AzToolsFramework::Prefab::PrefabDom dom; - bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom); - if (!success) - { - AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename)); - return false; - } - templateId = m_prefabSystemComponent->AddTemplate(relativePath, AZStd::move(dom)); - - if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) - { - AZ_Error("Prefab", false, "Couldn't add new template id '%i' when saving file '%.*s'", templateId, AZ_STRING_ARG(filename)); - return false; - } - } - - Prefab::TemplateId prevTemplateId = m_rootInstance->GetTemplateId(); - m_rootInstance->SetTemplateId(templateId); - - if (prevTemplateId != Prefab::InvalidTemplateId && templateId != prevTemplateId) - { - // Make sure we only have one level template loaded at a time - m_prefabSystemComponent->RemoveTemplate(prevTemplateId); - } - + AZStd::string out; - if (!m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out)) { return false; @@ -266,7 +234,7 @@ namespace AzToolsFramework { return false; } - m_prefabSystemComponent->SetTemplateDirtyFlag(templateId, false); + m_prefabSystemComponent->SetTemplateDirtyFlag(m_rootInstance->GetTemplateId(), false); return true; } From fe3b30e42ca96e97c4609de60daacde6d3f4fe60 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 14 Aug 2021 14:07:36 -0500 Subject: [PATCH 067/101] AtomTools: Fix python terminal help crash ATOM-16242 Checking EditorWindowRequests::GetAppMainWindow before searching for main window Signed-off-by: Guthrie Adams --- .../PythonTerminal/ScriptHelpDialog.cpp | 41 ++++++++++++++++++- .../PythonTerminal/ScriptHelpDialog.h | 34 +-------------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp index ea13d368cd..ba85911060 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp @@ -6,7 +6,6 @@ * */ - // Description : For listing available script commands with their descriptions #include "ScriptHelpDialog.h" @@ -23,6 +22,7 @@ // AzToolsFramework #include // for EditorPythonConsoleInterface +#include AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include @@ -313,6 +313,45 @@ namespace AzToolsFramework connect(ui->tableView, &ScriptTableView::doubleClicked, this, &CScriptHelpDialog::OnDoubleClick); } + CScriptHelpDialog* CScriptHelpDialog::GetInstance() + { + static CScriptHelpDialog* pInstance = nullptr; + if (!pInstance) + { + QMainWindow* mainWindow = GetMainWindowOfCurrentApplication(); + if (!mainWindow) + { + AZ_Assert(false, "Failed to find MainWindow."); + return nullptr; + } + + QWidget* parentWidget = mainWindow->window() + ? mainWindow->window() + : mainWindow; // MainWindow might have a WindowDecorationWrapper parent. Makes a difference on macOS. + pInstance = new CScriptHelpDialog(parentWidget); + } + return pInstance; + } + + QMainWindow* CScriptHelpDialog::GetMainWindowOfCurrentApplication() + { + QWidget* widget = nullptr; + EditorWindowRequestBus::BroadcastResult(widget, &EditorWindowRequests::GetAppMainWindow); + if (QMainWindow* mainWindow = qobject_cast(widget)) + { + return mainWindow; + } + + for (QWidget* widget : qApp->topLevelWidgets()) + { + if (QMainWindow* mainWindow = qobject_cast(widget)) + { + return mainWindow; + } + } + return nullptr; + } + void CScriptHelpDialog::OnDoubleClick(const QModelIndex& index) { if (!index.isValid()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.h b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.h index e34d652e1b..3cefa919c9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.h @@ -132,43 +132,13 @@ namespace AzToolsFramework { Q_OBJECT public: - static CScriptHelpDialog* GetInstance() - { - static CScriptHelpDialog* pInstance = nullptr; - if (!pInstance) - { - QMainWindow* mainWindow = GetMainWindowOfCurrentApplication(); - if (!mainWindow) - { - AZ_Assert(false, "Failed to find MainWindow."); - return nullptr; - } - - QWidget* parentWidget = mainWindow->window() ? mainWindow->window() : mainWindow; // MainWindow might have a WindowDecorationWrapper parent. Makes a difference on macOS. - pInstance = new CScriptHelpDialog(parentWidget); - } - return pInstance; - } - + static CScriptHelpDialog* GetInstance(); private Q_SLOTS: void OnDoubleClick(const QModelIndex&); private: - static QMainWindow* GetMainWindowOfCurrentApplication() - { - QMainWindow* mainWindow = nullptr; - for (QWidget* w : qApp->topLevelWidgets()) - { - mainWindow = qobject_cast(w); - if (mainWindow) - { - return mainWindow; - } - } - return nullptr; - } - explicit CScriptHelpDialog(QWidget* parent = nullptr); + static QMainWindow* GetMainWindowOfCurrentApplication(); QScopedPointer ui; }; } // namespace AzToolsFramework From d6c5f1444ba8595df24ce84776a8fec881377e72 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 14 Aug 2021 14:30:54 -0500 Subject: [PATCH 068/101] fixing hidden variable warning Signed-off-by: Guthrie Adams --- .../PythonTerminal/ScriptHelpDialog.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp index ba85911060..e9f6cd9e53 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp @@ -335,16 +335,16 @@ namespace AzToolsFramework QMainWindow* CScriptHelpDialog::GetMainWindowOfCurrentApplication() { - QWidget* widget = nullptr; - EditorWindowRequestBus::BroadcastResult(widget, &EditorWindowRequests::GetAppMainWindow); - if (QMainWindow* mainWindow = qobject_cast(widget)) + QWidget* mainWindowWidget = nullptr; + EditorWindowRequestBus::BroadcastResult(mainWindowWidget, &EditorWindowRequests::GetAppMainWindow); + if (QMainWindow* mainWindow = qobject_cast(mainWindowWidget)) { return mainWindow; } - for (QWidget* widget : qApp->topLevelWidgets()) + for (QWidget* topLevelWidget : qApp->topLevelWidgets()) { - if (QMainWindow* mainWindow = qobject_cast(widget)) + if (QMainWindow* mainWindow = qobject_cast(topLevelWidget)) { return mainWindow; } From 885357a6b54637e407e156313e9b3fb1db592921 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 14 Aug 2021 16:58:31 -0500 Subject: [PATCH 069/101] AtomTools: restoring log message filter to ignore source control spam Added message filter support to TraceLogger Signed-off-by: Guthrie Adams --- .../AzToolsFramework/Logger/TraceLogger.cpp | 36 +++++++++++++++---- .../AzToolsFramework/Logger/TraceLogger.h | 12 +++++-- .../Application/AtomToolsApplication.cpp | 11 +++--- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp index 5f1546bf83..547d328c45 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp @@ -5,11 +5,9 @@ * */ -#include - #include #include - +#include namespace AzToolsFramework { @@ -25,6 +23,22 @@ namespace AzToolsFramework bool TraceLogger::OnOutput(const char* window, const char* message) { + for (const auto& filter : m_windowFilters) + { + if (AZ::StringFunc::Contains(window, filter)) + { + return true; + } + } + + for (const auto& filter : m_messageFilters) + { + if (AZ::StringFunc::Contains(message, filter)) + { + return true; + } + } + if (m_logFile) { m_logFile->AppendLog(AzFramework::LogFile::SEV_NORMAL, window, message); @@ -36,10 +50,10 @@ namespace AzToolsFramework return false; } - void TraceLogger::WriteStartupLog(const AZStd::string& logFileName) - { + void TraceLogger::PrepareLogFile(const AZStd::string& logFileName) + { using namespace AzFramework; - + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); AZ_Assert(fileIO != nullptr, "FileIO should be running at this point"); @@ -71,4 +85,14 @@ namespace AzToolsFramework m_logFile->FlushLog(); } } + + void TraceLogger::AddWindowFilter(const AZStd::string& filter) + { + m_windowFilters.insert(filter); + } + + void TraceLogger::AddMessageFilter(const AZStd::string& filter) + { + m_messageFilters.insert(filter); + } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h index a10f4fc2df..ac1455452a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h @@ -22,8 +22,14 @@ namespace AzToolsFramework TraceLogger(); ~TraceLogger(); - //! Intalize logging for O3DEToolsApplications - void WriteStartupLog(const AZStd::string& logFileName); + //! Open log file and dump log sink into it + void PrepareLogFile(const AZStd::string& logFileName); + + //! Ignore messages sent to windowd with names matching filter + void AddWindowFilter(const AZStd::string& filter); + + //! Ignore messages with text matching filter + void AddMessageFilter(const AZStd::string& filter); protected: ////////////////////////////////////////////////////////////////////////// @@ -38,6 +44,8 @@ namespace AzToolsFramework AZStd::string message; }; AZStd::vector m_startupLogSink; + AZStd::unordered_set m_windowFilters; + AZStd::unordered_set m_messageFilters; AZStd::unique_ptr m_logFile; }; } // namespace AzToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index aedad7706b..efd3fec0e8 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -7,15 +7,15 @@ #include #include - -#include #include +#include #include #include #include -#include #include +#include + #include #include #include @@ -66,6 +66,9 @@ namespace AtomToolsFramework this->PumpSystemEventLoopUntilEmpty(); this->Tick(); }); + + // Suppress spam from the Source Control system + m_traceLogger.AddWindowFilter(AzToolsFramework::SCC_WINDOW); } AtomToolsApplication ::~AtomToolsApplication() @@ -396,7 +399,7 @@ namespace AtomToolsFramework AZStd::string fileName = GetBuildTargetName() + ".log"; - m_traceLogger.WriteStartupLog(fileName.c_str()); + m_traceLogger.PrepareLogFile(fileName.c_str()); if (!LaunchDiscoveryService()) { From 181698b950e63236d77c525964d9af5bbe617932 Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Mon, 16 Aug 2021 10:54:15 +0100 Subject: [PATCH 070/101] LY-91616 Dyn Veg: Push (up) and Pop (down) Items in Descriptor List (#3013) * LY-91616 Dyn Veg: Push (up) and Pop (down) Items in Descriptor List Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Changes as per reviews. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Additional review changes. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * review change Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- .../Components/FancyDocking.cpp | 5 +- .../PropertyEditor/EntityPropertyEditor.cpp | 1117 ++++++++++++++--- .../PropertyEditor/EntityPropertyEditor.hxx | 70 +- .../UI/PropertyEditor/PropertyRowWidget.cpp | 183 ++- .../UI/PropertyEditor/PropertyRowWidget.hxx | 21 + .../ReflectedPropertyEditor.cpp | 224 +++- .../ReflectedPropertyEditor.hxx | 10 + 7 files changed, 1441 insertions(+), 189 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp index c5aa1a3f88..4ced4ea635 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp @@ -1882,7 +1882,10 @@ namespace AzQtComponents return; } - QApplication::setOverrideCursor(m_dragCursor); + if (!QApplication::overrideCursor()) + { + QApplication::setOverrideCursor(m_dragCursor); + } QPoint relativePressPos = pressPos; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index f166e85ff9..2c46bb2d26 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -16,6 +16,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include #include #include #include @@ -106,7 +107,11 @@ void initEntityPropertyEditorResources() namespace AzToolsFramework { - static const char* kComponentEditorIndexMimeType = "editor/componentEditorIndices"; + constexpr const char* kComponentEditorIndexMimeType = "editor/componentEditorIndices"; + constexpr const char* kComponentEditorRowWidgetType = "editor/componentEditorRowWidget"; + + constexpr const char* kPropertyEditorMenuActionMoveUp("editor/propertyEditorMoveUp"); + constexpr const char* kPropertyEditorMenuActionMoveDown("editor/propertyEditorMoveDown"); //since component editors are spaced apart to make room for drop indicator, //giving drop logic simple buffer so drops between editors don't go to the bottom @@ -149,6 +154,7 @@ namespace AzToolsFramework : QWidget(parent) , m_editor(editor) , m_dropIndicatorOffset(8) + , m_dropIndicatorRowWidgetOffset(2) { setPalette(Qt::transparent); setWindowFlags(Qt::FramelessWindowHint); @@ -158,22 +164,137 @@ namespace AzToolsFramework } protected: - void paintEvent(QPaintEvent* event) override + static constexpr int TopMargin = 1; + static constexpr int RightMargin = 2; + static constexpr int BottomMargin = 5; + static constexpr int LeftMargin = 2; + static constexpr int RowHighlightIndent = 2; + + void paintDraggingRowWidget(QPainter& painter) { - const int TopMargin = 1; - const int RightMargin = 2; - const int BottomMargin = 5; - const int LeftMargin = 2; + ComponentEditor* rowWidgetEditor = m_editor->GetEditorForCurrentReorderRowWidget(); + PropertyRowWidget* dragRowWidget = m_editor->GetReorderRowWidget(); + PropertyRowWidget* dropTarget = m_editor->GetReorderDropTarget(); + EntityPropertyEditor::DropArea dropArea = m_editor->GetReorderDropArea(); - QWidget::paintEvent(event); + // The user is dragging a row widget. + for (auto componentEditor : m_editor->m_componentEditors) + { + if (!componentEditor->isVisible()) + { + continue; + } - QPainter painter(this); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + if (componentEditor != rowWidgetEditor) + { + continue; + } - QRect currRect; + for (auto& [dataNode, rowWidget] : componentEditor->GetPropertyEditor()->GetWidgets()) + { + if (!rowWidget->isVisible()) + { + continue; + } + + QRect globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(rowWidget); + + QRect currRect = QRect( + QPoint(mapFromGlobal(globalRect.topLeft()) + QPoint(LeftMargin, TopMargin)), + QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, BottomMargin))); + + currRect.setLeft(LeftMargin + RowHighlightIndent); + currRect.setWidth(rowWidget->GetContainingEditorFrameWidth() - (RightMargin + LeftMargin)); + + if (rowWidget == dragRowWidget) + { + QStyleOption opt; + opt.init(this); + opt.rect = currRect; + qobject_cast (style())->drawDragIndicator(&opt, &painter, this); + } + + if (rowWidget == dropTarget) + { + QRect dropRect = currRect; + if (dropArea == EntityPropertyEditor::DropArea::Above) + { + dropRect.setTop(currRect.top() - m_dropIndicatorRowWidgetOffset); + } + else + { + dropRect.setTop(currRect.bottom()); + } + + dropRect.setHeight(0); + + QStyleOption opt; + opt.init(this); + opt.rect = dropRect; + style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, &painter, this); + } + } + } + }; + + void paintMenuHighlight(QPainter& painter, float alpha) + { + // If a RowWidget can be moved up or down, highlight it. + PropertyRowWidget* dragRowWidget = m_editor->GetReorderRowWidget(); + if (!dragRowWidget) + { + return; + } + + PropertyRowWidget* dropTarget = m_editor->GetReorderDropTarget(); + EntityPropertyEditor::DropArea dropArea = m_editor->GetReorderDropArea(); + QPixmap dragImage = m_editor->GetReorderRowWidgetImage(); + + // User has the context menu open with a movable row selected. + QRect globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(dragRowWidget); + + int top = mapFromGlobal(globalRect.topLeft()).y(); + int imageHeight = dragImage.height() / dragImage.devicePixelRatioF(); + int imageWidth = dragImage.width() / dragImage.devicePixelRatioF(); + QRect currRect = QRect(QPoint(LeftMargin + 1, top), QPoint(LeftMargin + 1 + imageWidth, top + imageHeight)); + + painter.setOpacity(alpha); + painter.drawPixmap(currRect, dragImage); + + if (dropTarget) + { + // A move row menu command is highlighted. Draw an indicator to show where the current row will move to. + globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(dropTarget); + QRect dropRect = QRect( + QPoint(mapFromGlobal(globalRect.topLeft()) + QPoint(LeftMargin, TopMargin)), + QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, TopMargin))); + + if (dropArea == EntityPropertyEditor::DropArea::Above) + { + dropRect.setTop(dropRect.top() - m_dropIndicatorRowWidgetOffset); + } + else + { + dropRect.setTop(dropRect.bottom()); + } + dropRect.setHeight(0); + + painter.setOpacity(alpha); + QStyleOption lineOpt; + lineOpt.init(this); + lineOpt.rect = dropRect; + style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &lineOpt, &painter, this); + painter.setOpacity(1.0f); + } + }; + + void paintDraggingComponent(QPainter& painter) + { bool drag = false; bool drop = false; + QRect currRect; + // Check for a component editor being dragged. for (auto componentEditor : m_editor->m_componentEditors) { if (!componentEditor->isVisible()) @@ -185,8 +306,7 @@ namespace AzToolsFramework currRect = QRect( QPoint(mapFromGlobal(globalRect.topLeft()) + QPoint(LeftMargin, TopMargin)), - QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, BottomMargin)) - ); + QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, BottomMargin))); currRect.setWidth(currRect.width() - 1); currRect.setHeight(currRect.height() - 1); @@ -226,6 +346,67 @@ namespace AzToolsFramework opt.rect = dropRect; style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, &painter, this); } + }; + + void paintMovedRow(QPainter& painter, float alpha) + { + // After a move has been carried out, briefly highlight the moved row. + PropertyRowWidget* rowWidget = m_editor->GetRowToHighlight(); + + if (!rowWidget) + { + return; + } + + QRect globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(rowWidget); + QRect currRect = QRect( + QPoint(mapFromGlobal(globalRect.topLeft()) + QPoint(LeftMargin, TopMargin)), + QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, BottomMargin))); + + currRect.setLeft(LeftMargin + 2); + currRect.setWidth(rowWidget->GetContainingEditorFrameWidth() - (RightMargin + LeftMargin)); + + painter.setOpacity(alpha); + + QPen pen; + QColor drawColor = Qt::white; + drawColor.setAlphaF(alpha); + pen.setColor(drawColor); + pen.setWidth(1); + painter.setPen(pen); + painter.drawRect(currRect); + } + + void paintEvent(QPaintEvent* event) override + { + QWidget::paintEvent(event); + + QPainter painter(this); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + + EntityPropertyEditor::ReorderState currentState = m_editor->GetReorderState(); + float indicatorAlpha = m_editor->GetMoveIndicatorAlpha(); + + switch (currentState) + { + case EntityPropertyEditor::ReorderState::DraggingRowWidget: + paintDraggingRowWidget(painter); + break; + case EntityPropertyEditor::ReorderState::UsingMenu: + paintMenuHighlight(painter, 1.0f); + break; + case EntityPropertyEditor::ReorderState::MenuOperationInProgress: + paintMenuHighlight(painter, indicatorAlpha); + break; + case EntityPropertyEditor::ReorderState::DraggingComponent: + paintDraggingComponent(painter); + break; + case EntityPropertyEditor::ReorderState::HighlightMovedRow: + paintMovedRow(painter, indicatorAlpha); + break; + default: + break; + } } bool event(QEvent* ev) override @@ -280,6 +461,7 @@ namespace AzToolsFramework private: EntityPropertyEditor* m_editor; int m_dropIndicatorOffset; + int m_dropIndicatorRowWidgetOffset; }; EntityPropertyEditor::SharedComponentInfo::SharedComponentInfo(AZ::Component* component, AZ::Component* sliceReferenceComponent) @@ -382,6 +564,9 @@ namespace AzToolsFramework m_emptyIcon = QIcon(); m_clearIcon = QIcon(":/AssetBrowser/Resources/close.png"); + m_dragIcon = QIcon(QStringLiteral(":/Cursors/Grabbing.svg")); + m_dragCursor = QCursor(m_dragIcon.pixmap(16), 10, 5); + m_serializeContext = nullptr; AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); AZ_Assert(m_serializeContext, "Failed to acquire application serialize context."); @@ -1867,6 +2052,12 @@ namespace AzToolsFramework return; } + // Don't show if a move operation is pending. + if (m_currentReorderState != ReorderState::Inactive) + { + return; + } + // Locate the owning component and class data corresponding to the clicked node. InstanceDataNode* componentNode = node; while (componentNode->GetParent()) @@ -1905,7 +2096,12 @@ namespace AzToolsFramework if (!menu.actions().empty()) { + m_currentReorderState = EntityPropertyEditor::ReorderState::UsingMenu; menu.exec(position); + if (m_currentReorderState != EntityPropertyEditor::ReorderState::MenuOperationInProgress) + { + m_currentReorderState = EntityPropertyEditor::ReorderState::Inactive; + } } } } @@ -1956,129 +2152,179 @@ namespace AzToolsFramework AZ::SliceComponent* rootSlice = nullptr; AzFramework::SliceEntityOwnershipServiceRequestBus::EventResult(rootSlice, contextId, &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::GetRootSlice); - if (!rootSlice) + if (rootSlice) { - return; - } - - AZ::SliceComponent::SliceInstanceAddress address; - AzFramework::SliceEntityRequestBus::EventResult(address, entity->GetId(), - &AzFramework::SliceEntityRequests::GetOwningSlice); - AZ::SliceComponent::SliceReference* sliceReference = address.GetReference(); - if (sliceReference) - { - // This entity is instanced from a slice, so show data push/pull options - AZ::SliceComponent::EntityAncestorList ancestors; - sliceReference->GetInstanceEntityAncestry(entity->GetId(), ancestors); - - AZ_Error("PropertyEditor", !ancestors.empty(), "Entity \"%s\" belongs to a slice, but its source entity could not be located.", entity->GetName().c_str()); - if (!ancestors.empty()) + AZ::SliceComponent::SliceInstanceAddress address; + AzFramework::SliceEntityRequestBus::EventResult(address, entity->GetId(), &AzFramework::SliceEntityRequests::GetOwningSlice); + AZ::SliceComponent::SliceReference* sliceReference = address.GetReference(); + if (sliceReference) { - menu.addSeparator(); + // This entity is instanced from a slice, so show data push/pull options + AZ::SliceComponent::EntityAncestorList ancestors; + sliceReference->GetInstanceEntityAncestry(entity->GetId(), ancestors); - // Populate slice push options. - // Address should start with the fully-addressable component Id to resolve within the target entity. - InstanceDataHierarchy::Address pushFieldAddress; - CalculateAndAdjustNodeAddress(*fieldNode, AddressRootType::RootAtEntity, pushFieldAddress); - if (!pushFieldAddress.empty()) + AZ_Error( + "PropertyEditor", !ancestors.empty(), "Entity \"%s\" belongs to a slice, but its source entity could not be located.", + entity->GetName().c_str()); + if (!ancestors.empty()) { - SliceUtilities::PopulateQuickPushMenu( - menu, - entity->GetId(), - pushFieldAddress, - SliceUtilities::QuickPushMenuOptions("Save field override", SliceUtilities::QuickPushMenuOverrideDisplayCount::ShowOverrideCountOnlyWhenMultiple)); + menu.addSeparator(); + + // Populate slice push options. + // Address should start with the fully-addressable component Id to resolve within the target entity. + InstanceDataHierarchy::Address pushFieldAddress; + CalculateAndAdjustNodeAddress(*fieldNode, AddressRootType::RootAtEntity, pushFieldAddress); + if (!pushFieldAddress.empty()) + { + SliceUtilities::PopulateQuickPushMenu( + menu, entity->GetId(), pushFieldAddress, + SliceUtilities::QuickPushMenuOptions( + "Save field override", + SliceUtilities::QuickPushMenuOverrideDisplayCount::ShowOverrideCountOnlyWhenMultiple)); + } } } - } - menu.addSeparator(); + menu.addSeparator(); - // by leaf node, we mean a visual leaf node in the property editor (ie, we do not have any visible children) - bool isLeafNode = !fieldNode->GetClassMetadata() || !fieldNode->GetClassMetadata()->m_container; + // by leaf node, we mean a visual leaf node in the property editor (ie, we do not have any visible children) + bool isLeafNode = !fieldNode->GetClassMetadata() || !fieldNode->GetClassMetadata()->m_container; - if (isLeafNode) - { - for (const InstanceDataNode& childNode : fieldNode->GetChildren()) + if (isLeafNode) { - if (HasAnyVisibleElements(childNode)) + for (const InstanceDataNode& childNode : fieldNode->GetChildren()) { - // If we have any visible children, we must not be a leaf node - isLeafNode = false; - break; + if (HasAnyVisibleElements(childNode)) + { + // If we have any visible children, we must not be a leaf node + isLeafNode = false; + break; + } } } - } #ifdef ENABLE_SLICE_EDITOR - // Show PreventOverride & HideProperty options - if (GetEntityDataPatchAddress(fieldNode, m_dataPatchAddressBuffer)) - { - AZ::DataPatch::Flags nodeFlags = rootSlice->GetEntityDataFlagsAtAddress(entity->GetId(), m_dataPatchAddressBuffer); + // Show PreventOverride & HideProperty options + if (GetEntityDataPatchAddress(fieldNode, m_dataPatchAddressBuffer)) + { + AZ::DataPatch::Flags nodeFlags = rootSlice->GetEntityDataFlagsAtAddress(entity->GetId(), m_dataPatchAddressBuffer); - if (nodeFlags & AZ::DataPatch::Flag::PreventOverrideSet) - { - QAction* PreventOverrideAction = menu.addAction(tr("Allow property override")); - PreventOverrideAction->setEnabled(isLeafNode); - connect(PreventOverrideAction, &QAction::triggered, this, [this, fieldNode] + if (nodeFlags & AZ::DataPatch::Flag::PreventOverrideSet) { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::PreventOverrideSet, false); - InvalidatePropertyDisplay(Refresh_AttributesAndValues); + QAction* PreventOverrideAction = menu.addAction(tr("Allow property override")); + PreventOverrideAction->setEnabled(isLeafNode); + connect( + PreventOverrideAction, &QAction::triggered, this, + [this, fieldNode] + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::PreventOverrideSet, false); + InvalidatePropertyDisplay(Refresh_AttributesAndValues); + }); } - ); - } - else - { - QAction* PreventOverrideAction = menu.addAction(tr("Prevent property override")); - PreventOverrideAction->setEnabled(isLeafNode); - connect(PreventOverrideAction, &QAction::triggered, this, [this, fieldNode] + else { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::PreventOverrideSet, true); - InvalidatePropertyDisplay(Refresh_AttributesAndValues); + QAction* PreventOverrideAction = menu.addAction(tr("Prevent property override")); + PreventOverrideAction->setEnabled(isLeafNode); + connect( + PreventOverrideAction, &QAction::triggered, this, + [this, fieldNode] + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::PreventOverrideSet, true); + InvalidatePropertyDisplay(Refresh_AttributesAndValues); + }); } - ); - } - if (nodeFlags & AZ::DataPatch::Flag::HidePropertySet) - { - QAction* HideProperyAction = menu.addAction(tr("Show property on instances")); - HideProperyAction->setEnabled(isLeafNode); - connect(HideProperyAction, &QAction::triggered, this, [this, fieldNode] + if (nodeFlags & AZ::DataPatch::Flag::HidePropertySet) { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::HidePropertySet, false); - InvalidatePropertyDisplay(Refresh_AttributesAndValues); + QAction* HideProperyAction = menu.addAction(tr("Show property on instances")); + HideProperyAction->setEnabled(isLeafNode); + connect( + HideProperyAction, &QAction::triggered, this, + [this, fieldNode] + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::HidePropertySet, false); + InvalidatePropertyDisplay(Refresh_AttributesAndValues); + }); } - ); - } - else - { - QAction* HideProperyAction = menu.addAction(tr("Hide property on instances")); - HideProperyAction->setEnabled(isLeafNode); - connect(HideProperyAction, &QAction::triggered, this, [this, fieldNode] + else { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::HidePropertySet, true); - InvalidatePropertyDisplay(Refresh_AttributesAndValues); + QAction* HideProperyAction = menu.addAction(tr("Hide property on instances")); + HideProperyAction->setEnabled(isLeafNode); + connect( + HideProperyAction, &QAction::triggered, this, + [this, fieldNode] + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::HidePropertySet, true); + InvalidatePropertyDisplay(Refresh_AttributesAndValues); + }); } - ); } - } #endif - if (sliceReference) - { - // This entity is referenced from a slice, so show property override options - bool hasChanges = fieldNode->HasChangesVersusComparison(false); - - if (!hasChanges && isLeafNode) + if (sliceReference) { - // Add an option to set the ForceOverride flag for this field - menu.setToolTipsVisible(true); - QAction* forceOverrideAction = menu.addAction(tr("Force property override")); - forceOverrideAction->setToolTip(tr("Prevents a property from inheriting from its source slice")); - connect(forceOverrideAction, &QAction::triggered, this, [this, fieldNode]() - { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::ForceOverrideSet, true); - } - ); + // This entity is referenced from a slice, so show property override options + bool hasChanges = fieldNode->HasChangesVersusComparison(false); + + if (!hasChanges && isLeafNode) + { + // Add an option to set the ForceOverride flag for this field + menu.setToolTipsVisible(true); + QAction* forceOverrideAction = menu.addAction(tr("Force property override")); + forceOverrideAction->setToolTip(tr("Prevents a property from inheriting from its source slice")); + connect( + forceOverrideAction, &QAction::triggered, this, + [this, fieldNode]() + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::ForceOverrideSet, true); + }); + } + } + } + + m_reorderRowWidget = nullptr; + // Add move up/down actions if appropriate + auto componentEditorIterator = m_componentToEditorMap.find(componentInstance); + AZ_Assert(componentEditorIterator != m_componentToEditorMap.end(), "Unable to find a component editor for the given component"); + if (componentEditorIterator != m_componentToEditorMap.end()) + { + m_reorderRowWidgetEditor = componentEditorIterator->second; + PropertyRowWidget* widget = componentEditorIterator->second->GetPropertyEditor()->GetWidgetFromNode(fieldNode); + if (widget->CanBeReordered()) + { + m_reorderRowWidget = widget; + SetRowWidgetHighlighted(widget); + + QAction* moveUpAction = menu.addAction(tr("Move %1 Up").arg(widget->GetNameLabel()->text())); + moveUpAction->setEnabled(false); + moveUpAction->setData(kPropertyEditorMenuActionMoveUp); + + if (widget->CanMoveUp()) + { + moveUpAction->setEnabled(true); + connect( + moveUpAction, &QAction::triggered, this, + [this, widget] + { + ContextMenuActionMoveItemUp(m_reorderRowWidgetEditor, widget); + }); + } + + QAction* moveDownAction = menu.addAction(tr("Move %1 Down").arg(widget->GetNameLabel()->text())); + moveDownAction->setEnabled(false); + moveDownAction->setData(kPropertyEditorMenuActionMoveDown); + if (widget->CanMoveDown()) + { + moveDownAction->setEnabled(true); + connect( + moveDownAction, &QAction::triggered, this, + [this, widget] + { + ContextMenuActionMoveItemDown(m_reorderRowWidgetEditor, widget); + }); + } + + menu.addSeparator(); } } } @@ -2380,6 +2626,98 @@ namespace AzToolsFramework } } + void EntityPropertyEditor::BeginMoveRowWidgetFade() + { + // Fade out the highlights and indicator bar for two seconds before moving. + m_moveFadeSecondsRemaining = MoveFadeSeconds; + m_currentReorderState = EntityPropertyEditor::ReorderState::MenuOperationInProgress; + AZ::TickBus::Handler::BusConnect(); + } + + void EntityPropertyEditor::HighlightMovedRowWidget() + { + if (m_currentReorderState != ReorderState::WaitForRedraw) + { + return; + } + UpdateOverlay(); + + m_currentReorderState = ReorderState::HighlightMovedRow; + m_moveFadeSecondsRemaining = MoveFadeSeconds; + + AZ::TickBus::Handler::BusConnect(); + m_overlay->setVisible(true); + } + + void EntityPropertyEditor::OnTick(float deltaTime, AZ::ScriptTimePoint /*time*/) + { + m_moveFadeSecondsRemaining -= deltaTime; + m_overlay->setVisible(true); + if (m_moveFadeSecondsRemaining <= 0.0f) + { + m_moveFadeSecondsRemaining = 0.0f; + + if (m_currentReorderState == ReorderState::MenuOperationInProgress) + { + m_reorderRowWidgetEditor->GetPropertyEditor()->MoveNodeToIndex(m_nodeToMove, m_indexMapOfMovedRow[0]); + + // Ensure the highlight gets drawn once the RPE is updated. + m_currentReorderState = ReorderState::WaitForRedraw; + AZ::TickBus::Handler::BusDisconnect(); + ScrollToNewComponent(); + } + else + { + m_currentReorderState = ReorderState::Inactive; + AZ::TickBus::Handler::BusDisconnect(); + m_overlay->setVisible(false); + } + } + + // Force a repaint to show the fade. + repaint(0, 0, -1, -1); + } + + void EntityPropertyEditor::GenerateRowWidgetIndexMapToChildIndex(PropertyRowWidget* parent, int destIndex) + { + m_indexMapOfMovedRow.clear(); + m_indexMapOfMovedRow.push_back(destIndex); + + while (parent) + { + int index = parent->GetIndexInParent(); + if (index < 0) + { + // Top level widget. + break; + } + m_indexMapOfMovedRow.push_back(parent->GetIndexInParent()); + parent = parent->GetParentRow(); + } + } + + void EntityPropertyEditor::ContextMenuActionMoveItemUp(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget) + { + // After the RPE is rebuilt, there'll be no way to work out which is the moved RowWidget. + // Generate a map of the child indices up to the root. + PropertyRowWidget* parent = rowWidget->GetParentRow(); + GenerateRowWidgetIndexMapToChildIndex(parent, rowWidget->GetIndexInParent() - 1); + + m_reorderRowWidgetEditor = componentEditor; + m_nodeToMove = rowWidget->GetNode(); + BeginMoveRowWidgetFade(); + } + + void EntityPropertyEditor::ContextMenuActionMoveItemDown(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget) + { + PropertyRowWidget* parent = rowWidget->GetParentRow(); + GenerateRowWidgetIndexMapToChildIndex(parent, rowWidget->GetIndexInParent() + 1); + + m_reorderRowWidgetEditor = componentEditor; + m_nodeToMove = rowWidget->GetNode(); + BeginMoveRowWidgetFade(); + } + void EntityPropertyEditor::CalculateAndAdjustNodeAddress(const InstanceDataNode& componentFieldNode, AddressRootType rootType, InstanceDataNode::Address& outAddress) const { outAddress = componentFieldNode.ComputeAddress(); @@ -2763,9 +3101,7 @@ namespace AzToolsFramework if (!menu.actions().empty()) { - m_isShowingContextMenu = true; menu.exec(position); - m_isShowingContextMenu = false; } } @@ -3463,6 +3799,76 @@ namespace AzToolsFramework return this == widget || isAncestorOf(widget); } + AZ::u32 EntityPropertyEditor::GetHeightOfRowAndVisibleChildren(const PropertyRowWidget* row) const + { + if (!row->isVisible()) + { + return 0; + } + + QRect rect = QRect(row->mapToGlobal(row->rect().topLeft()), row->mapToGlobal(row->rect().bottomRight())); + + AZ::u32 height = rect.height() + 1; + + for (AZ::u32 childIndex = 0; childIndex < row->GetChildRowCount(); childIndex++) + { + PropertyRowWidget* childRow = row->GetChildRowByIndex(childIndex); + if (childRow->isVisible()) + { + height += GetHeightOfRowAndVisibleChildren(childRow); + } + } + + return height; + } + + QRect EntityPropertyEditor::GetWidgetAndVisibleChildrenGlobalRect(const PropertyRowWidget* widget) const + { + QRect rect = QRect(widget->mapToGlobal(widget->rect().topLeft()), widget->mapToGlobal(widget->rect().bottomRight())); + rect.setHeight(GetHeightOfRowAndVisibleChildren(widget)); + + return rect; + } + + PropertyRowWidget* EntityPropertyEditor::GetRowWidgetAtSameLevelAfter(PropertyRowWidget* widget) const + { + PropertyRowWidget* parent = widget->GetParentRow(); + + bool found = false; + for (PropertyRowWidget* child : parent->GetChildrenRows()) + { + if (found) + { + return child; + } + + if (child == widget) + { + found = true; + } + } + + return nullptr; + } + + PropertyRowWidget* EntityPropertyEditor::GetRowWidgetAtSameLevelBefore(PropertyRowWidget* widget) const + { + PropertyRowWidget* parent = widget->GetParentRow(); + + PropertyRowWidget* previous = nullptr; + for (PropertyRowWidget* child : parent->GetChildrenRows()) + { + if (child == widget) + { + return previous; + } + + previous = child; + } + + return nullptr; + } + QRect EntityPropertyEditor::GetWidgetGlobalRect(const QWidget* widget) const { return QRect( @@ -3757,6 +4163,8 @@ namespace AzToolsFramework m_shouldScrollToNewComponents = false; m_shouldScrollToNewComponentsQueued = false; m_newComponentId.reset(); + + HighlightMovedRowWidget(); } void EntityPropertyEditor::QueueScrollToNewComponent() @@ -3909,9 +4317,64 @@ namespace AzToolsFramework event->accept(); } + bool EntityPropertyEditor::HandleMenuEvent(QObject* /*object*/, QEvent* event) + { + QMenu* menu = qobject_cast(QApplication::activePopupWidget()); + if (!menu) + { + return false; + } + + PropertyRowWidget* lastReorderDropTarget = m_reorderDropTarget; + + switch (event->type()) + { + case QEvent::Leave: + m_reorderDropTarget = nullptr; + break; + case QEvent::Enter: + // Drop through. + case QEvent::MouseMove: + QMouseEvent* originalMouseEvent = static_cast(event); + QAction* action = menu->actionAt(originalMouseEvent->pos()); + if (!action) + { + m_reorderDropTarget = nullptr; + break; + } + + if (action->data() == kPropertyEditorMenuActionMoveUp) + { + m_reorderDropTarget = GetRowWidgetAtSameLevelBefore(m_reorderRowWidget); + + m_reorderDropArea = EntityPropertyEditor::DropArea::Above; + } + else if (action->data() == kPropertyEditorMenuActionMoveDown) + { + m_reorderDropTarget = GetRowWidgetAtSameLevelAfter(m_reorderRowWidget); + + if (m_reorderDropTarget) + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Below; + } + } + + break; + } + + if (lastReorderDropTarget != m_reorderDropTarget) + { + // Force a redraw as the menu is preventing automatic updates. + repaint(0, 0, -1, -1); + } + + return false; + } + //overridden to intercept application level mouse events for component editor selection bool EntityPropertyEditor::eventFilter(QObject* object, QEvent* event) { + HandleMenuEvent(object, event); HandleSelectionEvents(object, event); return false; } @@ -3919,11 +4382,23 @@ namespace AzToolsFramework void EntityPropertyEditor::mousePressEvent(QMouseEvent* event) { ResetDrag(event); + + PropertyRowWidget* rowWidget = FindPropertyRowWidgetAt(event->globalPos()); + if (rowWidget && rowWidget->CanBeReordered() && event->buttons() & Qt::LeftButton) + { + QApplication::setOverrideCursor(m_dragCursor); + } } void EntityPropertyEditor::mouseReleaseEvent(QMouseEvent* event) { ResetDrag(event); + + Qt::MouseButtons realButtons = QApplication::mouseButtons(); + if (QApplication::overrideCursor() && !(event->buttons() & Qt::LeftButton)) + { + QApplication::restoreOverrideCursor(); + } } void EntityPropertyEditor::mouseMoveEvent(QMouseEvent* event) @@ -3963,6 +4438,21 @@ namespace AzToolsFramework void EntityPropertyEditor::dropEvent(QDropEvent* event) { HandleDrop(event); + + if (QApplication::overrideCursor()) + { + QApplication::restoreOverrideCursor(); + } + } + + void EntityPropertyEditor::DragStopped() + { + if (QApplication::overrideCursor()) + { + QApplication::restoreOverrideCursor(); + } + + EndRowWidgetReorder(); } bool EntityPropertyEditor::HandleSelectionEvents(QObject* object, QEvent* event) @@ -4319,11 +4809,110 @@ namespace AzToolsFramework return true; } + bool EntityPropertyEditor::FindAllowedRowWidgetReorderDropTarget(const QPoint& globalPos) + { + const QRect globalRect(globalPos, globalPos); + + AZ_Assert(m_reorderRowWidgetEditor, "Missing editor for row widget drag."); + + AzToolsFramework::ReflectedPropertyEditor::WidgetList widgets = m_reorderRowWidgetEditor->GetPropertyEditor()->GetWidgets(); + for (auto widgetPair : widgets) + { + PropertyRowWidget* widget = widgetPair.second; + if (!widget) + { + continue; + } + + if (DoesIntersectWidget(globalRect, reinterpret_cast(widget))) + { + if (widget->CanBeReordered() && widget->GetParentRow() == m_reorderRowWidget->GetParentRow()) + { + m_reorderDropTarget = widget; + + QRect widgetRect = GetWidgetAndVisibleChildrenGlobalRect(widget); + if (globalPos.y() < widgetRect.center().y()) + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Above; + } + else + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Below; + } + + return true; + } + + // We're hovering over a child of a reorderable ancestor, use the ancestor as the drop target. + PropertyRowWidget* parent = widget->GetParentRow(); + while (parent) + { + if (parent->CanBeReordered() && parent->GetParentRow() == m_reorderRowWidget->GetParentRow()) + { + m_reorderDropTarget = parent; + + QRect widgetRect = GetWidgetAndVisibleChildrenGlobalRect(parent); + if (globalPos.y() < widgetRect.center().y()) + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Above; + } + else + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Below; + } + + return true; + } + parent = parent->GetParentRow(); + } + } + } + + return false; + } + + bool EntityPropertyEditor::UpdateRowWidgetDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* /*mimeData*/) + { + const QPoint globalPos(mapToGlobal(localPos)); + const QRect globalRect(globalPos, globalPos); + + if (!m_reorderRowWidget) + { + return false; + } + + if (m_reorderDropTarget) + { + m_reorderDropTarget = nullptr; + } + + UpdateOverlay(); + + // additional checks since handling is done in event filter + if ((mouseButtons & Qt::LeftButton) && DoesIntersectWidget(globalRect, this)) + { + FindAllowedRowWidgetReorderDropTarget(globalPos); + { + UpdateOverlay(); + return true; + } + } + return false; + } + bool EntityPropertyEditor::UpdateDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* mimeData) { const QPoint globalPos(mapToGlobal(localPos)); const QRect globalRect(globalPos, globalPos); + if (m_reorderRowWidget) + { + UpdateRowWidgetDrag(localPos, mouseButtons, mimeData); + QueueAutoScroll(); + UpdateOverlay(); + return true; + } + //reset drop indicators for (auto componentEditor : m_componentEditors) { @@ -4357,6 +4946,28 @@ namespace AzToolsFramework return false; } + PropertyRowWidget* EntityPropertyEditor::FindPropertyRowWidgetAt(QPoint globalPos) + { + const QRect globalRect(globalPos, globalPos); + + const bool dragSelected = DoesIntersectSelectedComponentEditor(globalRect); + const auto& componentEditors = dragSelected ? GetSelectedComponentEditors() : GetIntersectingComponentEditors(globalRect); + + for (auto componentEditor : componentEditors) + { + AzToolsFramework::ReflectedPropertyEditor::WidgetList widgets = componentEditor->GetPropertyEditor()->GetWidgets(); + for (auto& [dataNode, rowWidget] : widgets) + { + if (DoesIntersectWidget(globalRect, reinterpret_cast(rowWidget)) && rowWidget->CanBeReordered()) + { + return rowWidget; + } + } + } + + return nullptr; + } + bool EntityPropertyEditor::StartDrag(QMouseEvent* event) { // do not initiate a drag if property editor is disabled @@ -4402,7 +5013,27 @@ namespace AzToolsFramework if (!intersectsHeader) { - return false; + for (auto componentEditor : componentEditors) + { + AzToolsFramework::ReflectedPropertyEditor::WidgetList widgets = componentEditor->GetPropertyEditor()->GetWidgets(); + for (AZStd::pair w : widgets) + { + if (w.second) + { + if (DoesIntersectWidget(dragRect, reinterpret_cast(w.second)) && w.second->CanBeReordered()) + { + m_currentReorderState = EntityPropertyEditor::ReorderState::DraggingRowWidget; + m_reorderRowWidget = w.second; + m_reorderRowWidgetEditor = componentEditor; + if (m_reorderDropTarget) + { + m_reorderDropTarget = nullptr; + } + break; + } + } + } + } } m_dragStarted = true; @@ -4412,105 +5043,166 @@ namespace AzToolsFramework QRect dragImageRect; - AZStd::vector componentEditorIndices; - componentEditorIndices.reserve(componentEditors.size()); - for (auto componentEditor : componentEditors) + if (m_reorderRowWidget) { - //compute the drag image size - if (componentEditorIndices.empty()) - { - dragImageRect = componentEditor->rect(); - } - else - { - dragImageRect.setHeight(dragImageRect.height() + componentEditor->rect().height()); - } + // We're dragging a PropertyRowWidget, grab the image from that. + mimeData->setData(kComponentEditorRowWidgetType, QByteArray()); - //add component editor index to drag data - auto componentEditorIndex = GetComponentEditorIndex(componentEditor); - if (componentEditorIndex >= 0) - { - componentEditorIndices.push_back(GetComponentEditorIndex(componentEditor)); - } + drag->setMimeData(mimeData); + drag->setPixmap(m_reorderRowWidget->createDragImage( + QColor("#8E863E"), QColor("#EAECAA"), 0.5f, PropertyRowWidget::DragImageType::SingleRow)); + drag->setHotSpot(m_dragStartPosition - GetWidgetGlobalRect(m_reorderRowWidget).topLeft()); + drag->setDragCursor(m_dragIcon.pixmap(32), Qt::DropAction::MoveAction); + // Ensure we can tidy up if the drop happens elsewhere. + connect(drag, &QObject::destroyed, this, &EntityPropertyEditor::DragStopped); + drag->exec(Qt::MoveAction, Qt::MoveAction); } - - //build image from dragged editor UI - QImage dragImage(dragImageRect.size(), QImage::Format_ARGB32_Premultiplied); - QPainter painter(&dragImage); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(dragImageRect, Qt::transparent); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - painter.setOpacity(0.5f); - - //render a vertical stack of component editors, may change to render just the headers - QPoint dragImageOffset(0, 0); - for (AZ::s32 index : componentEditorIndices) + else { - auto componentEditor = GetComponentEditorsFromIndex(index); - if (componentEditor) + AZStd::vector componentEditorIndices; + componentEditorIndices.reserve(componentEditors.size()); + for (auto componentEditor : componentEditors) { - if (DoesIntersectWidget(dragRect, componentEditor)) + // compute the drag image size + if (componentEditorIndices.empty()) { - //offset drag image from the drag start position - drag->setHotSpot(dragImageOffset + (m_dragStartPosition - GetWidgetGlobalRect(componentEditor).topLeft())); + dragImageRect = componentEditor->rect(); + } + else + { + dragImageRect.setHeight(dragImageRect.height() + componentEditor->rect().height()); } - //render the component editor to the drag image - componentEditor->render(&painter, dragImageOffset); - - //update the render offset by the component editor height - dragImageOffset.setY(dragImageOffset.y() + componentEditor->rect().height()); + // add component editor index to drag data + auto componentEditorIndex = GetComponentEditorIndex(componentEditor); + if (componentEditorIndex >= 0) + { + componentEditorIndices.push_back(GetComponentEditorIndex(componentEditor)); + } } - } - painter.end(); - //mark dragged components after drag initiated to draw indicators - for (AZ::s32 index : componentEditorIndices) - { - auto componentEditor = GetComponentEditorsFromIndex(index); - if (componentEditor) + // build image from dragged editor UI + QImage dragImage(dragImageRect.size(), QImage::Format_ARGB32_Premultiplied); + QPainter painter(&dragImage); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(dragImageRect, Qt::transparent); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + painter.setOpacity(0.5f); + + // render a vertical stack of component editors, may change to render just the headers + QPoint dragImageOffset(0, 0); + for (AZ::s32 index : componentEditorIndices) { - componentEditor->SetDragged(true); + auto componentEditor = GetComponentEditorsFromIndex(index); + if (componentEditor) + { + if (DoesIntersectWidget(dragRect, componentEditor)) + { + // offset drag image from the drag start position + drag->setHotSpot(dragImageOffset + (m_dragStartPosition - GetWidgetGlobalRect(componentEditor).topLeft())); + } + + // render the component editor to the drag image + componentEditor->render(&painter, dragImageOffset); + + // update the render offset by the component editor height + dragImageOffset.setY(dragImageOffset.y() + componentEditor->rect().height()); + } } - } - UpdateOverlay(); + painter.end(); - //encode component editor indices as internal drag data - mimeData->setData( - kComponentEditorIndexMimeType, - QByteArray(reinterpret_cast(componentEditorIndices.data()), static_cast(componentEditorIndices.size() * sizeof(AZ::s32)))); - - drag->setMimeData(mimeData); - drag->setPixmap(QPixmap::fromImage(dragImage)); - drag->exec(Qt::MoveAction, Qt::MoveAction); - - //mark dragged components after drag completed to stop drawing indicators - for (AZ::s32 index : componentEditorIndices) - { - auto componentEditor = GetComponentEditorsFromIndex(index); - if (componentEditor) + // mark dragged components after drag initiated to draw indicators + for (AZ::s32 index : componentEditorIndices) { - componentEditor->SetDragged(false); + auto componentEditor = GetComponentEditorsFromIndex(index); + if (componentEditor) + { + componentEditor->SetDragged(true); + } + } + UpdateOverlay(); + + // encode component editor indices as internal drag data + mimeData->setData( + kComponentEditorIndexMimeType, + QByteArray( + reinterpret_cast(componentEditorIndices.data()), + static_cast(componentEditorIndices.size() * sizeof(AZ::s32)))); + + drag->setMimeData(mimeData); + drag->setPixmap(QPixmap::fromImage(dragImage)); + drag->exec(Qt::MoveAction, Qt::MoveAction); + + // mark dragged components after drag completed to stop drawing indicators + for (AZ::s32 index : componentEditorIndices) + { + auto componentEditor = GetComponentEditorsFromIndex(index); + if (componentEditor) + { + componentEditor->SetDragged(false); + } } } + UpdateOverlay(); return true; } + void EntityPropertyEditor::SetRowWidgetHighlighted(PropertyRowWidget* rowWidget) + { + m_reorderRowWidget = rowWidget; + m_reorderRowImage = rowWidget->createDragImage( + QColor("#8E863E"), QColor("#EAECAA"), 0.5f, PropertyRowWidget::DragImageType::IncludeVisibleChildren); + } + + void EntityPropertyEditor::EndRowWidgetReorder() + { + m_reorderDropTarget = nullptr; + m_reorderRowWidget = nullptr; + m_reorderDropTarget = nullptr; + m_currentReorderState = EntityPropertyEditor::ReorderState::Inactive; + m_overlay->setVisible(false); + } + bool EntityPropertyEditor::HandleDrop(QDropEvent* event) { const QPoint globalPos(mapToGlobal(event->pos())); const QMimeData* mimeData = event->mimeData(); - if (IsDropAllowed(mimeData, globalPos)) + + if (m_currentReorderState == EntityPropertyEditor::ReorderState::DraggingRowWidget) { - //handle drop for supported mime types - HandleDropForComponentTypes(event); - HandleDropForComponentAssets(event); - HandleDropForAssetBrowserEntries(event); - HandleDropForComponentReorder(event); + if (FindAllowedRowWidgetReorderDropTarget(globalPos)) + { + if (m_reorderDropArea == EntityPropertyEditor::DropArea::Above) + { + m_reorderRowWidgetEditor->GetPropertyEditor()->MoveNodeBefore( + m_reorderRowWidget->GetNode(), m_reorderDropTarget->GetNode()); + } + else + { + m_reorderRowWidgetEditor->GetPropertyEditor()->MoveNodeAfter( + m_reorderRowWidget->GetNode(), m_reorderDropTarget->GetNode()); + } + } + event->acceptProposedAction(); - return true; + + EndRowWidgetReorder(); } + else + { + if (IsDropAllowed(mimeData, globalPos)) + { + // handle drop for supported mime types + HandleDropForComponentTypes(event); + HandleDropForComponentAssets(event); + HandleDropForAssetBrowserEntries(event); + HandleDropForComponentReorder(event); + event->acceptProposedAction(); + return true; + } + } + return false; } @@ -5036,6 +5728,69 @@ namespace AzToolsFramework componentEditor->ActiveComponentModeChanged(componentType); } } + + EntityPropertyEditor::ReorderState EntityPropertyEditor::GetReorderState() const + { + return m_currentReorderState; + } + + ComponentEditor* EntityPropertyEditor::GetEditorForCurrentReorderRowWidget() const + { + return m_reorderRowWidgetEditor; + } + + PropertyRowWidget* EntityPropertyEditor::GetReorderRowWidget() const + { + return m_reorderRowWidget; + } + + PropertyRowWidget* EntityPropertyEditor::GetReorderDropTarget() const + { + return m_reorderDropTarget; + } + + EntityPropertyEditor::DropArea EntityPropertyEditor::GetReorderDropArea() const + { + return m_reorderDropArea; + } + + QPixmap EntityPropertyEditor::GetReorderRowWidgetImage() const + { + return m_reorderRowImage; + } + + float EntityPropertyEditor::GetMoveIndicatorAlpha() const + { + if (m_currentReorderState != ReorderState::MenuOperationInProgress) + { + return 1.0f; + } + + return m_moveFadeSecondsRemaining / MoveFadeSeconds; + } + + PropertyRowWidget* EntityPropertyEditor::GetRowToHighlight() + { + // Use the pregenerated map to find the RowWidget that's in the new position. + QSet rowWidgets = m_reorderRowWidgetEditor->GetPropertyEditor()->GetTopLevelWidgets(); + if (rowWidgets.isEmpty()) + { + return nullptr; + } + + PropertyRowWidget* highlightRow = *rowWidgets.begin(); + + int mapIndex = static_cast(m_indexMapOfMovedRow.size() - 1); + + while (mapIndex >= 0) + { + int mapEntry = m_indexMapOfMovedRow[mapIndex]; + highlightRow = highlightRow->GetChildrenRows()[mapEntry]; + mapIndex--; + } + + return highlightRow; + } } StatusComboBox::StatusComboBox(QWidget* parent) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx index 166d4c4392..3ff69f80e0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,7 @@ namespace AzToolsFramework , public EditorInspectorComponentNotificationBus::MultiHandler , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler , public AZ::EntitySystemBus::Handler + , public AZ::TickBus::Handler , private EditorWindowUIRequestBus::Handler { Q_OBJECT; @@ -117,6 +119,23 @@ namespace AzToolsFramework AZ_CLASS_ALLOCATOR(EntityPropertyEditor, AZ::SystemAllocator, 0) + enum class ReorderState + { + Inactive, // No row widget reordering operation is in progress. + DraggingComponent, // User is dragging a component editor. + DraggingRowWidget, // User is dragging a row widget around. + UsingMenu, // User has the context menu open and may hover over a move up/down operation. + MenuOperationInProgress, // User has selected a move/up down menu item. + WaitForRedraw, // Wait for rebuild of RPE. + HighlightMovedRow // User has moved a row, highlight the new position. + }; + + enum class DropArea + { + Above, + Below + }; + EntityPropertyEditor(QWidget* pParent = NULL, Qt::WindowFlags flags = Qt::WindowFlags(), bool isLevelEntityEditor = false); virtual ~EntityPropertyEditor(); @@ -151,6 +170,16 @@ namespace AzToolsFramework bool IsLockedToSpecificEntities() const { return !m_overrideSelectedEntityIds.empty(); } static bool AreComponentsCopyable(const AZ::Entity::ComponentArrayType& components, const ComponentFilter& filter); + + ReorderState GetReorderState() const; + ComponentEditor* GetEditorForCurrentReorderRowWidget() const; + PropertyRowWidget* GetReorderRowWidget() const; + PropertyRowWidget* GetReorderDropTarget() const; + DropArea GetReorderDropArea() const; + QPixmap GetReorderRowWidgetImage() const; + float GetMoveIndicatorAlpha() const; + PropertyRowWidget* GetRowToHighlight(); + Q_SIGNALS: void SelectedEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name); @@ -211,6 +240,9 @@ namespace AzToolsFramework void GetSelectedEntities(EntityIdList& selectedEntityIds) override; void SetNewComponentId(AZ::ComponentId componentId) override; + // TickBus + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + // EditorWindowRequestBus overrides void SetEditorUiEnabled(bool enable) override; @@ -253,6 +285,10 @@ namespace AzToolsFramework void ContextMenuActionPullFieldData(AZ::Component* parentComponent, InstanceDataNode* fieldNode); void ContextMenuActionSetDataFlag(InstanceDataNode* node, AZ::DataPatch::Flag flag, bool additive); + void GenerateRowWidgetIndexMapToChildIndex(PropertyRowWidget* parent, int destIndex); + void ContextMenuActionMoveItemUp(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget); + void ContextMenuActionMoveItemDown(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget); + /// Given an InstanceDataNode, calculate a DataPatch address relative to the entity. /// @return true if successful. bool GetEntityDataPatchAddress(const InstanceDataNode* componentFieldNode, AZ::DataPatch::AddressType& dataPatchAddressOut, AZ::EntityId* entityIdOut = nullptr) const; @@ -341,8 +377,6 @@ namespace AzToolsFramework QAction* m_actionToMoveComponentsBottom = nullptr; QAction* m_resetToSliceAction = nullptr; - bool m_isShowingContextMenu = false; - void CreateActions(); void UpdateActions(); @@ -390,6 +424,10 @@ namespace AzToolsFramework void ResetToSlice(); bool DoesOwnFocus() const; + AZ::u32 GetHeightOfRowAndVisibleChildren(const PropertyRowWidget* row) const; + QRect GetWidgetAndVisibleChildrenGlobalRect(const PropertyRowWidget* widget) const; + PropertyRowWidget* GetRowWidgetAtSameLevelAfter(PropertyRowWidget* widget) const; + PropertyRowWidget* GetRowWidgetAtSameLevelBefore(PropertyRowWidget* widget) const; QRect GetWidgetGlobalRect(const QWidget* widget) const; bool DoesIntersectWidget(const QRect& globalRect, const QWidget* widget) const; bool DoesIntersectSelectedComponentEditor(const QRect& globalRect) const; @@ -445,6 +483,8 @@ namespace AzToolsFramework bool HandleSelectionEvents(QObject* object, QEvent* event); bool m_selectionEventAccepted; + bool HandleMenuEvent(QObject* object, QEvent* event); + // drag and drop events QRect GetInflatedRectFromPoint(const QPoint& point, int radius) const; bool GetComponentsAtDropEventPosition(QDropEvent* event, AZ::Entity::ComponentArrayType& targetComponents); @@ -458,8 +498,12 @@ namespace AzToolsFramework ComponentEditor* GetReorderDropTarget(const QRect& globalRect) const; bool ResetDrag(QMouseEvent* event); + bool FindAllowedRowWidgetReorderDropTarget(const QPoint& globalPos); + bool UpdateRowWidgetDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* mimeData); + PropertyRowWidget* FindPropertyRowWidgetAt(QPoint globalPos); bool UpdateDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* mimeData); bool StartDrag(QMouseEvent* event); + void EndRowWidgetReorder(); bool HandleDrop(QDropEvent* event); bool HandleDropForComponentTypes(QDropEvent* event); bool HandleDropForComponentAssets(QDropEvent* event); @@ -468,6 +512,8 @@ namespace AzToolsFramework bool CanDropForComponentTypes(const QMimeData* mimeData) const; bool CanDropForComponentAssets(const QMimeData* mimeData) const; bool CanDropForAssetBrowserEntries(const QMimeData* mimeData) const; + void SetRowWidgetHighlighted(PropertyRowWidget* rowWidget); + AZStd::vector ExtractComponentEditorIndicesFromMimeData(const QMimeData* mimeData) const; ComponentEditorVector GetComponentEditorsFromIndices(const AZStd::vector& indices) const; ComponentEditor* GetComponentEditorsFromIndex(const AZ::s32 index) const; @@ -559,6 +605,8 @@ namespace AzToolsFramework QIcon m_emptyIcon; QIcon m_clearIcon; + QIcon m_dragIcon; + QCursor m_dragCursor; QStandardItem* m_comboItems[StatusItems]; EntityIdSet m_overrideSelectedEntityIds; @@ -566,6 +614,19 @@ namespace AzToolsFramework Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr; bool m_prefabsAreEnabled = false; + // Reordering row widgets within the RPE. + static constexpr float MoveFadeSeconds = 0.5f; + + ReorderState m_currentReorderState = ReorderState::Inactive; + ComponentEditor* m_reorderRowWidgetEditor = nullptr; + InstanceDataNode* m_nodeToMove = nullptr; + PropertyRowWidget* m_reorderRowWidget = nullptr; + PropertyRowWidget* m_reorderDropTarget = nullptr; + DropArea m_reorderDropArea = DropArea::Above; + QPixmap m_reorderRowImage; + float m_moveFadeSecondsRemaining; + AZStd::vector m_indexMapOfMovedRow; + // When m_initiatingPropertyChangeNotification is set to true, it means this EntityPropertyEditor is // broadcasting a change to all listeners about a property change for a given entity. This is needed // so that we don't update the values twice for this inspector @@ -573,6 +634,9 @@ namespace AzToolsFramework void ConnectToEntityBuses(const AZ::EntityId& entityId); void DisconnectFromEntityBuses(const AZ::EntityId& entityId); + void BeginMoveRowWidgetFade(); + void HighlightMovedRowWidget(); + //! Stores a component id to be focused on next time the UI updates. AZStd::optional m_newComponentId; @@ -594,6 +658,8 @@ namespace AzToolsFramework bool SelectedEntitiesAreFromSameSourceSliceEntity() const; + void DragStopped(); + AZ::Entity* GetSelectedEntityById(AZ::EntityId& entityId) const; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index 05c04872e3..c3da1e69b0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -368,10 +368,15 @@ namespace AzToolsFramework delete m_containerAddButton; } + this->unsetCursor(); + if ((m_parentRow) && (m_parentRow->IsContainerEditable())) { if (!m_elementRemoveButton) { + QIcon icon = QIcon(QStringLiteral(":/Cursors/Grab_release.svg")); + this->setCursor(QCursor(icon.pixmap(16), 5, 2)); + static QIcon s_iconRemove(QStringLiteral(":/stylesheet/img/UI20/delete-16.svg")); m_elementRemoveButton = new QToolButton(this); m_elementRemoveButton->setAutoRaise(true); @@ -570,7 +575,12 @@ namespace AzToolsFramework AZ_Assert(m_selectionEnabled, "Property is not selectable"); m_isSelected = selected; m_nameLabel->setProperty("selected", selected); - } + } + + bool PropertyRowWidget::GetSelected() + { + return m_isSelected; + } void PropertyRowWidget::SetSelectionEnabled(bool selectionEnabled) { @@ -1395,6 +1405,21 @@ namespace AzToolsFramework return !m_childrenRows.empty(); } + AZ::u32 PropertyRowWidget::GetChildRowCount() const + { + return static_cast(m_childrenRows.size()); + } + + PropertyRowWidget* PropertyRowWidget::GetChildRowByIndex(AZ::u32 index) const + { + if (index >= m_childrenRows.size()) + { + return nullptr; + } + + return m_childrenRows[index]; + } + bool PropertyRowWidget::ShouldPreValidatePropertyChange() const { return (m_changeValidators.size() > 0); @@ -1722,6 +1747,162 @@ namespace AzToolsFramework return m_parentRow->CanChildrenBeReordered(); } + + int PropertyRowWidget::GetIndexInParent() const + { + if (!GetParentRow()) + { + return -1; + } + + for (int index = 0; index < GetParentRow()->GetChildRowCount(); index++) + { + if (GetParentRow()->GetChildrenRows()[index] == this) + { + return index; + } + } + + return -1; + } + + bool PropertyRowWidget::CanMoveUp() const + { + if (!CanBeReordered()) + { + return false; + } + + return this != m_parentRow->GetChildRowByIndex(0); + } + + bool PropertyRowWidget::CanMoveDown() const + { + if (!CanBeReordered()) + { + return false; + } + + AZ::u32 numChildrenOfParent = m_parentRow->GetChildRowCount(); + + return this != m_parentRow->GetChildRowByIndex(numChildrenOfParent - 1); + } + + int PropertyRowWidget::GetContainingEditorFrameWidth() + { + QWidget* parent = parentWidget(); + + // Find the first ancestor that can be cast to a QFrame, this will be the RPE. + while (!qobject_cast(parent)) + { + parent = parent->parentWidget(); + } + + if (!parent) + { + return 0; + } + + // The parent of the RPE is the size we want. + parent = parent->parentWidget(); + + return parent->rect().width(); + } + + int PropertyRowWidget::GetHeightOfRowAndVisibleChildren() + { + int height = rect().height(); + + if (!GetChildRowCount() || !IsExpanded()) + { + return height; + } + + for (auto childRow : GetChildrenRows()) + { + height += childRow->GetHeightOfRowAndVisibleChildren(); + } + + return height; + } + + int PropertyRowWidget::DrawDragImageAndVisibleChildrenInto(QPainter& painter, int xpos, int ypos) + { + // Render our image into the given painter. + int ystart = ypos; + + render(&painter, QPoint(xpos, ypos)); + + if (!GetChildRowCount() || !IsExpanded()) + { + return rect().height(); + } + + ypos += rect().height(); + + // Recursively draw any children. + for (auto childRow : GetChildrenRows()) + { + ypos += childRow->DrawDragImageAndVisibleChildrenInto(painter, xpos, ypos); + } + + return ypos - ystart; + } + + QPixmap PropertyRowWidget::createDragImage( + const QColor backgroundColor, const QColor borderColor, const float alpha, DragImageType imageType) + { + // Make the drag box as wide as the containing editor minus a gap each side for the border. + static constexpr int ParentEditorBorderSize = 2; + int width = GetContainingEditorFrameWidth() - ParentEditorBorderSize * 2; + int height = 0; + + if (imageType == DragImageType::IncludeVisibleChildren) + { + height = GetHeightOfRowAndVisibleChildren(); + } + else + { + height = rect().height(); + } + + const auto dpr = devicePixelRatioF(); + QPixmap dragImage(width * dpr, height * dpr); + dragImage.setDevicePixelRatio(dpr); + dragImage.fill(Qt::transparent); + + QRect imageRect = QRect(0, 0, width, height); + + QPainter dragPainter(&dragImage); + dragPainter.setCompositionMode(QPainter::CompositionMode_Source); + dragPainter.fillRect(imageRect, Qt::transparent); + dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver); + dragPainter.setOpacity(alpha); + dragPainter.fillRect(imageRect, backgroundColor); + + dragPainter.setOpacity(1.0f); + + int marginWidth = (imageRect.width() - rect().width()) / 2 + ParentEditorBorderSize - 1; + + if (imageType == DragImageType::IncludeVisibleChildren) + { + DrawDragImageAndVisibleChildrenInto(dragPainter, marginWidth, 0); + } + else + { + render(&dragPainter, QPoint(marginWidth, 0)); + } + + QPen pen; + pen.setColor(QColor(borderColor)); + pen.setWidth(1); + dragPainter.setPen(pen); + dragPainter.drawRect(0, 0, imageRect.width() - 1, imageRect.height() - 1); + + dragPainter.end(); + + return dragImage; + } } #include "UI/PropertyEditor/moc_PropertyRowWidget.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx index ebf7c67b21..68cc9b9cf9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx @@ -45,6 +45,13 @@ namespace AzToolsFramework Q_PROPERTY(bool appendDefaultLabelToName READ GetAppendDefaultLabelToName WRITE AppendDefaultLabelToName) public: AZ_CLASS_ALLOCATOR(PropertyRowWidget, AZ::SystemAllocator, 0) + + enum class DragImageType + { + SingleRow, + IncludeVisibleChildren + }; + PropertyRowWidget(QWidget* pParent); virtual ~PropertyRowWidget(); @@ -86,6 +93,9 @@ namespace AzToolsFramework bool GetAppendDefaultLabelToName(); void AppendDefaultLabelToName(bool doAppend); + AZ::u32 GetChildRowCount() const; + PropertyRowWidget* GetChildRowByIndex(AZ::u32 index) const; + AZStd::vector& GetChildrenRows() { return m_childrenRows; } bool HasChildRows() const; @@ -124,6 +134,7 @@ namespace AzToolsFramework void SetSelectionEnabled(bool selectionEnabled); void SetSelected(bool selected); + bool GetSelected(); bool eventFilter(QObject *watched, QEvent *event) override; void paintEvent(QPaintEvent*) override; @@ -152,9 +163,18 @@ namespace AzToolsFramework bool CanChildrenBeReordered() const; bool CanBeReordered() const; + int GetIndexInParent() const; + bool CanMoveUp() const; + bool CanMoveDown() const; + + int GetContainingEditorFrameWidth(); + QPixmap createDragImage(const QColor backgroundColor, const QColor borderColor, const float alpha, DragImageType imageType); protected: int CalculateLabelWidth() const; + int GetHeightOfRowAndVisibleChildren(); + int DrawDragImageAndVisibleChildrenInto(QPainter& painter, int xpos, int ypos); + bool IsHidden(InstanceDataNode* node) const; struct ChangeNotification; @@ -216,6 +236,7 @@ namespace AzToolsFramework bool m_isMultiSizeContainer = false; bool m_isFixedSizeOrSmartPtrContainer = false; bool m_custom = false; + bool m_canChildrenBeReordered = false; bool m_isSelected = false; bool m_selectionEnabled = false; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp index 36462bca66..5d5b00e83d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp @@ -19,6 +19,7 @@ #include #include #include +#include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 'QTextFormat::d': class 'QSharedDataPointer' needs to have dll-interface to be used by clients of class 'QTextFormat' #include AZ_POP_DISABLE_WARNING @@ -1343,7 +1344,7 @@ namespace AzToolsFramework // calculate the index/offset of the instance data node in the container // (useful for notifying which element in a vector was modified/removed) - static size_t CalculateElementIndexInContainer( + static int CalculateElementIndexInContainer( InstanceDataNode* node, void* parentInstanceNode, AZ::SerializeContext::IDataContainer* container, AZStd::vector& nodeInstancesOut) { @@ -1358,7 +1359,7 @@ namespace AzToolsFramework } } - size_t elementIndex = 0; + int elementIndex = 0; void* elementPtr = nodeInstancesOut.empty() ? nullptr : nodeInstancesOut.front(); // find the index of the element we are about to remove @@ -1429,7 +1430,7 @@ namespace AzToolsFramework // if the element being modified exists in a container, calculate // the index to be passed through to PropertyNotify - const auto calculateElementIndex = [](InstanceDataNode* node) -> size_t { + const auto calculateElementIndex = [](InstanceDataNode* node) -> int { if (InstanceDataNode* parent = node->GetParent()) { if (AZ::SerializeContext::IDataContainer* container = parent->GetClassMetadata()->m_container) @@ -1656,6 +1657,221 @@ namespace AzToolsFramework AzToolsFramework::Refresh_EntireTree); } + InstanceDataNode* ReflectedPropertyEditor::FindContainerNodeForNode(InstanceDataNode* node) const + { + // Locate the owning container. There may be a level of indirection due to wrappers, such as DynamicSerializableField. + InstanceDataNode* pContainerNode = node->GetParent(); + if (!pContainerNode) + { + return nullptr; + } + + while (pContainerNode && !pContainerNode->GetClassMetadata()->m_container) + { + pContainerNode = pContainerNode->GetParent(); + node = node->GetParent(); + } + + // Check for pContainerNode again, can happen if a node is deleted during operation. + if (!pContainerNode) + { + return nullptr; + } + + if (IsParentAssociativeContainer(pContainerNode) && IsPairContainer(pContainerNode)) + { + // Go up one more level to the associative container, we'll remove the pair from that container + pContainerNode = pContainerNode->GetParent(); + node = node->GetParent(); + } + + AZ_Assert( + pContainerNode, "Failed to locate parent container for element \"%s\" of type %s.", + node->GetElementMetadata() ? node->GetElementMetadata()->m_name : node->GetClassMetadata()->m_name, + node->GetClassMetadata()->m_typeId.ToString().c_str()); + + return pContainerNode; + } + + InstanceDataNode* ReflectedPropertyEditor::GetNodeAtIndex(int index) + { + if (index >= m_impl->m_widgetsInDisplayOrder.size()) + { + return nullptr; + } + + return GetNodeFromWidget(m_impl->m_widgetsInDisplayOrder[index]); + } + + QSet ReflectedPropertyEditor::GetTopLevelWidgets() + { + return m_impl->getTopLevelWidgets(); + } + + void ReflectedPropertyEditor::ChangeNodeIndex(InstanceDataNode* containerNode, InstanceDataNode* node, int fromIndex, int toIndex) + { + auto container = containerNode->GetElementMetadata() + ? containerNode->GetElementMetadata()->m_genericClassInfo->GetClassData()->m_container + : nullptr; + + if (fromIndex == toIndex) + { + return; + } + + if (!container || container->GetAssociativeContainerInterface()) + { + return; + } + + AZ::Uuid typeId = node->GetClassMetadata()->m_typeId; + + if (m_impl->m_ptrNotify) + { + m_impl->m_ptrNotify->BeforePropertyModified(containerNode); + } + + const AZ::SerializeContext::ClassElement* containerClassElement = container->GetElement(container->GetDefaultElementNameCrc()); + + AZ::SerializeContext* serializeContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + + // Backup the item we're moving. + void* srcElement = nullptr; + void* destElement = nullptr; + + int destIndex = -1; + int srcIndex = fromIndex; + + srcElement = container->GetElementByIndex(containerNode->GetInstance(0), containerClassElement, srcIndex); + + void* tmpBuffer = serializeContext->CloneObject(srcElement, typeId); + + // Shuffle all intervening items up (or down). + int indexOffset = (toIndex < fromIndex) ? -1 : 1; + + while (destIndex != toIndex - indexOffset) + { + destIndex = srcIndex; + srcIndex += indexOffset; + + destElement = srcElement; + + srcElement = container->GetElementByIndex(containerNode->GetInstance(0), containerClassElement, srcIndex); + + serializeContext->CloneObjectInplace(destElement, srcElement, typeId); + } + + // Now replace the final element with the one backed up previously. + destElement = srcElement; + + serializeContext->CloneObjectInplace(destElement, tmpBuffer, typeId); + + if (m_impl->m_ptrNotify) + { + m_impl->m_ptrNotify->AfterPropertyModified(containerNode); + m_impl->m_ptrNotify->SealUndoStack(); + } + + // Need to refresh any pinned inspectors as well to keep the container state in sync + QueueInvalidation(Refresh_Values); + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values); + } + + void ReflectedPropertyEditor::MoveNodeToIndex(InstanceDataNode* node, int index) + { + InstanceDataNode* pContainerNode = FindContainerNodeForNode(node); + + if (!pContainerNode) + { + return; + } + + AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container; + + AZStd::vector nodeInstancesOut; + const int elementIndex = CalculateElementIndexInContainer(node, pContainerNode->GetInstance(0), container, nodeInstancesOut); + + ChangeNodeIndex(pContainerNode, node, elementIndex, index); + } + + void ReflectedPropertyEditor::MoveNodeBefore(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore) + { + InstanceDataNode* pContainerNode = FindContainerNodeForNode(nodeToMove); + InstanceDataNode* pContainerNodeTarget = FindContainerNodeForNode(nodeToMoveBefore); + + if (nodeToMove == nodeToMoveBefore) + { + return; + } + + // Can only move nodes within the same parent. + if (pContainerNode != pContainerNodeTarget) + { + return; + } + + AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container; + + AZStd::vector nodeInstancesOut; + int elementIndex = CalculateElementIndexInContainer(nodeToMove, pContainerNode->GetInstance(0), container, nodeInstancesOut); + nodeInstancesOut.clear(); + int elementIndexTarget = + CalculateElementIndexInContainer(nodeToMoveBefore, pContainerNode->GetInstance(0), container, nodeInstancesOut); + + if (elementIndex < elementIndexTarget) + { + elementIndexTarget -= 1; + } + + ChangeNodeIndex(pContainerNode, nodeToMove, elementIndex, elementIndexTarget); + } + + void ReflectedPropertyEditor::MoveNodeAfter(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore) + { + InstanceDataNode* pContainerNode = FindContainerNodeForNode(nodeToMove); + InstanceDataNode* pContainerNodeTarget = FindContainerNodeForNode(nodeToMoveBefore); + + if (nodeToMove == nodeToMoveBefore) + { + return; + } + + // Can only move nodes within the same parent. + if (pContainerNode != pContainerNodeTarget) + { + return; + } + + AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container; + + AZStd::vector nodeInstancesOut; + int elementIndex = CalculateElementIndexInContainer(nodeToMove, pContainerNode->GetInstance(0), container, nodeInstancesOut); + nodeInstancesOut.clear(); + int elementIndexTarget = + CalculateElementIndexInContainer(nodeToMoveBefore, pContainerNode->GetInstance(0), container, nodeInstancesOut); + + if (elementIndex > elementIndexTarget) + { + elementIndexTarget += 1; + } + + ChangeNodeIndex(pContainerNode, nodeToMove, elementIndex, elementIndexTarget); + } + + int ReflectedPropertyEditor::GetNodeIndexInContainer(InstanceDataNode* node) + { + InstanceDataNode* pContainerNode = FindContainerNodeForNode(node); + + AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container; + + AZStd::vector nodeInstancesOut; + int elementIndex = CalculateElementIndexInContainer(node, pContainerNode->GetInstance(0), container, nodeInstancesOut); + + return elementIndex; + } + void ReflectedPropertyEditor::OnPropertyRowRequestContainerRemoveItem(PropertyRowWidget* widget, InstanceDataNode* node) { // Locate the owning container. There may be a level of indirection due to wrappers, such as DynamicSerializableField. @@ -1690,7 +1906,7 @@ namespace AzToolsFramework // the index of the element being removed AZStd::vector nodeInstancesOut; - const size_t elementIndex = CalculateElementIndexInContainer( + const int elementIndex = CalculateElementIndexInContainer( node, pContainerNode->GetInstance(0), container, nodeInstancesOut); // pass the context as the last parameter to actually delete the related data. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx index b10e153162..28da540098 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx @@ -155,9 +155,19 @@ namespace AzToolsFramework using VisibilityCallback = AZStd::function; void SetVisibilityCallback(VisibilityCallback callback); + void MoveNodeToIndex(InstanceDataNode* node, int index); + void MoveNodeBefore(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore); + void MoveNodeAfter(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore); + + int GetNodeIndexInContainer(InstanceDataNode* node); + InstanceDataNode* GetNodeAtIndex(int index); + QSet GetTopLevelWidgets(); signals: void OnExpansionContractionDone(); private: + InstanceDataNode* FindContainerNodeForNode(InstanceDataNode* node) const; + void ChangeNodeIndex(InstanceDataNode* containerNode, InstanceDataNode* node, int oldIndex, int newIndex); + class Impl; std::unique_ptr m_impl; From f7e536bfb1868203c53e20c2895718da45f4784e Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Mon, 16 Aug 2021 12:37:12 +0100 Subject: [PATCH 071/101] compile fix - signed/unsigned mismatch (#3139) Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- .../AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index c3da1e69b0..604c6141d7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -1755,7 +1755,7 @@ namespace AzToolsFramework return -1; } - for (int index = 0; index < GetParentRow()->GetChildRowCount(); index++) + for (AZ::u32 index = 0; index < GetParentRow()->GetChildRowCount(); index++) { if (GetParentRow()->GetChildrenRows()[index] == this) { From 5925bd22f6e0607f9fda0a705c6b3738c81bda24 Mon Sep 17 00:00:00 2001 From: jonawals Date: Mon, 16 Aug 2021 14:15:02 +0100 Subject: [PATCH 072/101] Further subdivide TIAF data by suite. (#3128) * Further subdivide TIAF data by suite. * Key fix typo. Signed-off-by: John --- .../TestImpactRuntimeConfigurationFactory.cpp | 25 ++++--------- .../TestImpactClientSequenceReport.h | 2 +- .../TestImpactConfiguration.h | 4 +-- .../Runtime/Code/Source/TestImpactRuntime.cpp | 5 +-- .../ConsoleFrontendConfig.in | 11 ++---- scripts/build/TestImpactAnalysis/tiaf.py | 3 +- .../tiaf_persistent_storage.py | 35 +++++++++++-------- .../tiaf_persistent_storage_local.py | 2 ++ .../tiaf_persistent_storage_s3.py | 6 ++-- 9 files changed, 42 insertions(+), 51 deletions(-) diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp index 8ea32d6447..c2bc95a906 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp @@ -27,7 +27,7 @@ namespace TestImpact "relative_paths", "artifact_dir", "enumeration_cache_dir", - "test_impact_data_files", + "test_impact_data_file", "temp", "active", "target_sources", @@ -72,7 +72,7 @@ namespace TestImpact RelativePaths, ArtifactDir, EnumerationCacheDir, - TestImpactDataFiles, + TestImpactDataFile, TempWorkspace, ActiveWorkspace, TargetSources, @@ -138,31 +138,18 @@ namespace TestImpact tempWorkspaceConfig.m_artifactDirectory = GetAbsPathFromRelPath( tempWorkspaceConfig.m_root, tempWorkspace[Config::Keys[Config::RelativePaths]][Config::Keys[Config::ArtifactDir]].GetString()); + tempWorkspaceConfig.m_enumerationCacheDirectory = GetAbsPathFromRelPath( + tempWorkspaceConfig.m_root, + tempWorkspace[Config::Keys[Config::RelativePaths]][Config::Keys[Config::EnumerationCacheDir]].GetString()); return tempWorkspaceConfig; } - AZStd::array ParseTestImpactAnalysisDataFiles(const RepoPath& root, const rapidjson::Value& sparTiaFile) - { - AZStd::array sparTiaFiles; - sparTiaFiles[static_cast(SuiteType::Main)] = - GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Main).c_str()].GetString()); - sparTiaFiles[static_cast(SuiteType::Periodic)] = - GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Periodic).c_str()].GetString()); - sparTiaFiles[static_cast(SuiteType::Sandbox)] = - GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Sandbox).c_str()].GetString()); - - return sparTiaFiles; - } - WorkspaceConfig::Active ParseActiveWorkspaceConfig(const rapidjson::Value& activeWorkspace) { WorkspaceConfig::Active activeWorkspaceConfig; const auto& relativePaths = activeWorkspace[Config::Keys[Config::RelativePaths]]; activeWorkspaceConfig.m_root = activeWorkspace[Config::Keys[Config::Root]].GetString(); - activeWorkspaceConfig.m_enumerationCacheDirectory - = GetAbsPathFromRelPath(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::EnumerationCacheDir]].GetString()); - activeWorkspaceConfig.m_sparTiaFiles = - ParseTestImpactAnalysisDataFiles(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::TestImpactDataFiles]]); + activeWorkspaceConfig.m_sparTiaFile = relativePaths[Config::Keys[Config::TestImpactDataFile]].GetString(); return activeWorkspaceConfig; } diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h index e86123ddc7..1ddd1042e6 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h @@ -530,7 +530,7 @@ namespace TestImpact size_t GetTotalNumTimedOutTestRuns() const override; size_t GetTotalNumUnexecutedTestRuns() const override; - //! Returns the report for the discarded test runs. + // ImpactAnalysisSequenceReport overrides ... const TestRunSelection GetDiscardedTestRuns() const; //! Returns the report for the discarded test runs. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h index fcacd90e71..92dd454b01 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h @@ -37,14 +37,14 @@ namespace TestImpact { RepoPath m_root; //!< Path to the temporary workspace (cleaned prior to use). RepoPath m_artifactDirectory; //!< Path to read and write runtime artifacts to and from. + RepoPath m_enumerationCacheDirectory; //!< Path to the test enumerations cache. }; //! Active persistent data workspace configuration. struct Active { RepoPath m_root; //!< Path to the persistent workspace tracked by the repository. - RepoPath m_enumerationCacheDirectory; //!< Path to the test enumerations cache. - AZStd::array m_sparTiaFiles; //!< Paths to the test impact analysis data files for each test suite. + RepoPath m_sparTiaFile; //!< Paths to the test impact analysis data file. }; Temp m_temp; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp index 8a9d96bca8..515118dd7a 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp @@ -275,7 +275,7 @@ namespace TestImpact m_testEngine = AZStd::make_unique( m_config.m_repo.m_root, m_config.m_target.m_outputDirectory, - m_config.m_workspace.m_active.m_enumerationCacheDirectory, + m_config.m_workspace.m_temp.m_enumerationCacheDirectory, m_config.m_workspace.m_temp.m_artifactDirectory, m_config.m_testEngine.m_testRunner.m_binary, m_config.m_testEngine.m_instrumentation.m_binary, @@ -289,7 +289,8 @@ namespace TestImpact } else { - m_sparTiaFile = m_config.m_workspace.m_active.m_sparTiaFiles[static_cast(m_suiteFilter)].String(); + m_sparTiaFile = + m_config.m_workspace.m_active.m_root / RepoPath(SuiteTypeAsString(m_suiteFilter)) / m_config.m_workspace.m_active.m_sparTiaFile; } // Populate the dynamic dependency map with the existing source coverage data (if any) diff --git a/cmake/TestImpactFramework/ConsoleFrontendConfig.in b/cmake/TestImpactFramework/ConsoleFrontendConfig.in index 17fbd217d7..3b6318e1e0 100644 --- a/cmake/TestImpactFramework/ConsoleFrontendConfig.in +++ b/cmake/TestImpactFramework/ConsoleFrontendConfig.in @@ -15,19 +15,14 @@ "temp": { "root": "${temp_dir}", "relative_paths": { - "artifact_dir": "RuntimeArtifact" + "artifact_dir": "RuntimeArtifact", + "enumeration_cache_dir": "EnumerationCache" } }, "active": { "root": "${active_dir}", "relative_paths": { - "test_impact_data_files": { - "main": "TestImpactData.main.spartia", - "periodic": "TestImpactData.periodic.spartia", - "sandbox": "TestImpactData.sandbox.spartia" - }, - "enumeration_cache_dir": "EnumerationCache", - "last_build_target_list_file": "LastRunBuildTargets.json" + "test_impact_data_file": "TestImpactData.spartia" } }, "historic": { diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index e8faef30e3..27fbaf451f 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -230,7 +230,7 @@ class TestImpact: # Flag for corner case where: # 1. TIAF was already run previously for this commit. - # 2. There was no last commit hash when TIAF last ran on this commit (due to no coverage data existing get for this branch) + # 2. There was no last commit hash when TIAF last ran on this commit (due to no coverage data existing yet for this branch) # 3. TIAF has not been run on any other commits between the run for this commit and the last run for this commit. # The above results in TIAF being stuck in a state of generating an empty change list (and thus doing no work until another # commit comes in) which is problematic if the commit needs to be re-run for whatever reason so in these conditions we revert @@ -323,7 +323,6 @@ class TestImpact: logger.info(f"Args: {unpacked_args}") runtime_result = subprocess.run([str(self._tiaf_bin)] + args) report = None - # If the sequence completed (with or without failures) we will update the historical meta-data if runtime_result.returncode == 0 or runtime_result.returncode == 7: logger.info("Test impact analysis runtime returned successfully.") diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index 3fff05b549..5445c1f955 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -17,11 +17,11 @@ logger = get_logger(__file__) class PersistentStorage(ABC): WORKSPACE_KEY = "workspace" - LAST_RUNS_KEY = "last_runs" + HISTORIC_SEQUENCES_KEY = "historic_sequences" ACTIVE_KEY = "active" ROOT_KEY = "root" RELATIVE_PATHS_KEY = "relative_paths" - TEST_IMPACT_DATA_FILES_KEY = "test_impact_data_files" + TEST_IMPACT_DATA_FILE_KEY = "test_impact_data_file" LAST_COMMIT_HASH_KEY = "last_commit_hash" COVERAGE_DATA_KEY = "coverage_data" @@ -35,19 +35,21 @@ class PersistentStorage(ABC): """ # Work on the assumption that there is no historic meta-data (a valid state to be in, should none exist) + self._suite = suite self._last_commit_hash = None self._has_historic_data = False self._has_previous_last_commit_hash = False self._this_commit_hash = commit self._this_commit_hash_last_commit_hash = None self._historic_data = None - logger.info(f"Attempting to access persistent storage for the commit {self._this_commit_hash}") + logger.info(f"Attempting to access persistent storage for the commit '{self._this_commit_hash}' for suite '{self._suite}'") try: # The runtime expects the coverage data to be in the location specified in the config file (unless overridden with # the --datafile command line argument, which the TIAF scripts do not do) self._active_workspace = pathlib.Path(config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.ROOT_KEY]) - unpacked_coverage_data_file = config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.RELATIVE_PATHS_KEY][self.TEST_IMPACT_DATA_FILES_KEY][suite] + self._active_workspace = self._active_workspace.joinpath(pathlib.Path(self._suite)) + unpacked_coverage_data_file = config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.RELATIVE_PATHS_KEY][self.TEST_IMPACT_DATA_FILE_KEY] except KeyError as e: raise SystemError(f"The config does not contain the key {str(e)}.") @@ -70,25 +72,27 @@ class PersistentStorage(ABC): self._last_commit_hash = self._historic_data[self.LAST_COMMIT_HASH_KEY] logger.info(f"Last commit hash '{self._last_commit_hash}' found.") - if self.LAST_RUNS_KEY in self._historic_data: - # Last commit hash for the sequence that was run for this commit previously (if any) - if self._this_commit_hash in self._historic_data[self.LAST_RUNS_KEY]: + # Last commit hash for the sequence that was run for this commit previously (if any) + if self.HISTORIC_SEQUENCES_KEY in self._historic_data: + if self._this_commit_hash in self._historic_data[self.HISTORIC_SEQUENCES_KEY]: # 'None' is a valid value for the previously used last commit hash if there was no coverage data at that time - self._this_commit_hash_last_commit_hash = self._historic_data[self.LAST_RUNS_KEY][self._this_commit_hash] + self._this_commit_hash_last_commit_hash = self._historic_data[self.HISTORIC_SEQUENCES_KEY][self._this_commit_hash] self._has_previous_last_commit_hash = self._this_commit_hash_last_commit_hash is not None if self._has_previous_last_commit_hash: logger.info(f"Last commit hash '{self._this_commit_hash_last_commit_hash}' was used previously for this commit.") else: - logger.info(f"Prior sequence data found for this commit but it is empty (there was no coverage data vailable at that time).") + logger.info(f"Prior sequence data found for this commit but it is empty (there was no coverage data available at that time).") else: logger.info(f"No prior sequence data found for commit '{self._this_commit_hash}', this is the first sequence for this commit.") else: logger.info(f"No prior sequence data found for any commits.") - # Create the active workspace directory where the coverage data file will be placed and unpack the coverage data so - # it is accessible by the runtime + # Create the active workspace directory for the unpacked historic data files so they are accessible by the runtime self._active_workspace.mkdir(exist_ok=True) + + # Coverage file + logger.info(f"Writing coverage data to '{self._unpacked_coverage_data_file}'.") with open(self._unpacked_coverage_data_file, "w", newline='\n') as coverage_data: coverage_data.write(self._historic_data[self.COVERAGE_DATA_KEY]) @@ -117,9 +121,12 @@ class PersistentStorage(ABC): self._historic_data[self.LAST_COMMIT_HASH_KEY] = self._this_commit_hash # Last commit hash for this commit - if not self.LAST_RUNS_KEY in self._historic_data: - self._historic_data[self.LAST_RUNS_KEY] = {} - self._historic_data[self.LAST_RUNS_KEY][self._this_commit_hash] = self._last_commit_hash + if not self.HISTORIC_SEQUENCES_KEY in self._historic_data: + self._historic_data[self.HISTORIC_SEQUENCES_KEY] = {} + self._historic_data[self.HISTORIC_SEQUENCES_KEY][self._this_commit_hash] = self._last_commit_hash + + # Test runs for this completed sequence + self._historic_data[self.PREVIOUS_TEST_RUNS_KEY] = test_runs # Coverage data for this branch with open(self._unpacked_coverage_data_file, "r") as coverage_data: diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py index c72fafc580..7ad9155a41 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py @@ -32,10 +32,12 @@ class PersistentStorageLocal(PersistentStorage): try: # Attempt to obtain the local persistent data location specified in the runtime config file self._historic_workspace = pathlib.Path(config[self.WORKSPACE_KEY][self.HISTORIC_KEY][self.ROOT_KEY]) + self._historic_workspace = self._historic_workspace.joinpath(pathlib.Path(self._suite)) historic_data_file = pathlib.Path(config[self.WORKSPACE_KEY][self.HISTORIC_KEY][self.RELATIVE_PATHS_KEY][self.DATA_KEY]) # Attempt to unpack the local historic data file self._historic_data_file = self._historic_workspace.joinpath(historic_data_file) + logger.info(f"Attempting to retrieve historic data at location '{self._historic_data_file}'...") if self._historic_data_file.is_file(): with open(self._historic_data_file, "r") as historic_data_raw: historic_data_json = historic_data_raw.read() diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py index 074caf73a1..175eb3148d 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py @@ -43,9 +43,9 @@ class PersistentStorageS3(PersistentStorage): # historic_data.json.zip is the file containing the coverage and meta-data of the last TIAF sequence run historic_data_file = f"historic_data.{object_extension}" - # The location of the data is in the form // so the build config of each branch gets its own historic data - self._historic_data_dir = f'{root_dir}/{branch}/{config[self.META_KEY][self.BUILD_CONFIG_KEY]}' - self._historic_data_key = f'{self._historic_data_dir}/{historic_data_file}' + # The location of the data is in the form /// so the build config of each branch gets its own historic data + self._historic_data_dir = f"{root_dir}/{branch}/{config[self.META_KEY][self.BUILD_CONFIG_KEY]}/{self._suite}" + self._historic_data_key = f"{self._historic_data_dir}/{historic_data_file}" logger.info(f"Attempting to retrieve historic data for branch '{branch}' at location '{self._historic_data_key}' on bucket '{s3_bucket}'...") self._s3 = boto3.resource("s3") From e630e3324dc5836fcfea328d9e002fa0877f060b Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:46:46 +0100 Subject: [PATCH 073/101] fixed joint crash when no lead entity is selected (#2867) Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- Gems/PhysX/Code/Source/BallJointComponent.cpp | 19 +++++- .../PhysX/Code/Source/FixedJointComponent.cpp | 18 ++++- .../PhysX/Code/Source/HingeJointComponent.cpp | 18 ++++- .../Code/Source/Joint/PhysXJointUtils.cpp | 15 +++-- Gems/PhysX/Code/Tests/PhysXJointsTest.cpp | 66 +++++++++++++++++-- 5 files changed, 121 insertions(+), 15 deletions(-) diff --git a/Gems/PhysX/Code/Source/BallJointComponent.cpp b/Gems/PhysX/Code/Source/BallJointComponent.cpp index 12323e5077..60f7888b0d 100644 --- a/Gems/PhysX/Code/Source/BallJointComponent.cpp +++ b/Gems/PhysX/Code/Source/BallJointComponent.cpp @@ -46,11 +46,26 @@ namespace PhysX JointComponent::LeadFollowerInfo leadFollowerInfo; ObtainLeadFollowerInfo(leadFollowerInfo); - if (!leadFollowerInfo.m_followerActor) + if (leadFollowerInfo.m_followerActor == nullptr || + leadFollowerInfo.m_followerBody == nullptr) { return; } + // if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle. + AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle; + if (leadFollowerInfo.m_leadBody != nullptr) + { + parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle; + } + else + { + AZ_TracePrintf( + "PhysX", "Entity [%s] Ball Joint component missing lead entity. This joint will be a global constraint on the follower's global position.", + GetEntity()->GetName().c_str()); + } + + BallJointConfiguration configuration; configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation(); configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation(); @@ -65,7 +80,7 @@ namespace PhysX m_jointHandle = sceneInterface->AddJoint( leadFollowerInfo.m_followerBody->m_sceneOwner, &configuration, - leadFollowerInfo.m_leadBody->m_bodyHandle, + parentHandle, leadFollowerInfo.m_followerBody->m_bodyHandle); m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner; } diff --git a/Gems/PhysX/Code/Source/FixedJointComponent.cpp b/Gems/PhysX/Code/Source/FixedJointComponent.cpp index 53a9946998..82c8cc485c 100644 --- a/Gems/PhysX/Code/Source/FixedJointComponent.cpp +++ b/Gems/PhysX/Code/Source/FixedJointComponent.cpp @@ -54,11 +54,25 @@ namespace PhysX JointComponent::LeadFollowerInfo leadFollowerInfo; ObtainLeadFollowerInfo(leadFollowerInfo); - if (!leadFollowerInfo.m_followerActor) + if (leadFollowerInfo.m_followerActor == nullptr || + leadFollowerInfo.m_followerBody == nullptr) { return; } + // if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle. + AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle; + if (leadFollowerInfo.m_leadBody != nullptr) + { + parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle; + } + else + { + AZ_TracePrintf("PhysX", + "Entity [%s] Fixed Joint component missing lead entity. This joint will be a global constraint on the follower's global position.", + GetEntity()->GetName().c_str()); + } + FixedJointConfiguration configuration; configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation(); configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation(); @@ -72,7 +86,7 @@ namespace PhysX m_jointHandle = sceneInterface->AddJoint( leadFollowerInfo.m_followerBody->m_sceneOwner, &configuration, - leadFollowerInfo.m_leadBody->m_bodyHandle, + parentHandle, leadFollowerInfo.m_followerBody->m_bodyHandle); m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner; } diff --git a/Gems/PhysX/Code/Source/HingeJointComponent.cpp b/Gems/PhysX/Code/Source/HingeJointComponent.cpp index f275d32dc7..5edf1803c4 100644 --- a/Gems/PhysX/Code/Source/HingeJointComponent.cpp +++ b/Gems/PhysX/Code/Source/HingeJointComponent.cpp @@ -48,12 +48,24 @@ namespace PhysX JointComponent::LeadFollowerInfo leadFollowerInfo; ObtainLeadFollowerInfo(leadFollowerInfo); if (leadFollowerInfo.m_followerActor == nullptr || - leadFollowerInfo.m_leadBody == nullptr || leadFollowerInfo.m_followerBody == nullptr) { return; } + // if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle. + AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle; + if (leadFollowerInfo.m_leadBody != nullptr) + { + parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle; + } + else + { + AZ_TracePrintf( + "PhysX", "Entity [%s] Hinge Joint component missing lead entity. This joint will be a global constraint on the follower's global position.", + GetEntity()->GetName().c_str()); + } + HingeJointConfiguration configuration; configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation(); configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation(); @@ -66,7 +78,9 @@ namespace PhysX if (auto* sceneInterface = AZ::Interface::Get()) { m_jointHandle = sceneInterface->AddJoint( - leadFollowerInfo.m_followerBody->m_sceneOwner, &configuration, leadFollowerInfo.m_leadBody->m_bodyHandle, + leadFollowerInfo.m_followerBody->m_sceneOwner, + &configuration, + parentHandle, leadFollowerInfo.m_followerBody->m_bodyHandle); m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner; } diff --git a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp index 5b63a43966..3558c9fb56 100644 --- a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp +++ b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp @@ -190,8 +190,9 @@ namespace PhysX { { PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle); - if (!actorData.parentActor || !actorData.childActor) + if (actorData.parentActor == nullptr && actorData.childActor == nullptr) { + AZ_Warning("PhysX Joint", false, "CreateJoint failed - at least one body must be a PxRigidActor."); return nullptr; } @@ -239,7 +240,8 @@ namespace PhysX { { PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle); - if (!actorData.parentActor || !actorData.childActor) + //only check the child actor, as a null parent actor means this joint is a global constraint. + if (!actorData.childActor) { return nullptr; } @@ -252,7 +254,8 @@ namespace PhysX { { PHYSX_SCENE_READ_LOCK(actorData.childActor->getScene()); - joint = physx::PxFixedJointCreate(PxGetPhysics(), + joint = physx::PxFixedJointCreate( + PxGetPhysics(), actorData.parentActor, PxMathConvert(parentLocalTM), actorData.childActor, PxMathConvert(childLocalTM)); } @@ -272,7 +275,8 @@ namespace PhysX { { PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle); - if (!actorData.parentActor || !actorData.childActor) + // only check the child actor, as a null parent actor means this joint is a global constraint. + if (!actorData.childActor) { return nullptr; } @@ -306,7 +310,8 @@ namespace PhysX { { PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle); - if (!actorData.parentActor || !actorData.childActor) + // only check the child actor, as a null parent actor means this joint is a global constraint. + if (!actorData.childActor) { return nullptr; } diff --git a/Gems/PhysX/Code/Tests/PhysXJointsTest.cpp b/Gems/PhysX/Code/Tests/PhysXJointsTest.cpp index ff9cf11cca..ac5a99e29a 100644 --- a/Gems/PhysX/Code/Tests/PhysXJointsTest.cpp +++ b/Gems/PhysX/Code/Tests/PhysXJointsTest.cpp @@ -123,7 +123,7 @@ namespace PhysX const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); - EXPECT_TRUE(followerEndPosition.GetX() > followerPosition.GetX()); + EXPECT_GT(followerEndPosition.GetX(), followerPosition.GetX()); } TEST_F(PhysXJointsTest, Joint_HingeJoint_FollowerSwingsAroundLead) @@ -164,8 +164,8 @@ namespace PhysX const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); - EXPECT_TRUE(followerEndPosition.GetX() > followerPosition.GetX()); - EXPECT_TRUE(abs(followerEndPosition.GetZ()) > FLT_EPSILON); + EXPECT_GT(followerEndPosition.GetX(), followerPosition.GetX()); + EXPECT_GT(abs(followerEndPosition.GetZ()), FLT_EPSILON); } TEST_F(PhysXJointsTest, Joint_BallJoint_FollowerSwingsUpAboutLead) @@ -206,7 +206,65 @@ namespace PhysX const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); - EXPECT_TRUE(followerEndPosition.GetZ() > followerPosition.GetZ()); + EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ()); + } + + TEST_F(PhysXJointsTest, Joint_BallJoint_GlobalConstraint) + { + // Place an entity in the world with a rigid body, physx collider, and a ball joint components. + // Do not set a lead entity on the ball joint component. + // Set entity's initial velocity to 10 in the X and Y directions on the rigid body component. + // The entity should swing up on the global constraint. + + const AZ::Vector3 followerPosition(0.0f, 0.0f, -1.0f); + const AZ::Vector3 followerInitialLinearVelocity(10.0f, 10.0f, 0.0f); + + const AZ::Vector3 jointLocalPosition(0.0f, 0.0f, 2.0f); + const AZ::Quaternion jointLocalRotation = AZ::Quaternion::CreateRotationY(90.0f); + const AZ::Transform jointLocalTransform = AZ::Transform::CreateFromQuaternionAndTranslation(jointLocalRotation, jointLocalPosition); + + //we want a global constraint, so leave the lead entity unset. + auto jointConfig = AZStd::make_shared(); + jointConfig->m_localTransformFromFollower = jointLocalTransform; + + auto jointLimits = AZStd::make_shared(); + jointLimits->m_isLimited = false; + + auto followerEntity = AddBodyColliderEntity( + m_testSceneHandle, followerPosition, followerInitialLinearVelocity, jointConfig, nullptr, jointLimits); + + const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); + + EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ()); + } + + TEST_F(PhysXJointsTest, Joint_HingeJoint_GlobalConstraint) + { + // Place an entity in the world with a rigid body, physx collider, and a hinge joint components. + // Do not set a lead entity on the hinge joint component. + // Set entity's initial velocity to 10 in the X and Y directions on the rigid body component. + // The entity should swing up on the global constraint. + + const AZ::Vector3 followerPosition(0.0f, 0.0f, -1.0f); + const AZ::Vector3 followerInitialLinearVelocity(10.0f, 10.0f, 0.0f); + + const AZ::Vector3 jointLocalPosition(0.0f, 0.0f, 2.0f); + const AZ::Quaternion jointLocalRotation = AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 180.0f, 90.0f)); + const AZ::Transform jointLocalTransform = AZ::Transform::CreateFromQuaternionAndTranslation(jointLocalRotation, jointLocalPosition); + + // do not set the lead entity as that makes this a global constraint + auto jointConfig = AZStd::make_shared(); + jointConfig->m_localTransformFromFollower = jointLocalTransform; + + auto jointLimits = AZStd::make_shared(); + jointLimits->m_isLimited = false; + + auto followerEntity = AddBodyColliderEntity( + m_testSceneHandle, followerPosition, followerInitialLinearVelocity, jointConfig, nullptr, jointLimits); + + const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); + + EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ()); } // for some reason TYPED_TEST_CASE with the fixture is not working on Android + Linux From 252c268ffdf340ce43411f1b93c05a39eb92b35b Mon Sep 17 00:00:00 2001 From: jonawals Date: Mon, 16 Aug 2021 16:09:36 +0100 Subject: [PATCH 074/101] Fix corrupt merge. (#3142) * Further subdivide TIAF data by suite. * Key fix typo. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index 5445c1f955..e499b0303c 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -125,9 +125,6 @@ class PersistentStorage(ABC): self._historic_data[self.HISTORIC_SEQUENCES_KEY] = {} self._historic_data[self.HISTORIC_SEQUENCES_KEY][self._this_commit_hash] = self._last_commit_hash - # Test runs for this completed sequence - self._historic_data[self.PREVIOUS_TEST_RUNS_KEY] = test_runs - # Coverage data for this branch with open(self._unpacked_coverage_data_file, "r") as coverage_data: self._historic_data[self.COVERAGE_DATA_KEY] = coverage_data.read() From 4f2d4d00ec612a5a7a9ad946ebedf6d04841640c Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 08:40:27 -0700 Subject: [PATCH 075/101] Auto-completing the inserted text by pressing TAB within Editor's Console results in a silent crash Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CrySystem/XConsole.cpp | 57 ++++++++---------------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index ae07f86312..36443fb9ee 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -2873,7 +2873,7 @@ void CXConsole::Paste() ////////////////////////////////////////////////////////////////////////// int CXConsole::GetNumVars() { - return (int)m_mapVariables.size(); + return static_cast(m_mapVariables.size()); } ////////////////////////////////////////////////////////////////////////// @@ -3132,7 +3132,6 @@ char* CXConsole::GetCheatVarAt(uint32 nOffset) ////////////////////////////////////////////////////////////////////////// size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, const char* szPrefix) { - size_t i = 0; size_t iPrefixLen = szPrefix ? strlen(szPrefix) : 0; // variables @@ -3140,11 +3139,6 @@ size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, con ConsoleVariablesMap::const_iterator it, end = m_mapVariables.end(); for (it = m_mapVariables.begin(); it != end; ++it) { - if (i >= pszArray.size()) - { - break; - } - if (szPrefix) { if (_strnicmp(it->first, szPrefix, iPrefixLen) != 0) @@ -3158,9 +3152,7 @@ size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, con continue; } - pszArray[i] = it->first; - - i++; + pszArray.push_back(it->first); } } @@ -3169,11 +3161,6 @@ size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, con ConsoleCommandsMap::iterator it, end = m_mapCommands.end(); for (it = m_mapCommands.begin(); it != end; ++it) { - if (i >= pszArray.size()) - { - break; - } - if (szPrefix) { if (_strnicmp(it->first.c_str(), szPrefix, iPrefixLen) != 0) @@ -3187,25 +3174,18 @@ size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, con continue; } - pszArray[i] = it->first.c_str(); - - i++; + pszArray.push_back(it->first.c_str()); } } - if (i != 0) - { - std::sort(pszArray.begin(), pszArray.end()); - } - - return i; + std::sort(pszArray.begin(), pszArray.end()); + return pszArray.size(); } ////////////////////////////////////////////////////////////////////////// void CXConsole::FindVar(const char* substr) { AZStd::vector cmds; - cmds.resize(GetNumVars() + m_mapCommands.size()); size_t cmdCount = GetSortedVars(cmds); for (size_t i = 0; i < cmdCount; i++) @@ -3231,10 +3211,9 @@ const char* CXConsole::AutoComplete(const char* substr) // following code can be optimized AZStd::vector cmds; - cmds.resize(GetNumVars() + m_mapCommands.size()); size_t cmdCount = GetSortedVars(cmds); - size_t substrLen = strlen(substr); + size_t substrLen = substr ? strlen(substr) : 0; // If substring is empty return first command. if (substrLen == 0 && cmdCount > 0) @@ -3246,7 +3225,7 @@ const char* CXConsole::AutoComplete(const char* substr) for (size_t i = 0; i < cmdCount; i++) { const char* szCmd = cmds[i].data(); - size_t cmdlen = strlen(szCmd); + size_t cmdlen = cmds[i].size(); if (cmdlen >= substrLen && memcmp(szCmd, substr, substrLen) == 0) { if (substrLen == cmdlen) @@ -3267,7 +3246,7 @@ const char* CXConsole::AutoComplete(const char* substr) { const char* szCmd = cmds[i].data(); - size_t cmdlen = strlen(szCmd); + size_t cmdlen = cmds[i].size(); if (cmdlen >= substrLen && azstrnicmp(szCmd, substr, substrLen) == 0) { if (substrLen == cmdlen) @@ -3301,27 +3280,19 @@ void CXConsole::SetInputLine(const char* szLine) const char* CXConsole::AutoCompletePrev(const char* substr) { AZStd::vector cmds; - cmds.resize(GetNumVars() + m_mapCommands.size()); - size_t cmdCount = GetSortedVars(cmds); + GetSortedVars(cmds); // If substring is empty return last command. - if (strlen(substr) == 0 && cmds.size() > 0) + if (strlen(substr) == 0 && !cmds.empty()) { - return cmds[cmdCount - 1].data(); + return cmds.back().data(); } - for (unsigned int i = 0; i < cmdCount; i++) + for (const AZStd::string_view& cmd : cmds) { - if (azstricmp(substr, cmds[i].data()) == 0) + if (azstricmp(substr, cmd.data()) == 0) { - if (i > 0) - { - return cmds[i - 1].data(); - } - else - { - return cmds[0].data(); - } + return cmd.data(); } } return AutoComplete(substr); From 994403bfa018dd96e8494c5b57fa8ba08b849819 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 16 Aug 2021 11:56:50 -0500 Subject: [PATCH 076/101] Updated Radius Weight Modifier component name for consistency. Signed-off-by: Chris Galvan --- .../EditorRadiusWeightModifierComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp index 039255276c..219ab6acb9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp @@ -25,7 +25,7 @@ namespace AZ if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class( - "Radius Weight Modifier", "Modifies PostFX override factor based on proximity of an influencer against this entity's bounding sphere") + "PostFX Radius Weight Modifier", "Modifies PostFX override factor based on proximity of an influencer against this entity's bounding sphere") ->ClassElement(Edit::ClassElements::EditorData, "") ->Attribute(Edit::Attributes::Category, "Atom") ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") From e2b4d8e50249727294bfdd0856b0d935f311aaa2 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard <64656371+jcbhl@users.noreply.github.com> Date: Mon, 16 Aug 2021 10:13:24 -0700 Subject: [PATCH 077/101] Profiler: Runtime region name support (#2924) * Profiler: add support for runtime region names * Profiler: fix group name collisions * Profiler: use set of GroupRegionNames * Profiler: add comments + named constant Signed-off-by: Jacob Hilliard --- .../RHI/Code/Include/Atom/RHI/CpuProfiler.h | 16 +++++++++++ .../Code/Include/Atom/RHI/CpuProfilerImpl.h | 12 +++++++++ .../RHI/Code/Source/RHI/CpuProfilerImpl.cpp | 27 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h index 2248474820..3fedc99566 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h @@ -30,6 +30,12 @@ namespace AZ const char* const m_groupName = nullptr; const char* const m_regionName = nullptr; + + struct Hash + { + AZStd::size_t operator()(const GroupRegionName& name) const; + }; + bool operator==(const GroupRegionName& other) const; }; CachedTimeRegion() = default; @@ -95,6 +101,9 @@ namespace AZ virtual void SetProfilerEnabled(bool enabled) = 0; virtual bool IsProfilerEnabled() const = 0 ; + + //! Used by AZ_ATOM_PROFILE_DYNAMIC to create GroupRegionNames with known lifetimes. + virtual const CachedTimeRegion::GroupRegionName& InsertDynamicName(const char* groupName, const AZStd::string& regionName) = 0; }; } // namespace RPI @@ -120,3 +129,10 @@ namespace AZ #define AZ_ATOM_PROFILE_FUNCTION(groupName, regionName) \ AZ_TRACE_METHOD(); \ AZ_ATOM_PROFILE_TIME_GROUP_REGION(groupName, regionName) \ + +//! Macro that allows for region names to be submitted at runtime. Use sparingly - this acquires a lock and allocates new objects within a map. +#define AZ_ATOM_PROFILE_DYNAMIC(groupName, regionName) \ + static_assert(AZStd::is_convertible_v, "Runtime group names are not allowed, use a static string literal instead."); \ + const AZ::RHI::CachedTimeRegion::GroupRegionName& AZ_JOIN(groupRegionName, __LINE__) = \ + AZ::RHI::CpuProfiler::Get()->InsertDynamicName(groupName, regionName); \ + AZ::RHI::TimeRegion AZ_JOIN(timeRegion, __LINE__)(&AZ_JOIN(groupRegionName, __LINE__)); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h index 7d3b0c5b81..2e4ca67db8 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -114,9 +115,11 @@ namespace AZ bool IsContinuousCaptureInProgress() const final override; void SetProfilerEnabled(bool enabled) final override; bool IsProfilerEnabled() const final override; + const CachedTimeRegion::GroupRegionName& InsertDynamicName(const char* groupName, const AZStd::string& regionName) final override; private: static constexpr AZStd::size_t MaxFramesToSave = 2 * 60 * 120; // 2 minutes of 120fps + static constexpr AZStd::size_t MaxRegionStringPoolSize = 16384; // Max amount of unique strings to save in the pool before throwing warnings. // Lazily create and register the local thread data void RegisterThreadStorage(); @@ -129,6 +132,15 @@ namespace AZ AZStd::vector, AZ::OSStdAllocator> m_registeredThreads; AZStd::mutex m_threadRegisterMutex; + // Pool for GroupRegionNames that are generated at runtime through AZ_ATOM_PROFILE_DYNAMIC. Each unique + // combination of group name and region name submitted will be stored in this pool to emulate static lifetime. + AZStd::unordered_set m_dynamicGroupRegionNamePool; + + // String pool for storing region names submitted at runtime. Each call to AZ_ATOM_PROFILE_DYNAMIC will either construct + // a string in this pool or use an already-existing entry. + AZStd::unordered_set m_regionNameStringPool; + AZStd::mutex m_dynamicNameMutex; + // Thread local storage, gets lazily allocated when a thread is created static thread_local CpuTimingLocalStorage* ms_threadLocalStorage; diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index cdfd4ac469..d41b5d656e 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -74,6 +74,20 @@ namespace AZ { } + AZStd::size_t CachedTimeRegion::GroupRegionName::Hash::operator()(const CachedTimeRegion::GroupRegionName& name) const + { + AZStd::size_t seed = 0; + AZStd::hash_combine(seed, name.m_groupName); + AZStd::hash_combine(seed, name.m_regionName); + return seed; + } + + bool CachedTimeRegion::GroupRegionName::operator==(const GroupRegionName& other) const + { + return (m_groupName == other.m_groupName) && (m_regionName == other.m_regionName); + } + + // --- CpuProfilerImpl --- void CpuProfilerImpl::Init() @@ -218,6 +232,19 @@ namespace AZ return m_enabled; } + const CachedTimeRegion::GroupRegionName& CpuProfilerImpl::InsertDynamicName(const char* groupName, const AZStd::string& regionName) + { + AZStd::scoped_lock lock(m_dynamicNameMutex); + AZ_Warning("CpuProfiler", m_regionNameStringPool.size() < MaxRegionStringPoolSize, + "Stored dynamic region names are accumulating. Consider removing a AZ_ATOM_PROFILE_DYNAMIC invocation."); + auto [regionNameItr, wasRegionInserted] = m_regionNameStringPool.insert(regionName); + + CachedTimeRegion::GroupRegionName newGroupRegionName(groupName, regionNameItr->c_str()); + auto [groupRegionNameItr, wasGroupRegionInserted] = m_dynamicGroupRegionNamePool.insert(newGroupRegionName); + + return *groupRegionNameItr; + } + void CpuProfilerImpl::OnSystemTick() { if (!m_enabled) From 1c7f71f93a5bd42700f7f750d97ce50424048b13 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 16 Aug 2021 12:13:32 -0500 Subject: [PATCH 078/101] Updated Atom automated test that uses the PostFX Radius Weight Modifier. Signed-off-by: Chris Galvan --- ...ydra_AtomEditorComponents_AddedToEntity.py | 4 +-- .../atom_renderer/test_Atom_MainSuite.py | 26 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py index b4031d2ffa..cd10caf57b 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py @@ -206,8 +206,8 @@ def run(): # PostFX Layer Component ComponentTests("PostFX Layer") - # Radius Weight Modifier Component - ComponentTests("Radius Weight Modifier") + # PostFX Radius Weight Modifier Component + ComponentTests("PostFX Radius Weight Modifier") # Light Component ComponentTests("Light") diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py index be75801b63..55c049b929 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py @@ -32,7 +32,7 @@ class TestAtomEditorComponentsMain(object): Tests the following Atom components and verifies all "expected_lines" appear in Editor.log: 1. Display Mapper 2. Light - 3. Radius Weight Modifier + 3. PostFX Radius Weight Modifier 4. PostFX Layer 5. Physical Sky 6. Global Skylight (IBL) @@ -126,18 +126,18 @@ class TestAtomEditorComponentsMain(object): "PostFX Layer_test: Entity deleted: True", "PostFX Layer_test: UNDO entity deletion works: True", "PostFX Layer_test: REDO entity deletion works: True", - # Radius Weight Modifier Component - "Radius Weight Modifier Entity successfully created", - "Radius Weight Modifier_test: Component added to the entity: True", - "Radius Weight Modifier_test: Component removed after UNDO: True", - "Radius Weight Modifier_test: Component added after REDO: True", - "Radius Weight Modifier_test: Entered game mode: True", - "Radius Weight Modifier_test: Exit game mode: True", - "Radius Weight Modifier_test: Entity is hidden: True", - "Radius Weight Modifier_test: Entity is shown: True", - "Radius Weight Modifier_test: Entity deleted: True", - "Radius Weight Modifier_test: UNDO entity deletion works: True", - "Radius Weight Modifier_test: REDO entity deletion works: True", + # PostFX Radius Weight Modifier Component + "PostFX Radius Weight Modifier Entity successfully created", + "PostFX Radius Weight Modifier_test: Component added to the entity: True", + "PostFX Radius Weight Modifier_test: Component removed after UNDO: True", + "PostFX Radius Weight Modifier_test: Component added after REDO: True", + "PostFX Radius Weight Modifier_test: Entered game mode: True", + "PostFX Radius Weight Modifier_test: Exit game mode: True", + "PostFX Radius Weight Modifier_test: Entity is hidden: True", + "PostFX Radius Weight Modifier_test: Entity is shown: True", + "PostFX Radius Weight Modifier_test: Entity deleted: True", + "PostFX Radius Weight Modifier_test: UNDO entity deletion works: True", + "PostFX Radius Weight Modifier_test: REDO entity deletion works: True", # Light Component "Light Entity successfully created", "Light_test: Component added to the entity: True", From b88a7faf642e102282b45021d91ea50d7ef18cc3 Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Mon, 16 Aug 2021 10:18:45 -0700 Subject: [PATCH 079/101] Fixed issues with blend shape animations (#3080) Duplicate blend shape animations are now handled correctly. Invalid animation targets are now an error instead of a crash in the builder. Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- .../SDKWrapper/AssImpSceneWrapper.cpp | 3 + .../Importers/AssImpAnimationImporter.cpp | 32 ++++++- .../Importers/AssImpBlendShapeImporter.cpp | 87 ++++++++++++++++--- 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp index 0680b41eca..12aefca00c 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp @@ -70,6 +70,9 @@ namespace AZ // This results in the loss of the offset matrix data for nodes without a mesh which is required for the Transform Importer. m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false); m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, false); + // The remove empty bones flag is on by default, but doesn't do anything internal to AssImp right now. + // This is here as a bread crumb to save others times investigating issues with empty bones. + // m_importer.SetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, false); m_sceneFileName = fileName; m_assImpScene = m_importer.ReadFile(fileName, aiProcess_Triangulate //Triangulates all faces of all meshes diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp index 150a50138e..97b5960a8d 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -147,7 +147,9 @@ namespace AZ SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(5); // [LYN-4226] Invert PostRotation matrix in animation chains + // Revision 5: [LYN-4226] Invert PostRotation matrix in animation chains + // Revision 6: Handle duplicate blend shape animations + serializeContext->Class()->Version(6); } } @@ -631,6 +633,15 @@ namespace AZ for (const auto& [meshIdx, keys] : valueToKeyDataMap) { + + if (static_cast(meshIdx) >= mesh->mNumAnimMeshes) + { + AZ_Error( + "AnimationImporter", false, + "Mesh %s has an animation mesh index reference of %d, but only has %d animation meshes. Skipping importing this. This is an error in the source scene file that should be corrected.", + mesh->mName.C_Str(), meshIdx, mesh->mNumAnimMeshes); + continue; + } AZStd::shared_ptr morphAnimNode = AZStd::make_shared(); @@ -656,12 +667,29 @@ namespace AZ morphAnimNode->AddKeyFrame(weight); } + // Some DCC tools, like Maya, include a full path separated by '.' in the node names. + // For example, "cone_skin_blendShapeNode.cone_squash" + // Downstream processing doesn't want anything but the last part of that node name, + // so find the last '.' and remove anything before it. const size_t dotIndex = nodeName.find_last_of('.'); nodeName = nodeName.substr(dotIndex + 1); morphAnimNode->SetBlendShapeName(nodeName.data()); - AZStd::string animNodeName(AZStd::string::format("%s_%s", s_animationNodeName, nodeName.data())); + // Duplicates can exist if an anim mesh had a name with a suffix like .001, in that case + // AssImp will strip off that suffix. Note that this behavior is separate from the + // scan for a period in the node name that came before this. + AZStd::string originalNodeName(AZStd::string::format("%s_%s", s_animationNodeName, nodeName.data())); + AZStd::string animNodeName(originalNodeName); + if (RenamedNodesMap::SanitizeNodeName( + animNodeName, context.m_scene.GetGraph(), context.m_currentGraphPosition, originalNodeName.c_str())) + { + AZ_Warning( + "AnimationImporter", false, + "Duplicate animations were found with the name %s on mesh %s. The duplicate will be named %s.", + originalNodeName.c_str(), mesh->mName.C_Str(), animNodeName.c_str()); + } + Containers::SceneGraph::NodeIndex addNode = context.m_scene.GetGraph().AddChild( context.m_currentGraphPosition, animNodeName.c_str(), AZStd::move(morphAnimNode)); context.m_scene.GetGraph().MakeEndPoint(addNode); diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp index e8eb5ecf68..8e447f9d79 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp @@ -40,7 +40,9 @@ namespace AZ SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(3); // LYN-2576 + // Revision 3: Fixed an issue where jack.fbx was failing to process + // Revision 4: Handle duplicate blend shape animations + serializeContext->Class()->Version(4); } } @@ -80,7 +82,32 @@ namespace AZ // AssImp separates meshes that have multiple materials. // This code re-combines them to match previous FBX SDK behavior, // so they can be separated by engine code instead. - AZStd::map>> animToMeshToAnimMeshIndices; + // Can't de-dupe nodes in the first loop because we can't generate names until we create nodes later. + // Because meshes are split on material at this point and need to be recombined, we can be in a position where + // There is a legit duped anim mesh that needs to be combined based on the outer non-anim mesh, + // or this is a duplicately named anim mesh that needs to be de-duped. There is also the case where both are true, + // it's a duplicate name and the non-anim mesh has to be deduped. + + // Helper struct to track an anim mesh and its associated mesh. + struct AnimMeshAndSceneMeshIndex + { + AnimMeshAndSceneMeshIndex(const aiAnimMesh* aiAnimMesh, const aiMesh* aiMesh) + : m_aiAnimMesh(aiAnimMesh) + , m_aiMesh(aiMesh) + { + } + const aiAnimMesh* m_aiAnimMesh = nullptr; + const aiMesh* m_aiMesh = nullptr; + }; + + // Helper struct to track all anim meshes at an index for all scene meshes. + struct AnimMeshAndSceneMeshes + { + AZStd::vector m_animMeshAndSceneMeshIndex; + }; + + // Map the animation index to the list of anim meshes at that index, and the mesh associated with those anim meshes. + AZStd::map animMeshIndexToSceneMeshes; for (int nodeMeshIdx = 0; nodeMeshIdx < numMesh; nodeMeshIdx++) { int sceneMeshIdx = context.m_sourceNode.GetAssImpNode()->mMeshes[nodeMeshIdx]; @@ -88,20 +115,57 @@ namespace AZ for (unsigned int animIdx = 0; animIdx < aiMesh->mNumAnimMeshes; animIdx++) { aiAnimMesh* aiAnimMesh = aiMesh->mAnimMeshes[animIdx]; - animToMeshToAnimMeshIndices[aiAnimMesh->mName.C_Str()].emplace_back(nodeMeshIdx, animIdx); + + // This code executes if: + // A mesh in the FBX file had multiple materials and blend shapes. + // This means that AssImp splits that mesh to one material per mesh. + // AssImp creates a set of anim meshes for each mesh based on that split. + // This verifies that those anim mesh arrays are in the same order across all split meshes, if it fails + // it means this logic needs to be updated, but it also catches that here earlier in an obvious way, + // instead of failing later in a harder to track way. + if (animMeshIndexToSceneMeshes.contains(animIdx)) + { + const AnimMeshAndSceneMeshIndex& firstExistingAnim( + animMeshIndexToSceneMeshes[animIdx].m_animMeshAndSceneMeshIndex[0]); + if (strcmp( + firstExistingAnim.m_aiAnimMesh->mName.C_Str(), + aiAnimMesh->mName.C_Str()) != 0) + { + AZ_Error( + Utilities::ErrorWindow, false, + "Meshes %s and %s on node %s have mismatched animations %s and %s at index %d. This can be resolved by " + "either manually separating meshes by material in the source scene file, or by updating this logic to " + "handle out of order animation indices.", + firstExistingAnim.m_aiMesh->mName.C_Str(), + aiMesh->mName.C_Str(), + context.m_sourceNode.GetName(), + firstExistingAnim.m_aiAnimMesh->mName.C_Str(), + aiAnimMesh->mName.C_Str(), animIdx); + return Events::ProcessingResult::Failure; + } + } + + animMeshIndexToSceneMeshes[animIdx].m_animMeshAndSceneMeshIndex.emplace_back( + AnimMeshAndSceneMeshIndex(aiAnimMesh, aiMesh)); } } - for (const auto& animToMeshIndex : animToMeshToAnimMeshIndices) + for (const auto& animMeshToSceneMeshes : animMeshIndexToSceneMeshes) { AZStd::shared_ptr blendShapeData = AZStd::make_shared(); + if (animMeshToSceneMeshes.second.m_animMeshAndSceneMeshIndex.size() == 0) + { + AZ_Error(Utilities::ErrorWindow, false, "Blend shape animations were expected but missing on node %s.", + context.m_sourceNode.GetName()); + return Events::ProcessingResult::Failure; + } // Some DCC tools, like Maya, include a full path separated by '.' in the node names. // For example, "cone_skin_blendShapeNode.cone_squash" // Downstream processing doesn't want anything but the last part of that node name, // so find the last '.' and remove anything before it. - AZStd::string nodeName(animToMeshIndex.first); + AZStd::string nodeName(animMeshToSceneMeshes.second.m_animMeshAndSceneMeshIndex[0].m_aiAnimMesh->mName.C_Str()); size_t dotIndex = nodeName.rfind('.'); if (dotIndex != AZStd::string::npos) { @@ -109,12 +173,11 @@ namespace AZ } int vertexOffset = 0; RenamedNodesMap::SanitizeNodeName(nodeName, context.m_scene.GetGraph(), context.m_currentGraphPosition, "BlendShape"); - AZ_TraceContext("Blend shape name", nodeName); - for (const auto& meshIndex : animToMeshIndex.second) + + for (const auto& animMeshAndSceneIndex : animMeshToSceneMeshes.second.m_animMeshAndSceneMeshIndex) { - int sceneMeshIdx = context.m_sourceNode.GetAssImpNode()->mMeshes[meshIndex.first]; - const aiMesh* aiMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[sceneMeshIdx]; - const aiAnimMesh* aiAnimMesh = aiMesh->mAnimMeshes[meshIndex.second]; + const aiAnimMesh* aiAnimMesh = animMeshAndSceneIndex.m_aiAnimMesh; + const aiMesh* aiMesh = animMeshAndSceneIndex.m_aiMesh; AZStd::bitset uvSetUsedFlags; for (AZ::u8 uvSetIndex = 0; uvSetIndex < SceneData::GraphData::BlendShapeData::MaxNumUVSets; ++uvSetIndex) @@ -199,6 +262,7 @@ namespace AZ face.mNumIndices); continue; } + for (unsigned int idx = 0; idx < face.mNumIndices; ++idx) { blendFace.vertexIndex[idx] = face.mIndices[idx] + vertexOffset; @@ -207,11 +271,8 @@ namespace AZ blendShapeData->AddFace(blendFace); } vertexOffset += aiMesh->mNumVertices; - - } - // Report problem if no vertex or face converted to MeshData if (blendShapeData->GetVertexCount() <= 0 || blendShapeData->GetFaceCount() <= 0) { From d6b268e84e54b3d606e129bf346010b88be4b1ba Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Mon, 16 Aug 2021 12:41:24 -0500 Subject: [PATCH 080/101] Remove ResourceSelectorHost and clean up/refactor related bits (#3050) * Sever dependency on legacy resource selector host Audio resource selectors (browse dialogs) no longer need to be registered with the legacy IResourceSelectorHost system. Set up a new EBus specifically to handle browse button presses and directly invokes the dialog. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Hook up legacy audio control selector to new EBus Remaining use of legacy audio selectors (trackview) need to be able to bypass ResourceSelectorHost now. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Removes ResourceSelectorHost and legacy selectors This removes various Variable types that were tied to resource selectors, such as GeomCache, Model, Animation, File. Removes the ResourceSelectorHost completely. The two things that still appeared to have selectors in TrackView are Audio Controls and Texture. Fixed the audio control selector to work via EBus and the Texture selector didn't seem to work at all, but left it in as it was. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Make the default audio selector return old value Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Fix some signed/unsigned comparison warnings Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Remove deleted function from Editor Mock Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Change audio selector api to use string_view Per feedback. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../ReflectedPropertyControl/PropertyCtrl.cpp | 3 - .../PropertyGenericCtrl.cpp | 10 -- .../PropertyGenericCtrl.h | 10 -- .../PropertyResourceCtrl.cpp | 78 ++++----- .../ReflectedPropertiesPanel.cpp | 93 ---------- .../ReflectedPropertiesPanel.h | 46 ----- .../ReflectedPropertyItem.cpp | 10 -- .../ReflectedPropertyControl/ReflectedVar.cpp | 14 -- .../ReflectedPropertyControl/ReflectedVar.h | 25 --- .../ReflectedVarWrapper.cpp | 21 +-- .../ReflectedVarWrapper.h | 14 -- Code/Editor/EditorPanelUtils.cpp | 4 +- Code/Editor/IEditor.h | 2 - Code/Editor/IEditorImpl.cpp | 2 - Code/Editor/IEditorImpl.h | 2 - Code/Editor/IEditorPanelUtils.h | 2 +- Code/Editor/Include/IResourceSelectorHost.h | 135 --------------- Code/Editor/Lib/Tests/IEditorMock.h | 1 - .../ComponentEntityEditorPlugin.cpp | 3 - .../SandboxIntegration.cpp | 11 -- .../SandboxIntegration.h | 1 - Code/Editor/ResourceSelectorHost.cpp | 163 ------------------ Code/Editor/ResourceSelectorHost.h | 18 -- Code/Editor/Util/Variable.cpp | 2 +- Code/Editor/Util/Variable.h | 6 - Code/Editor/Util/VariablePropertyType.cpp | 33 ---- Code/Editor/Util/VariablePropertyType.h | 6 - Code/Editor/editor_lib_files.cmake | 8 - .../API/ToolsApplicationAPI.h | 3 - .../UI/PropertyEditor/PropertyAudioCtrl.cpp | 19 +- .../UI/PropertyEditor/PropertyAudioCtrl.h | 21 +++ .../PropertyEditor/PropertyAudioCtrlTypes.h | 10 +- .../Editor/ATLControlsResourceDialog.cpp | 2 + .../Editor/AudioControlsEditorPlugin.cpp | 3 - .../Source/Editor/AudioControlsEditorPlugin.h | 4 +- .../Source/Editor/AudioResourceSelectors.cpp | 105 ++++------- .../Source/Editor/AudioResourceSelectors.h | 11 +- 37 files changed, 125 insertions(+), 776 deletions(-) delete mode 100644 Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp delete mode 100644 Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h delete mode 100644 Code/Editor/Include/IResourceSelectorHost.h delete mode 100644 Code/Editor/ResourceSelectorHost.cpp delete mode 100644 Code/Editor/ResourceSelectorHost.h diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp index bf87f2017d..c228fbda09 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp @@ -10,7 +10,6 @@ // Editor #include "PropertyCtrl.h" -#include "PropertyAnimationCtrl.h" #include "PropertyResourceCtrl.h" #include "PropertyGenericCtrl.h" #include "PropertyMiscCtrl.h" @@ -22,9 +21,7 @@ void RegisterReflectedVarHandlers() if (!registered) { registered = true; - EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew AnimationPropertyWidgetHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FileResourceSelectorWidgetHandler()); - EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ReverbPresetPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequencePropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequenceIdPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler()); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp index a2c66b8b10..8ff83dd894 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp @@ -73,16 +73,6 @@ void GenericPopupPropertyEditor::SetPropertyType(PropertyType type) m_propertyType = type; } -void ReverbPresetPropertyEditor::onEditClicked() -{ - CSelectEAXPresetDlg PresetDlg(this); - PresetDlg.SetCurrPreset(GetValue()); - if (PresetDlg.exec() == QDialog::Accepted) - { - SetValue(PresetDlg.GetCurrPreset()); - } -} - void SequencePropertyEditor::onEditClicked() { CSelectSequenceDialog gtDlg(this); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h index 2296773f0a..b6b14cf125 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h @@ -96,15 +96,6 @@ public: } }; -class ReverbPresetPropertyEditor - : public GenericPopupPropertyEditor -{ -public: - ReverbPresetPropertyEditor(QWidget* pParent = nullptr) - : GenericPopupPropertyEditor(pParent){} - void onEditClicked() override; -}; - class MissionObjPropertyEditor : public GenericPopupPropertyEditor { @@ -155,7 +146,6 @@ public: // So we use our own #define CONST_AZ_CRC(name, value) AZ::u32(value) -using ReverbPresetPropertyHandler = GenericPopupWidgetHandler; using MissionObjPropertyHandler = GenericPopupWidgetHandler; using SequencePropertyHandler = GenericPopupWidgetHandler; using SequenceIdPropertyHandler = GenericPopupWidgetHandler; diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp index d3ae6aaecf..c5ccc599d6 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp @@ -17,9 +17,9 @@ // AzToolsFramework #include #include +#include // Editor -#include "IResourceSelectorHost.h" #include "Controls/QToolTipWidget.h" #include "Controls/BitmapToolTip.h" @@ -35,8 +35,8 @@ BrowseButton::BrowseButton(PropertyType type, QWidget* parent /*= nullptr*/) void BrowseButton::SetPathAndEmit(const QString& path) { - //only emit if path changes, except for ePropertyGeomCache. Old property control - if (path != m_path || m_propertyType == ePropertyGeomCache) + //only emit if path changes. Old property control + if (path != m_path) { m_path = path; emit PathChanged(m_path); @@ -78,21 +78,6 @@ private: // Filters for texture. selection = AssetSelectionModel::AssetGroupSelection("Texture"); } - else if (m_propertyType == ePropertyModel) - { - // Filters for models. - selection = AssetSelectionModel::AssetGroupSelection("Geometry"); - } - else if (m_propertyType == ePropertyGeomCache) - { - // Filters for geom caches. - selection = AssetSelectionModel::AssetTypeSelection("Geom Cache"); - } - else if (m_propertyType == ePropertyFile) - { - // Filters for files. - selection = AssetSelectionModel::AssetTypeSelection("File"); - } else { return; @@ -106,14 +91,7 @@ private: switch (m_propertyType) { case ePropertyTexture: - case ePropertyModel: newPath.replace("\\\\", "/"); - } - switch (m_propertyType) - { - case ePropertyTexture: - case ePropertyModel: - case ePropertyFile: if (newPath.size() > MAX_PATH) { newPath.resize(MAX_PATH); @@ -125,26 +103,51 @@ private: } }; -class ResourceSelectorButton +class AudioControlSelectorButton : public BrowseButton { public: - AZ_CLASS_ALLOCATOR(ResourceSelectorButton, AZ::SystemAllocator, 0); + AZ_CLASS_ALLOCATOR(AudioControlSelectorButton, AZ::SystemAllocator, 0); - ResourceSelectorButton(PropertyType type, QWidget* pParent = nullptr) + AudioControlSelectorButton(PropertyType type, QWidget* pParent = nullptr) : BrowseButton(type, pParent) { - setToolTip(tr("Select resource")); + setToolTip(tr("Select Audio Control")); } private: void OnClicked() override { - SResourceSelectorContext x; - x.parentWidget = this; - x.typeName = Prop::GetPropertyTypeToResourceType(m_propertyType); - QString newPath = GetIEditor()->GetResourceSelectorHost()->SelectResource(x, m_path); - SetPathAndEmit(newPath); + AZStd::string resourceResult; + auto ConvertLegacyAudioPropertyType = [](const PropertyType type) -> AzToolsFramework::AudioPropertyType + { + switch (type) + { + case ePropertyAudioTrigger: + return AzToolsFramework::AudioPropertyType::Trigger; + case ePropertyAudioRTPC: + return AzToolsFramework::AudioPropertyType::Rtpc; + case ePropertyAudioSwitch: + return AzToolsFramework::AudioPropertyType::Switch; + case ePropertyAudioSwitchState: + return AzToolsFramework::AudioPropertyType::SwitchState; + case ePropertyAudioEnvironment: + return AzToolsFramework::AudioPropertyType::Environment; + case ePropertyAudioPreloadRequest: + return AzToolsFramework::AudioPropertyType::Preload; + default: + return AzToolsFramework::AudioPropertyType::NumTypes; + } + }; + + auto propType = ConvertLegacyAudioPropertyType(m_propertyType); + if (propType != AzToolsFramework::AudioPropertyType::NumTypes) + { + AzToolsFramework::AudioControlSelectorRequestBus::EventResult( + resourceResult, propType, &AzToolsFramework::AudioControlSelectorRequestBus::Events::SelectResource, + AZStd::string_view{ m_path.toUtf8().constData() }); + SetPathAndEmit(QString{ resourceResult.c_str() }); + } } }; @@ -235,18 +238,13 @@ void FileResourceSelectorWidget::SetPropertyType(PropertyType type) AddButton(new TextureEditButton); m_previewToolTip.reset(new CBitmapToolTip); break; - case ePropertyModel: - case ePropertyGeomCache: case ePropertyAudioTrigger: case ePropertyAudioSwitch: case ePropertyAudioSwitchState: case ePropertyAudioRTPC: case ePropertyAudioEnvironment: case ePropertyAudioPreloadRequest: - AddButton(new ResourceSelectorButton(type)); - break; - case ePropertyFile: - AddButton(new FileBrowseButton(type)); + AddButton(new AudioControlSelectorButton(type)); break; default: break; diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp deleted file mode 100644 index 8651db7e96..0000000000 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp +++ /dev/null @@ -1,93 +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 - * - */ - - -// Description : implementation file - -#include "EditorDefs.h" - -#include "ReflectedPropertiesPanel.h" - -///////////////////////////////////////////////////////////////////////////// -// ReflectedPropertiesPanel dialog - - -ReflectedPropertiesPanel::ReflectedPropertiesPanel(QWidget* pParent) - : ReflectedPropertyControl(pParent) -{ -} - -////////////////////////////////////////////////////////////////////////// -void ReflectedPropertiesPanel::DeleteVars() -{ - ClearVarBlock(); - m_updateCallbacks.clear(); - m_varBlock = nullptr; -} - -////////////////////////////////////////////////////////////////////////// -void ReflectedPropertiesPanel::SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category) -{ - assert(vb); - - m_varBlock = vb; - - RemoveAllItems(); - m_varBlock = vb; - AddVarBlock(m_varBlock, category); - - SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1)); - - // When new object set all previous callbacks freed. - m_updateCallbacks.clear(); - if (updCallback) - { - stl::push_back_unique(m_updateCallbacks, updCallback); - } -} - -////////////////////////////////////////////////////////////////////////// -void ReflectedPropertiesPanel::AddVars(CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category) -{ - assert(vb); - - bool bNewBlock = false; - // Make a clone of properties. - if (!m_varBlock) - { - RemoveAllItems(); - m_varBlock = vb->Clone(true); - AddVarBlock(m_varBlock, category); - bNewBlock = true; - } - m_varBlock->Wire(vb); - - if (bNewBlock) - { - SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1)); - - // When new object set all previous callbacks freed. - m_updateCallbacks.clear(); - } - - if (updCallback) - { - stl::push_back_unique(m_updateCallbacks, updCallback); - } -} - -void ReflectedPropertiesPanel::OnPropertyChanged(IVariable* pVar) -{ - std::list::iterator iter; - for (iter = m_updateCallbacks.begin(); iter != m_updateCallbacks.end(); ++iter) - { - (*iter)->operator()(pVar); - } -} - - diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h deleted file mode 100644 index cd551c63e2..0000000000 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h +++ /dev/null @@ -1,46 +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 - * - */ - -#ifndef CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H -#define CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H - -#pragma once - -#include "Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.h" -#include "Util/Variable.h" - -///////////////////////////////////////////////////////////////////////////// -// ReflectedPropertiesPanel dialog - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -//This class is a port of ReflectedPropertiesPanel to use the ReflectedPropertyControl -class SANDBOX_API ReflectedPropertiesPanel - : public ReflectedPropertyControl -{ -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - ReflectedPropertiesPanel(QWidget* pParent = nullptr); // standard constructor - - void DeleteVars(); - void AddVars(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr); - - void SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr); - -protected: - void OnPropertyChanged(IVariable* pVar); - -protected: - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - TSmartPtr m_varBlock; - - std::list m_updateCallbacks; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - - -#endif // CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp index 5a9d61be42..303f86d270 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp @@ -255,9 +255,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) case ePropertySelection: m_reflectedVarAdapter = new ReflectedVarEnumAdapter; break; - case ePropertyAnimation: - m_reflectedVarAdapter = new ReflectedVarAnimationAdapter; - break; case ePropertyColor: m_reflectedVarAdapter = new ReflectedVarColorAdapter; break; @@ -265,7 +262,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) m_reflectedVarAdapter = new ReflectedVarUserAdapter; break; case ePropertyEquip: - case ePropertyReverbPreset: case ePropertyGameToken: case ePropertyMissionObj: case ePropertySequence: @@ -276,15 +272,12 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) m_reflectedVarAdapter = new ReflectedVarGenericPropertyAdapter(desc.m_type); break; case ePropertyTexture: - case ePropertyModel: - case ePropertyGeomCache: case ePropertyAudioTrigger: case ePropertyAudioSwitch: case ePropertyAudioSwitchState: case ePropertyAudioRTPC: case ePropertyAudioEnvironment: case ePropertyAudioPreloadRequest: - case ePropertyFile: m_reflectedVarAdapter = new ReflectedVarResourceAdapter; break; case ePropertyFloatCurve: @@ -569,7 +562,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo break; case ePropertyTexture: - case ePropertyModel: value.replace('\\', '/'); break; } @@ -578,8 +570,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo switch (m_type) { case ePropertyTexture: - case ePropertyModel: - case ePropertyFile: if (value.length() >= MAX_PATH) { value = value.left(MAX_PATH); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp index 5b9c5b8063..263c17a8bb 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp @@ -31,12 +31,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext) ->Field("description", &CReflectedVar::m_description) ->Field("varName", &CReflectedVar::m_varName); - serializeContext->Class () - ->Version(1) - ->Field("animation", &CReflectedVarAnimation::m_animation) - ->Field("entityID", &CReflectedVarAnimation::m_entityID) - ; - serializeContext->Class () ->Version(1) ->Field("path", &CReflectedVarResource::m_path) @@ -76,12 +70,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext) AZ::EditContext* ec = serializeContext->GetEditContext(); if (ec) { - ec->Class< CReflectedVarAnimation >("VarAnimation", "Animation") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarAnimation::varName) - ->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarAnimation::description) - ; - ec->Class< CReflectedVarResource >("VarResource", "Resource") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarResource::varName) @@ -284,8 +272,6 @@ AZ::u32 CReflectedVarGenericProperty::handler() return AZ_CRC("ePropertyShader", 0xc40932f1); case ePropertyEquip: return AZ_CRC("ePropertyEquip", 0x66ffd290); - case ePropertyReverbPreset: - return AZ_CRC("ePropertyReverbPreset", 0x51469f38); case ePropertyDeprecated0: return AZ_CRC("ePropertyCustomAction", 0x4ffa5ba5); case ePropertyGameToken: diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h index 634f2efd3a..a15f8326d1 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h @@ -265,32 +265,8 @@ public: AZ::Vector3 m_color; }; -//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION ) -class CReflectedVarAnimation - : public CReflectedVar -{ -public: - AZ_RTTI(CReflectedVarAnimation, "{635D982E-23EC-463F-8F33-4FC2C19D5673}", CReflectedVar) - - CReflectedVarAnimation(const AZStd::string& name) - : CReflectedVar(name) - , m_entityID(0) - {} - CReflectedVarAnimation() - : m_entityID(0){} - - AZStd::string varName() const { return m_varName; } - AZStd::string description() const { return m_description; } - - AZStd::string m_animation; - AZ::EntityId m_entityID; -}; - //Class to hold: // ePropertyTexture (IVariable::DT_TEXTURE) -// ePropertyMaterial (IVariable::DT_MATERIAL) -// ePropertyModel (IVariable::DT_OBJECT) -// ePropertyGeomCache (IVariable::DT_GEOM_CACHE) // ePropertyAudioTrigger (IVariable::DT_AUDIO_TRIGGER) // ePropertyAudioSwitch (IVariable::DT_AUDIO_SWITCH ) // ePropertyAudioSwitchState (IVariable::DT_AUDIO_SWITCH_STATE) @@ -344,7 +320,6 @@ public: AZStd::vector m_itemDescriptions; }; -//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION ) class CReflectedVarSpline : public CReflectedVar { diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp index 5639fa95b0..aba346ce6a 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp @@ -392,25 +392,6 @@ void ReflectedVarColorAdapter::SyncIVarToReflectedVar(IVariable *pVariable) -void ReflectedVarAnimationAdapter::SetVariable(IVariable *pVariable) -{ - m_reflectedVar.reset(new CReflectedVarAnimation(pVariable->GetHumanName().toUtf8().data())); - m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data(); -} - -void ReflectedVarAnimationAdapter::SyncReflectedVarToIVar(IVariable *pVariable) -{ - m_reflectedVar->m_entityID = static_cast(pVariable->GetUserData().value()); - m_reflectedVar->m_animation = pVariable->GetDisplayValue().toUtf8().data(); -} - -void ReflectedVarAnimationAdapter::SyncIVarToReflectedVar(IVariable *pVariable) -{ - pVariable->SetUserData(static_cast(m_reflectedVar->m_entityID)); - pVariable->SetDisplayValue(m_reflectedVar->m_animation.c_str()); - -} - void ReflectedVarResourceAdapter::SetVariable(IVariable *pVariable) { m_reflectedVar.reset(new CReflectedVarResource(pVariable->GetHumanName().toUtf8().data())); @@ -429,7 +410,7 @@ void ReflectedVarResourceAdapter::SyncReflectedVarToIVar(IVariable *pVariable) void ReflectedVarResourceAdapter::SyncIVarToReflectedVar(IVariable *pVariable) { - const bool bForceModified = (m_reflectedVar->m_propertyType == ePropertyGeomCache); + const bool bForceModified = false; pVariable->SetForceModified(bForceModified); pVariable->SetDisplayValue(m_reflectedVar->m_path.c_str()); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h index 07bb72413a..9c49f1ae1a 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h @@ -218,20 +218,6 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING }; -class EDITOR_CORE_API ReflectedVarAnimationAdapter - : public ReflectedVarAdapter -{ -public: - void SetVariable(IVariable* pVariable) override; - void SyncReflectedVarToIVar(IVariable* pVariable) override; - void SyncIVarToReflectedVar(IVariable* pVariable) override; - CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); } -private: -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - QScopedPointer m_reflectedVar; -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - class EDITOR_CORE_API ReflectedVarResourceAdapter : public ReflectedVarAdapter { diff --git a/Code/Editor/EditorPanelUtils.cpp b/Code/Editor/EditorPanelUtils.cpp index b19bde4583..12e9457474 100644 --- a/Code/Editor/EditorPanelUtils.cpp +++ b/Code/Editor/EditorPanelUtils.cpp @@ -130,7 +130,7 @@ public: HotKey_BuildDefaults(); for (QPair key : keys) { - for (unsigned int j = 0; j < hotkeys.count(); j++) + for (int j = 0; j < hotkeys.count(); j++) { if (hotkeys[j].path.compare(key.first, Qt::CaseInsensitive) == 0) { @@ -256,7 +256,7 @@ public: hotkey.second = settings.value("keySequence").toString(); if (!hotkey.first.isEmpty()) { - for (unsigned int j = 0; j < hotkeys.count(); j++) + for (int j = 0; j < hotkeys.count(); j++) { if (hotkeys[j].path.compare(hotkey.first, Qt::CaseInsensitive) == 0) { diff --git a/Code/Editor/IEditor.h b/Code/Editor/IEditor.h index f66dca412e..7d0fc653fa 100644 --- a/Code/Editor/IEditor.h +++ b/Code/Editor/IEditor.h @@ -68,7 +68,6 @@ class CDisplaySettings; struct SGizmoParameters; class CLevelIndependentFileMan; class CSelectionTreeManager; -struct IResourceSelectorHost; struct SEditorSettings; class CGameExporter; class IAWSResourceManager; @@ -714,7 +713,6 @@ struct IEditor virtual ESystemConfigSpec GetEditorConfigSpec() const = 0; virtual ESystemConfigPlatform GetEditorConfigPlatform() const = 0; virtual void ReloadTemplates() = 0; - virtual IResourceSelectorHost* GetResourceSelectorHost() = 0; virtual void ShowStatusText(bool bEnable) = 0; // Provides a way to extend the context menu of an object. The function gets called every time the menu is opened. diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index 1459139f66..1e268d64ef 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -67,7 +67,6 @@ AZ_POP_DISABLE_WARNING #include "EditorFileMonitor.h" #include "MainStatusBar.h" -#include "ResourceSelectorHost.h" #include "Util/FileUtil_impl.h" #include "Util/ImageUtil_impl.h" #include "LogFileImpl.h" @@ -187,7 +186,6 @@ CEditorImpl::CEditorImpl() m_pAnimationContext = new CAnimationContext; m_pImageUtil = new CImageUtil_impl(); - m_pResourceSelectorHost.reset(CreateResourceSelectorHost()); m_selectedRegion.min = Vec3(0, 0, 0); m_selectedRegion.max = Vec3(0, 0, 0); DetectVersion(); diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h index 02be8bb8e3..2cf6c7805b 100644 --- a/Code/Editor/IEditorImpl.h +++ b/Code/Editor/IEditorImpl.h @@ -290,7 +290,6 @@ public: ESystemConfigPlatform GetEditorConfigPlatform() const; void ReloadTemplates(); void AddErrorMessage(const QString& text, const QString& caption); - IResourceSelectorHost* GetResourceSelectorHost() { return m_pResourceSelectorHost.get(); } virtual void ShowStatusText(bool bEnable); void OnObjectContextMenuOpened(QMenu* pMenu, const CBaseObject* pObject); @@ -374,7 +373,6 @@ protected: //! Export manager for exporting objects and a terrain from the game to DCC tools CExportManager* m_pExportManager; std::unique_ptr m_pEditorFileMonitor; - std::unique_ptr m_pResourceSelectorHost; QString m_selectFileBuffer; QString m_levelNameBuffer; diff --git a/Code/Editor/IEditorPanelUtils.h b/Code/Editor/IEditorPanelUtils.h index 5df15bd86b..4649213ae7 100644 --- a/Code/Editor/IEditorPanelUtils.h +++ b/Code/Editor/IEditorPanelUtils.h @@ -65,7 +65,7 @@ struct HotKey int size = (m_catSize < o_catSize) ? m_catSize : o_catSize; //sort categories to keep them together - for (unsigned int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { if (m_categories[i] < o_categories[i]) { diff --git a/Code/Editor/Include/IResourceSelectorHost.h b/Code/Editor/Include/IResourceSelectorHost.h deleted file mode 100644 index 55ce4e15d3..0000000000 --- a/Code/Editor/Include/IResourceSelectorHost.h +++ /dev/null @@ -1,135 +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 -// The aim of IResourceSelectorHost is to unify resource selection dialogs in a one -// API that can be reused with plugins. It also makes possible to register new -// resource selectors dynamically, e.g. inside plugins. -// -// Here is how new selectors are created. In your implementation file you add handler function: -// -// #include "IResourceSelectorHost.h" -// -// QString SoundFileSelector(const SResourceSelectorContext& x, const QString& previousValue) -// { -// CMyModalDialog dialog(CWnd::FromHandle(x.parentWindow)); -// ... -// return previousValue; -// } -// REGISTER_RESOURCE_SELECTOR("Sound", SoundFileSelector, "Icons/sound_16x16.png") -// -// Here is how it can be invoked directly: -// -// SResourceSelectorContext x; -// x.parentWindow = parent.GetSafeHwnd(); -// x.typeName = "Sound"; -// string newValue = GetIEditor()->GetResourceSelector()->SelectResource(x, previousValue).c_str(); -// -// If you have your own resource selectors in the plugin you will need to run -// -// RegisterModuleResourceSelectors(GetIEditor()->GetResourceSelector()) -// -// during plugin initialization. -// -// If you want to be able to pass some custom context to the selector (e.g. source of the information for the -// list of items or something similar) then you can add a poitner argument to your selector function, i.e.: -// -// QString SoundFileSelector(const SResourceSelectorContext& x, const QString& previousValue, -// SoundFileList* list) // your context argument - -#include - -class QWidget; - -struct SResourceSelectorContext -{ - const char* typeName; - - // use either parentWidget or parentWindow (not both) until everything porting to QWidget. - QWidget* parentWidget; - - unsigned int entityId; - void* contextObject; - - SResourceSelectorContext() - : parentWidget(0) - , typeName(0) - , entityId(0) - , contextObject() - { - } -}; - -// TResourceSelecitonFunction is used to declare handlers for specific types. -// -// For canceled dialogs previousValue should be returned. -typedef QString (* TResourceSelectionFunction)(const SResourceSelectorContext& selectorContext, const QString& previousValue); -typedef QString (* TResourceSelectionFunctionWithContext)(const SResourceSelectorContext& selectorContext, const QString& previousValue, void* contextObject); - -struct SStaticResourceSelectorEntry; - -// See note at the beginning of the file. -struct IResourceSelectorHost -{ - virtual ~IResourceSelectorHost() = default; - virtual QString SelectResource(const SResourceSelectorContext& context, const QString& previousValue) = 0; - virtual const char* ResourceIconPath(const char* typeName) const = 0; - - virtual void RegisterResourceSelector(const SStaticResourceSelectorEntry* entry) = 0; - - // secondary responsibility of this class is to store global selections - virtual void SetGlobalSelection(const char* resourceType, const char* value) = 0; - virtual const char* GetGlobalSelection(const char* resourceType) const = 0; -}; - -// --------------------------------------------------------------------------- -#define INTERNAL_RSH_COMBINE_UTIL(A, B) A##B -#define INTERNAL_RSH_COMBINE(A, B) INTERNAL_RSH_COMBINE_UTIL(A, B) -#define REGISTER_RESOURCE_SELECTOR(name, function, icon) \ - static SStaticResourceSelectorEntry INTERNAL_RSH_COMBINE(selector_##function, __LINE__)((name), (function), (icon)); - -struct SStaticResourceSelectorEntry -{ - const char* typeName; - TResourceSelectionFunction function; - TResourceSelectionFunctionWithContext functionWithContext; - const char* iconPath; - - static SStaticResourceSelectorEntry*& GetFirst() { static SStaticResourceSelectorEntry* first; return first; } - SStaticResourceSelectorEntry* next; - - SStaticResourceSelectorEntry(const char* typeName, TResourceSelectionFunction function, const char* icon) - : typeName(typeName) - , function(function) - , functionWithContext() - , iconPath(icon) - { - next = GetFirst(); - GetFirst() = this; - } - - template - SStaticResourceSelectorEntry(const char* typeName, QString (*function)(const SResourceSelectorContext&, const QString& previousValue, T * context), const char* icon) - : typeName(typeName) - , function() - , functionWithContext(TResourceSelectionFunctionWithContext(function)) - , iconPath(icon) - { - next = GetFirst(); - GetFirst() = this; - } -}; - -inline void RegisterModuleResourceSelectors(IResourceSelectorHost* editorResourceSelector) -{ - for (SStaticResourceSelectorEntry* current = SStaticResourceSelectorEntry::GetFirst(); current != 0; current = current->next) - { - editorResourceSelector->RegisterResourceSelector(current); - } -} diff --git a/Code/Editor/Lib/Tests/IEditorMock.h b/Code/Editor/Lib/Tests/IEditorMock.h index 9f99b0cd9d..242bf4d25c 100644 --- a/Code/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Editor/Lib/Tests/IEditorMock.h @@ -178,7 +178,6 @@ public: MOCK_CONST_METHOD0(GetEditorConfigSpec, ESystemConfigSpec()); MOCK_CONST_METHOD0(GetEditorConfigPlatform, ESystemConfigPlatform()); MOCK_METHOD0(ReloadTemplates, void()); - MOCK_METHOD0(GetResourceSelectorHost, IResourceSelectorHost* ()); MOCK_METHOD1(ShowStatusText, void(bool )); MOCK_METHOD1(RegisterObjectContextMenuExtension, void(TContextMenuExtensionFunc )); MOCK_METHOD0(GetEnv, SSystemGlobalEnvironment* ()); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp index 3f4cd1b566..50b315b9c3 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp @@ -9,7 +9,6 @@ #include "ComponentEntityEditorPlugin.h" #include -#include "IResourceSelectorHost.h" #include "UI/QComponentEntityEditorMainWindow.h" #include "UI/QComponentEntityEditorOutlinerWindow.h" @@ -180,8 +179,6 @@ ComponentEntityEditorPlugin::ComponentEntityEditorPlugin([[maybe_unused]] IEdito RegisterViewPane(LyViewPane::SliceRelationships, LyViewPane::CategoryTools, options); } - RegisterModuleResourceSelectors(GetIEditor()->GetResourceSelectorHost()); - ComponentEntityEditorPluginInternal::RegisterSandboxObjects(); // Check for common mistakes in component declarations diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 66c57361be..b10fe35513 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -82,7 +82,6 @@ #include #include #include -#include #include "CryEdit.h" #include "Undo/Undo.h" @@ -1387,16 +1386,6 @@ AZStd::string SandboxIntegrationManager::GetLevelName() return AZStd::string(GetIEditor()->GetGameEngine()->GetLevelName().toUtf8().constData()); } -AZStd::string SandboxIntegrationManager::SelectResource(const AZStd::string& resourceType, const AZStd::string& previousValue) -{ - SResourceSelectorContext context; - context.parentWidget = GetMainWindow(); - context.typeName = resourceType.c_str(); - - QString resource = GetEditor()->GetResourceSelectorHost()->SelectResource(context, previousValue.c_str()); - return AZStd::string(resource.toUtf8().constData()); -} - void SandboxIntegrationManager::OnContextReset() { // Deselect everything. diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index a2ec3b579b..d14ba80bce 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -158,7 +158,6 @@ private: void LaunchLuaEditor(const char* files) override; bool IsLevelDocumentOpen() override; AZStd::string GetLevelName() override; - AZStd::string SelectResource(const AZStd::string& resourceType, const AZStd::string& previousValue) override; void OpenPinnedInspector(const AzToolsFramework::EntityIdSet& entities) override; void ClosePinnedInspector(AzToolsFramework::EntityPropertyEditor* editor) override; void GoToSelectedOrHighlightedEntitiesInViewports() override; diff --git a/Code/Editor/ResourceSelectorHost.cpp b/Code/Editor/ResourceSelectorHost.cpp deleted file mode 100644 index eb82b57ab4..0000000000 --- a/Code/Editor/ResourceSelectorHost.cpp +++ /dev/null @@ -1,163 +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 "EditorDefs.h" - -#include "ResourceSelectorHost.h" - -// Qt -#include -#include - -// AzToolsFramework -#include -#include -#include - - -class CResourceSelectorHost - : public IResourceSelectorHost -{ -public: - CResourceSelectorHost() - { - RegisterModuleResourceSelectors(this); - } - - QString SelectResource(const SResourceSelectorContext& context, const QString& previousValue) override - { - if (!context.typeName) - { - assert(false && "SResourceSelectorContext::typeName is not specified"); - return QString(); - } - - TTypeMap::iterator it = m_typeMap.find(context.typeName); - if (it == m_typeMap.end()) - { - QMessageBox::critical(QApplication::activeWindow(), QString(), QObject::tr("No Resource Selector is registered for resource type \"%1\"").arg(context.typeName)); - return previousValue; - } - - QString result = previousValue; - if (it->second->function) - { - result = it->second->function(context, previousValue); - } - else if (it->second->functionWithContext) - { - result = it->second->functionWithContext(context, previousValue, context.contextObject); - } - - return result; - } - - const char* ResourceIconPath(const char* typeName) const override - { - TTypeMap::const_iterator it = m_typeMap.find(typeName); - if (it != m_typeMap.end()) - { - return it->second->iconPath; - } - return ""; - } - - void RegisterResourceSelector(const SStaticResourceSelectorEntry* entry) override - { - m_typeMap[entry->typeName] = entry; - } - - void SetGlobalSelection(const char* resourceType, const char* value) override - { - if (!resourceType || !value) - { - return; - } - m_globallySelectedResources[resourceType] = value; - } - - const char* GetGlobalSelection(const char* resourceType) const override - { - if (!resourceType) - { - return ""; - } - auto it = m_globallySelectedResources.find(resourceType); - if (it != m_globallySelectedResources.end()) - { - return it->second.c_str(); - } - return ""; - } - -private: - using TTypeMap = std::map>; - TTypeMap m_typeMap; - - std::map m_globallySelectedResources; -}; - -// --------------------------------------------------------------------------- - -IResourceSelectorHost* CreateResourceSelectorHost() -{ - return new CResourceSelectorHost(); -} - -// --------------------------------------------------------------------------- - -QString SoundFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue) -{ - AssetSelectionModel selection = AssetSelectionModel::AssetTypeSelection("Audio"); - AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection); - if (selection.IsValid()) - { - return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str())); - } - else - { - return Path::FullPathToGamePath(previousValue); - } -} -REGISTER_RESOURCE_SELECTOR("Sound", SoundFileSelector, "") - -// --------------------------------------------------------------------------- -QString ModelFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue) -{ - AssetSelectionModel selection = AssetSelectionModel::AssetGroupSelection("Geometry"); - AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection); - if (selection.IsValid()) - { - return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str())); - } - else - { - return Path::FullPathToGamePath(previousValue); - } -} -REGISTER_RESOURCE_SELECTOR("Model", ModelFileSelector, "") - -// --------------------------------------------------------------------------- -QString GeomCacheFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue) -{ - AssetSelectionModel selection = AssetSelectionModel::AssetTypeSelection("Geom Cache"); - AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection); - if (selection.IsValid()) - { - return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str())); - } - else - { - return Path::FullPathToGamePath(previousValue); - } -} - -REGISTER_RESOURCE_SELECTOR("GeomCache", GeomCacheFileSelector, "") - - diff --git a/Code/Editor/ResourceSelectorHost.h b/Code/Editor/ResourceSelectorHost.h deleted file mode 100644 index 266b7c39d1..0000000000 --- a/Code/Editor/ResourceSelectorHost.h +++ /dev/null @@ -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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_RESOURCESELECTORHOST_H -#define CRYINCLUDE_EDITOR_RESOURCESELECTORHOST_H -#pragma once - -#include "IResourceSelectorHost.h" - -IResourceSelectorHost* CreateResourceSelectorHost(); - -#endif // CRYINCLUDE_EDITOR_RESOURCESELECTORHOST_H diff --git a/Code/Editor/Util/Variable.cpp b/Code/Editor/Util/Variable.cpp index ee5ccc9879..97c2a1e8af 100644 --- a/Code/Editor/Util/Variable.cpp +++ b/Code/Editor/Util/Variable.cpp @@ -351,7 +351,7 @@ void CVarBlock::EnableUpdateCallbacks(bool boEnable) void CVarBlock::GatherUsedResourcesInVar(IVariable* pVar, CUsedResources& resources) { int type = pVar->GetDataType(); - if (type == IVariable::DT_FILE || type == IVariable::DT_OBJECT || type == IVariable::DT_TEXTURE) + if (type == IVariable::DT_TEXTURE) { // this is file. QString filename; diff --git a/Code/Editor/Util/Variable.h b/Code/Editor/Util/Variable.h index ecd54e42ae..da506b9db0 100644 --- a/Code/Editor/Util/Variable.h +++ b/Code/Editor/Util/Variable.h @@ -142,15 +142,10 @@ struct IVariable DT_PERCENT, //!< Percent data type, (Same as simple but value is from 0-1 and UI will be from 0-100). DT_COLOR, DT_ANGLE, - DT_FILE, DT_TEXTURE, - DT_ANIMATION, - DT_OBJECT, DT_SHADER, DT_LOCAL_STRING, DT_EQUIP, - DT_REVERBPRESET, - DT_DEPRECATED0, // formerly DT_MATERIAL DT_MATERIALLOOKUP, DT_EXTARRAY, // Extendable Array DT_SEQUENCE, // Movie Sequence (DEPRECATED, use DT_SEQUENCE_ID, instead.) @@ -160,7 +155,6 @@ struct IVariable DT_SEQUENCE_ID, // Movie Sequence DT_LIGHT_ANIMATION, // Light Animation Node in the global Light Animation Set DT_PARTICLE_EFFECT, - DT_GEOM_CACHE, // Geometry cache DT_DEPRECATED, // formerly DT_FLARE DT_AUDIO_TRIGGER, DT_AUDIO_SWITCH, diff --git a/Code/Editor/Util/VariablePropertyType.cpp b/Code/Editor/Util/VariablePropertyType.cpp index 014995467b..17c80a505c 100644 --- a/Code/Editor/Util/VariablePropertyType.cpp +++ b/Code/Editor/Util/VariablePropertyType.cpp @@ -37,17 +37,12 @@ namespace Prop { IVariable::DT_CURVE | IVariable::DT_PERCENT, "FloatCurve", ePropertyFloatCurve, 13 }, { IVariable::DT_CURVE | IVariable::DT_COLOR, "ColorCurve", ePropertyColorCurve, 1 }, { IVariable::DT_ANGLE, "Angle", ePropertyAngle, 0 }, - { IVariable::DT_FILE, "File", ePropertyFile, 7 }, { IVariable::DT_TEXTURE, "Texture", ePropertyTexture, 4 }, - { IVariable::DT_ANIMATION, "Animation", ePropertyAnimation, -1 }, { IVariable::DT_MOTION, "Motion", ePropertyMotion, -1 }, - { IVariable::DT_OBJECT, "Model", ePropertyModel, 5 }, { IVariable::DT_SIMPLE, "Selection", ePropertySelection, -1 }, { IVariable::DT_SIMPLE, "List", ePropertyList, -1 }, { IVariable::DT_SHADER, "Shader", ePropertyShader, 9 }, - { IVariable::DT_DEPRECATED0, "DEPRECATED", ePropertyDeprecated2, -1 }, { IVariable::DT_EQUIP, "Equip", ePropertyEquip, 11 }, - { IVariable::DT_REVERBPRESET, "ReverbPreset", ePropertyReverbPreset, 11 }, { IVariable::DT_LOCAL_STRING, "LocalString", ePropertyLocalString, 3 }, { IVariable::DT_SEQUENCE, "Sequence", ePropertySequence, -1 }, { IVariable::DT_MISSIONOBJ, "Mission Objective", ePropertyMissionObj, -1 }, @@ -55,7 +50,6 @@ namespace Prop { IVariable::DT_SEQUENCE_ID, "SequenceId", ePropertySequenceId, -1 }, { IVariable::DT_LIGHT_ANIMATION, "LightAnimation", ePropertyLightAnimation, -1 }, { IVariable::DT_PARTICLE_EFFECT, "ParticleEffect", ePropertyParticleName, 3 }, - { IVariable::DT_GEOM_CACHE, "Geometry Cache", ePropertyGeomCache, 5 }, { IVariable::DT_AUDIO_TRIGGER, "Audio Trigger", ePropertyAudioTrigger, 6 }, { IVariable::DT_AUDIO_SWITCH, "Audio Switch", ePropertyAudioSwitch, 6 }, { IVariable::DT_AUDIO_SWITCH_STATE, "Audio Switch", ePropertyAudioSwitchState, 6 }, @@ -301,31 +295,4 @@ namespace Prop return -1; } - - const char* GetPropertyTypeToResourceType(PropertyType type) - { - // The strings below are names used together with - // REGISTER_RESOURCE_SELECTOR. See IResourceSelector.h. - switch (type) - { - case ePropertyModel: - return "Model"; - case ePropertyGeomCache: - return "GeomCache"; - case ePropertyAudioTrigger: - return "AudioTrigger"; - case ePropertyAudioSwitch: - return "AudioSwitch"; - case ePropertyAudioSwitchState: - return "AudioSwitchState"; - case ePropertyAudioRTPC: - return "AudioRTPC"; - case ePropertyAudioEnvironment: - return "AudioEnvironment"; - case ePropertyAudioPreloadRequest: - return "AudioPreloadRequest"; - default: - return nullptr; - } - } } diff --git a/Code/Editor/Util/VariablePropertyType.h b/Code/Editor/Util/VariablePropertyType.h index af2865add1..decb930cb3 100644 --- a/Code/Editor/Util/VariablePropertyType.h +++ b/Code/Editor/Util/VariablePropertyType.h @@ -28,16 +28,11 @@ enum PropertyType ePropertyAngle, ePropertyFloatCurve, ePropertyColorCurve, - ePropertyFile, ePropertyTexture, - ePropertyAnimation, - ePropertyModel, ePropertySelection, ePropertyList, ePropertyShader, - ePropertyDeprecated2, // formerly ePropertyMaterial ePropertyEquip, - ePropertyReverbPreset, ePropertyLocalString, ePropertyDeprecated0, // formerly ePropertyCustomAction ePropertyGameToken, @@ -48,7 +43,6 @@ enum PropertyType ePropertyLightAnimation, ePropertyDeprecated1, // formerly ePropertyFlare ePropertyParticleName, - ePropertyGeomCache, ePropertyAudioTrigger, ePropertyAudioSwitch, ePropertyAudioSwitchState, diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index 4b80a5d461..c10db3bac5 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -289,7 +289,6 @@ set(FILES Include/IPlugin.h Include/IPreferencesPage.h Include/IRenderListener.h - Include/IResourceSelectorHost.h Include/ISourceControl.h Include/ISubObjectSelectionReferenceFrameCalculator.h Include/ITextureDatabaseUpdater.h @@ -360,8 +359,6 @@ set(FILES Controls/TimelineCtrl.cpp Controls/TimelineCtrl.h Controls/WndGridHelper.h - Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp - Controls/ReflectedPropertyControl/PropertyAnimationCtrl.h Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp Controls/ReflectedPropertyControl/PropertyGenericCtrl.h Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp @@ -372,8 +369,6 @@ set(FILES Controls/ReflectedPropertyControl/PropertyResourceCtrl.h Controls/ReflectedPropertyControl/PropertyCtrl.cpp Controls/ReflectedPropertyControl/PropertyCtrl.h - Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp - Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h MainStatusBar.cpp MainStatusBar.h MainStatusBarItems.h @@ -590,8 +585,6 @@ set(FILES FBXExporterDialog.ui FileTypeUtils.cpp LightmapCompiler/SimpleTriangleRasterizer.cpp - ResourceSelectorHost.cpp - ResourceSelectorHost.h ToolBox.cpp TrackViewNewSequenceDialog.cpp TrackViewNewSequenceDialog.ui @@ -668,7 +661,6 @@ set(FILES TrackView/2DBezierKeyUIControls.cpp TrackView/AssetBlendKeyUIControls.cpp TrackView/CaptureKeyUIControls.cpp - TrackView/CharacterKeyUIControls.cpp TrackView/ConsoleKeyUIControls.cpp TrackView/EventKeyUIControls.cpp TrackView/GotoKeyUIControls.cpp diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index f6046b9f25..9e5db5b5b7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -841,9 +841,6 @@ namespace AzToolsFramework */ virtual AZStd::string GetComponentIconPath(const AZ::Uuid& /*componentType*/, AZ::Crc32 /*componentIconAttrib*/, AZ::Component* /*component*/) { return AZStd::string(); } - /// Resource Selector hook, returns a path for a resource. - virtual AZStd::string SelectResource(const AZStd::string& /*resourceType*/, const AZStd::string& /*previousValue*/) { return AZStd::string(); } - /** * Calculate the navigation 2D radius in units of an agent given its Navigation Type Name * @param angentTypeName the name that identifies the agent navigation type diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.cpp index 6951d7ae8c..274db35da2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.cpp @@ -7,8 +7,8 @@ */ -#include "PropertyAudioCtrl.h" -#include "PropertyQTConstants.h" +#include +#include #include #include @@ -34,7 +34,7 @@ namespace AzToolsFramework : QWidget(parent) , m_browseEdit(nullptr) , m_mainLayout(nullptr) - , m_propertyType(AudioPropertyType::Invalid) + , m_propertyType(AudioPropertyType::NumTypes) { // create the gui m_mainLayout = new QHBoxLayout(); @@ -96,7 +96,7 @@ namespace AzToolsFramework return; } - if (type != AudioPropertyType::Invalid) + if (type != AudioPropertyType::NumTypes) { m_propertyType = type; } @@ -136,10 +136,11 @@ namespace AzToolsFramework void AudioControlSelectorWidget::OnOpenAudioControlSelector() { - AZStd::string resourceResult; - AZStd::string resourceType(GetResourceSelectorNameFromType(m_propertyType)); AZStd::string currentValue(m_controlName.toStdString().c_str()); - EditorRequests::Bus::BroadcastResult(resourceResult, &EditorRequests::Bus::Events::SelectResource, resourceType, currentValue); + AZStd::string resourceResult; + AudioControlSelectorRequestBus::EventResult( + resourceResult, m_propertyType, + &AudioControlSelectorRequestBus::Events::SelectResource, currentValue); SetControlName(QString(resourceResult.c_str())); } @@ -167,12 +168,12 @@ namespace AzToolsFramework { case AudioPropertyType::Trigger: return { "AudioTrigger" }; + case AudioPropertyType::Rtpc: + return { "AudioRTPC" }; case AudioPropertyType::Switch: return { "AudioSwitch" }; case AudioPropertyType::SwitchState: return { "AudioSwitchState" }; - case AudioPropertyType::Rtpc: - return { "AudioRTPC" }; case AudioPropertyType::Environment: return { "AudioEnvironment" }; case AudioPropertyType::Preload: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h index 4996806a8d..dbc45a592d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h @@ -29,6 +29,27 @@ class QMimeData; namespace AzToolsFramework { + //============================================================================= + // Audio Control Selector Request Bus + // For connecting UI proper + //============================================================================= + class AudioControlSelectorRequests + : public AZ::EBusTraits + { + public: + // EBusTraits + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + using BusIdType = AudioPropertyType; + + virtual AZStd::string SelectResource(AZStd::string_view previousValue) + { + return previousValue; + } + }; + + using AudioControlSelectorRequestBus = AZ::EBus; + //============================================================================= // Audio Control Selector Widget //============================================================================= diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrlTypes.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrlTypes.h index df31e297cd..c23e082a44 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrlTypes.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrlTypes.h @@ -18,15 +18,15 @@ namespace AzToolsFramework { //========================================================================= - enum class AudioPropertyType + enum class AudioPropertyType : AZ::u32 { - Invalid = 0, - Trigger, + Trigger = 0, + Rtpc, Switch, SwitchState, - Rtpc, Environment, Preload, + NumTypes, }; //========================================================================= @@ -40,7 +40,7 @@ namespace AzToolsFramework virtual ~CReflectedVarAudioControl() = default; AZStd::string m_controlName; - AudioPropertyType m_propertyType = AudioPropertyType::Invalid; + AudioPropertyType m_propertyType = AudioPropertyType::NumTypes; static void Reflect(AZ::ReflectContext* context) { diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.cpp b/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.cpp index 46941baf17..d3121f6245 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.cpp @@ -30,6 +30,8 @@ namespace AudioControls : QDialog(pParent) , m_eType(eType) { + AZ_Assert(CAudioControlsEditorPlugin::GetATLModel() != nullptr, "ATLControlsDialog - ATL Model is null!"); + setWindowTitle(GetWindowTitle(m_eType)); setWindowModality(Qt::ApplicationModal); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp index 2b7023df61..f3d5a03ffc 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp @@ -14,8 +14,6 @@ #include #include -#include - #include #include #include @@ -41,7 +39,6 @@ CAudioControlsEditorPlugin::CAudioControlsEditorPlugin(IEditor* editor) QtViewOptions options; options.canHaveMultipleInstances = true; RegisterQtViewPane(editor, LyViewPane::AudioControlsEditor, LyViewPane::CategoryOther, options); - RegisterAudioControlsResourceSelectors(); Audio::AudioSystemRequestBus::BroadcastResult(ms_pIAudioProxy, &Audio::AudioSystemRequestBus::Events::GetFreeAudioProxy); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.h index 4e5c528901..f8288a5d7f 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -68,6 +69,7 @@ private: static AudioControls::FilepathSet ms_currentFilenames; static Audio::IAudioProxy* ms_pIAudioProxy; static Audio::TAudioControlID ms_nAudioTriggerID; - static CImplementationManager ms_implementationManager; + + AudioControls::AudioControlSelectorHandler m_controlSelector; }; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp index 74233be2e9..a6ab3878b8 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp @@ -10,88 +10,45 @@ #include #include #include -#include -#include #include +#include + namespace AudioControls { //-------------------------------------------------------------------------------------------// - QString ShowSelectDialog(const SResourceSelectorContext& context, const QString& pPreviousValue, const EACEControlType controlType) + AudioControlSelectorHandler::AudioControlSelectorHandler() { - AZ_Assert(CAudioControlsEditorPlugin::GetATLModel() != nullptr, "AudioResourceSelectors - ATL Model is null!"); - - AZStd::string levelName; - AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName); - - ATLControlsDialog dialog(context.parentWidget, controlType); - dialog.SetScope(levelName); - return dialog.ChooseItem(pPreviousValue.toUtf8().constData()); - } - - //-------------------------------------------------------------------------------------------// - QString AudioTriggerSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_TRIGGER); - } - - //-------------------------------------------------------------------------------------------// - QString AudioSwitchSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_SWITCH); - } - - //-------------------------------------------------------------------------------------------// - QString AudioSwitchStateSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_SWITCH_STATE); - } - - //-------------------------------------------------------------------------------------------// - QString AudioRTPCSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_RTPC); - } - - //-------------------------------------------------------------------------------------------// - QString AudioEnvironmentSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_ENVIRONMENT); - } - - //-------------------------------------------------------------------------------------------// - QString AudioPreloadRequestSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_PRELOAD); - } - - //-------------------------------------------------------------------------------------------// - static SStaticResourceSelectorEntry audioTriggerSelector( - "AudioTrigger", AudioTriggerSelector, ":/Icons/Trigger_Icon.svg"); - static SStaticResourceSelectorEntry audioSwitchSelector( - "AudioSwitch", AudioSwitchSelector, ":/Icons/Switch_Icon.svg"); - static SStaticResourceSelectorEntry audioStateSelector( - "AudioSwitchState", AudioSwitchStateSelector, ":/Icons/Property_Icon.png"); - static SStaticResourceSelectorEntry audioRtpcSelector( - "AudioRTPC", AudioRTPCSelector, ":/Icons/RTPC_Icon.svg"); - static SStaticResourceSelectorEntry audioEnvironmentSelector( - "AudioEnvironment", AudioEnvironmentSelector, ":/Icons/Environment_Icon.svg"); - static SStaticResourceSelectorEntry audioPreloadSelector( - "AudioPreloadRequest", AudioPreloadRequestSelector, ":/Icons/Bank_Icon.png"); - - //-------------------------------------------------------------------------------------------// - void RegisterAudioControlsResourceSelectors() - { - if (IResourceSelectorHost* host = GetIEditor()->GetResourceSelectorHost(); - host != nullptr) + for (AZ::u32 type = 0; type < static_cast(AzToolsFramework::AudioPropertyType::NumTypes); ++type) { - host->RegisterResourceSelector(&audioTriggerSelector); - host->RegisterResourceSelector(&audioSwitchSelector); - host->RegisterResourceSelector(&audioStateSelector); - host->RegisterResourceSelector(&audioRtpcSelector); - host->RegisterResourceSelector(&audioEnvironmentSelector); - host->RegisterResourceSelector(&audioPreloadSelector); + AzToolsFramework::AudioControlSelectorRequestBus::MultiHandler::BusConnect( + static_cast(type)); } } + AudioControlSelectorHandler::~AudioControlSelectorHandler() + { + AzToolsFramework::AudioControlSelectorRequestBus::MultiHandler::BusDisconnect(); + } + + AZStd::string AudioControlSelectorHandler::SelectResource(AZStd::string_view previousValue) + { + using namespace AzToolsFramework; + if (auto busId = AudioControlSelectorRequestBus::GetCurrentBusId(); + busId != nullptr) + { + auto controlType = static_cast(*busId); + QWidget* parentWidget = nullptr; + AzToolsFramework::EditorRequestBus::BroadcastResult(parentWidget, &AzToolsFramework::EditorRequestBus::Events::GetMainWindow); + + AZStd::string levelName; + AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName); + + ATLControlsDialog dialog(parentWidget, controlType); + dialog.SetScope(levelName); + return dialog.ChooseItem(previousValue.data()); + } + return previousValue; + } + } // namespace AudioControls diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h index d2bff7c799..127cfb15b4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h @@ -8,7 +8,16 @@ #pragma once +#include + namespace AudioControls { - void RegisterAudioControlsResourceSelectors(); + class AudioControlSelectorHandler + : public AzToolsFramework::AudioControlSelectorRequestBus::MultiHandler + { + public: + AudioControlSelectorHandler(); + ~AudioControlSelectorHandler(); + AZStd::string SelectResource(AZStd::string_view previousValue) override; + }; } From 88bef1074bc20ac4e8dd543af1bc7f345bddfd5f Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 16 Aug 2021 15:43:01 -0500 Subject: [PATCH 081/101] Replaced some Lumberyard references with O3DE. Signed-off-by: Chris Galvan --- .../Gem/PythonTests/EditorPythonTestTools/README.txt | 4 ++-- .../PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py | 2 +- .../BasicEditorWorkflows_LevelEntityComponentCRUD.py | 4 ++-- .../editor/EditorScripts/Menus_EditMenuOptions.py | 2 +- .../editor/EditorScripts/Menus_FileMenuOptions.py | 2 +- .../editor/EditorScripts/Menus_ViewMenuOptions.py | 2 +- .../scripting/Pane_PropertiesChanged_RetainsOnRestart.py | 2 +- .../Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py | 2 +- Gems/QtForPython/Editor/Scripts/tests/log_main_window.py | 2 +- .../Include/ScriptCanvas/Libraries/Entity/EntityNodes.h | 6 +++--- .../Include/ScriptCanvas/Libraries/Math/TransformNodes.h | 6 +++--- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt index 0405dacbf4..90afee39bc 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt @@ -8,7 +8,7 @@ INTRODUCTION ------------ EditorPythonBindings is a Python project that contains a collection of editor testing tools -developed by the Lumberyard feature teams. The project contains tools for system level +developed by the O3DE feature teams. The project contains tools for system level editor tests. @@ -23,7 +23,7 @@ installed on your system. INSTALL ----------- -It is recommended to set up these these tools with Lumberyard's CMake build commands. +It is recommended to set up these these tools with O3DE's CMake build commands. Assuming CMake is already setup on your operating system, below are some sample build commands: cd /path/to/od3e/ mkdir windows_vs2019 diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py index f728714125..068f25fb1e 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py @@ -61,7 +61,7 @@ class AssetPickerUIUXTest(EditorTestHelper): 5) Verify if Mesh Asset is assigned via both OK/Enter options Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py index 32d20ea2b4..994fc661ed 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py @@ -37,7 +37,7 @@ class TestBasicEditorWorkflows(EditorTestHelper): async def run_test(self): """ Summary: - Open Lumberyard editor and check if basic Editor workflows are completable. + Open O3DE editor and check if basic Editor workflows are completable. Expected Behavior: - A new level can be created @@ -48,7 +48,7 @@ class TestBasicEditorWorkflows(EditorTestHelper): - Level can be exported Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py index 6b861894c0..53a8da4116 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py @@ -36,7 +36,7 @@ class TestEditMenuOptions(EditorTestHelper): 2) Interact with Edit Menu options Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py index ab9aa1d326..77ee9ac61d 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py @@ -32,7 +32,7 @@ class TestFileMenuOptions(EditorTestHelper): 2) Interact with File Menu options Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py index d1233e9815..d2db4210ce 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py @@ -36,7 +36,7 @@ class TestViewMenuOptions(EditorTestHelper): 2) Interact with View Menu options Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py b/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py index 5c74754449..338389b1c4 100644 --- a/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py @@ -52,7 +52,7 @@ def Pane_PropertiesChanged_RetainsOnRestart(): from utils import TestHelper as helper import pyside_utils - # Lumberyard Imports + # O3DE Imports import azlmbr.legacy.general as general # Pyside imports diff --git a/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py index 9a54de856c..71956488fc 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py @@ -53,7 +53,7 @@ def Editor_NewExistingLevels_Works(): 10) Save, Load and Export an existing level and close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/Gems/QtForPython/Editor/Scripts/tests/log_main_window.py b/Gems/QtForPython/Editor/Scripts/tests/log_main_window.py index 528e869d8c..6971731cb0 100755 --- a/Gems/QtForPython/Editor/Scripts/tests/log_main_window.py +++ b/Gems/QtForPython/Editor/Scripts/tests/log_main_window.py @@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t SPDX-License-Identifier: Apache-2.0 OR MIT """ -# bit more complex example set to demo connecting Lumberyard tech to PySide2 widgets +# bit more complex example set to demo connecting O3DE tech to PySide2 widgets import azlmbr.bus from PySide2 import QtWidgets from PySide2 import QtGui diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h index 701c3a0869..191635757c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h @@ -35,7 +35,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityRight, DefaultScale<1>, k_categoryName, "{C12282BE-29D2-497D-8C22-75B940E254E2}", "returns the right direction vector from the specified entity's world transform, scaled by a given value (Lumberyard uses Z up, right handed)", "EntityId", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityRight, DefaultScale<1>, k_categoryName, "{C12282BE-29D2-497D-8C22-75B940E254E2}", "returns the right direction vector from the specified entity's world transform, scaled by a given value (O3DE uses Z up, right handed)", "EntityId", "Scale"); AZ_INLINE Vector3Type GetEntityForward(AZ::EntityId entityId, NumberType scale) { @@ -46,7 +46,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityForward, DefaultScale<1>, k_categoryName, "{719D9F76-84D4-4B0F-BCEB-26D5D097C7D6}", "returns the forward direction vector from the specified entity' world transform, scaled by a given value (Lumberyard uses Z up, right handed)", "EntityId", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityForward, DefaultScale<1>, k_categoryName, "{719D9F76-84D4-4B0F-BCEB-26D5D097C7D6}", "returns the forward direction vector from the specified entity' world transform, scaled by a given value (O3DE uses Z up, right handed)", "EntityId", "Scale"); AZ_INLINE Vector3Type GetEntityUp(AZ::EntityId entityId, NumberType scale) { @@ -57,7 +57,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityUp, DefaultScale<1>, k_categoryName, "{96B86F3F-F022-4611-9AEA-175EA952C562}", "returns the up direction vector from the specified entity's world transform, scaled by a given value (Lumberyard uses Z up, right handed)", "EntityId", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityUp, DefaultScale<1>, k_categoryName, "{96B86F3F-F022-4611-9AEA-175EA952C562}", "returns the up direction vector from the specified entity's world transform, scaled by a given value (O3DE uses Z up, right handed)", "EntityId", "Scale"); AZ_INLINE BooleanType IsActive(const EntityIDType& entityId) { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h index ddbe5ac5f7..f2088dbf6d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h @@ -74,7 +74,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetRight, DefaultScale<1>, k_categoryName, "{65811752-711F-4566-869E-5AEF53206342}", "returns the right direction vector from the specified transform scaled by a given value (Lumberyard uses Z up, right handed)", "Source", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetRight, DefaultScale<1>, k_categoryName, "{65811752-711F-4566-869E-5AEF53206342}", "returns the right direction vector from the specified transform scaled by a given value (O3DE uses Z up, right handed)", "Source", "Scale"); AZ_INLINE Vector3Type GetForward(const TransformType& source, NumberType scale) { @@ -82,7 +82,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetForward, DefaultScale<1>, k_categoryName, "{3602a047-9f12-46d4-9648-8f53770c8130}", "returns the forward direction vector from the specified transform scaled by a given value (Lumberyard uses Z up, right handed)", "Source", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetForward, DefaultScale<1>, k_categoryName, "{3602a047-9f12-46d4-9648-8f53770c8130}", "returns the forward direction vector from the specified transform scaled by a given value (O3DE uses Z up, right handed)", "Source", "Scale"); AZ_INLINE Vector3Type GetUp(const TransformType& source, NumberType scale) { @@ -90,7 +90,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetUp, DefaultScale<1>, k_categoryName, "{F10F52D2-E6F2-4E39-84D5-B4A561F186D3}", "returns the up direction vector from the specified transform scaled by a given value (Lumberyard uses Z up, right handed)", "Source", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetUp, DefaultScale<1>, k_categoryName, "{F10F52D2-E6F2-4E39-84D5-B4A561F186D3}", "returns the up direction vector from the specified transform scaled by a given value (O3DE uses Z up, right handed)", "Source", "Scale"); AZ_INLINE Vector3Type GetTranslation(const TransformType& source) { From a461a82030e5aa7f77e0a8337b61d7f8abfc3885 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Mon, 16 Aug 2021 18:13:35 -0400 Subject: [PATCH 082/101] Remove non-existant files from icon contents.json files (#3148) Signed-off-by: mgwynn --- .../AppIcon.appiconset/Contents.json | 32 +------------ .../Contents.json | 32 +------------ .../LaunchImage.launchimage/Contents.json | 47 +------------------ 3 files changed, 3 insertions(+), 108 deletions(-) diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json index 09621469c3..94e3dcd84d 100644 --- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,17 +1,5 @@ { "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "iPhoneNotificationIcon40x40.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "iPhoneNotificationIcon60x60.png", - "scale" : "3x" - }, { "size" : "29x29", "idiom" : "iphone", @@ -48,18 +36,6 @@ "filename" : "iPhoneAppIcon180x180.png", "scale" : "3x" }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "iPadNotificationIcon20x20.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "iPadNotificationIcon40x40.png", - "scale" : "2x" - }, { "size" : "29x29", "idiom" : "ipad", @@ -101,16 +77,10 @@ "idiom" : "ipad", "filename" : "iPadProAppIcon167x167.png", "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "iOSAppStoreIcon1024x1024.png", - "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } -} \ No newline at end of file +} diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json index 09621469c3..94e3dcd84d 100644 --- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json +++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json @@ -1,17 +1,5 @@ { "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "iPhoneNotificationIcon40x40.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "iPhoneNotificationIcon60x60.png", - "scale" : "3x" - }, { "size" : "29x29", "idiom" : "iphone", @@ -48,18 +36,6 @@ "filename" : "iPhoneAppIcon180x180.png", "scale" : "3x" }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "iPadNotificationIcon20x20.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "iPadNotificationIcon40x40.png", - "scale" : "2x" - }, { "size" : "29x29", "idiom" : "ipad", @@ -101,16 +77,10 @@ "idiom" : "ipad", "filename" : "iPadProAppIcon167x167.png", "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "iOSAppStoreIcon1024x1024.png", - "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } -} \ No newline at end of file +} diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json index f836f07ee7..67b253d091 100644 --- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json +++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -1,50 +1,5 @@ { "images" : [ - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "2436h", - "filename" : "iPhoneLaunchImage1125x2436.png", - "minimum-system-version" : "11.0", - "orientation" : "portrait", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "2436h", - "filename" : "iPhoneLaunchImage2436x1125.png", - "minimum-system-version" : "11.0", - "orientation" : "landscape", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "iPhoneLaunchImage1242x2208.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "iPhoneLaunchImage2208x1242.png", - "minimum-system-version" : "8.0", - "orientation" : "landscape", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "667h", - "filename" : "iPhoneLaunchImage750x1334.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "2x" - }, { "orientation" : "portrait", "idiom" : "iphone", @@ -166,4 +121,4 @@ "version" : 1, "author" : "xcode" } -} \ No newline at end of file +} From 0884f96997ab18916b4b83ce01f167eb75d1eea6 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Mon, 16 Aug 2021 16:00:18 -0700 Subject: [PATCH 083/101] PR feedback Signed-off-by: mnaumov --- .../AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp | 6 +++--- .../AzToolsFramework/Prefab/PrefabDomUtils.cpp | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp index af42919637..92b37b10db 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp @@ -82,13 +82,13 @@ namespace AzToolsFramework result.Combine(resultInstances); } - PrefabDomUtils::LinkIdMetadata** linkIdMetadata = context.GetMetadata().Find(); - if (linkIdMetadata && *linkIdMetadata) + PrefabDomUtils::LinkIdMetadata* subPathLinkId = context.GetMetadata().Find(); + if (subPathLinkId) { AZ::ScopedContextPath subPathSource(context, "m_linkId"); result = ContinueStoringToJsonObjectField( - outputValue, "LinkId", &(instance->m_linkId), &InvalidLinkId, azrtti_typeid(), context); + outputValue, "LinkId", &(instance->m_linkId), &InvalidLinkId, azrtti_typeidm_linkId)>(), context); } return context.Report(result, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index 2462bc0348..dcc14d3b91 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -90,8 +90,7 @@ namespace AzToolsFramework if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None) { - LinkIdMetadata linkIdMetadata; - settings.m_metadata.Add(&linkIdMetadata); + settings.m_metadata.Create(); } AZStd::string scratchBuffer; From f76d09e2158bc6a310083f085cfc9dc99bf1be9e Mon Sep 17 00:00:00 2001 From: pereslav Date: Tue, 17 Aug 2021 00:19:57 +0100 Subject: [PATCH 084/101] Fixed assert about memory override when logged string is longer than the buffer size Signed-off-by: pereslav --- Code/Legacy/CrySystem/Log.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index d248274b1d..872a522a69 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -851,7 +851,8 @@ bool CLog::LogToMainThread(const char* szString, ELogType logType, bool bAdd, SL { // When logging from other thread then main, push all log strings to queue. SLogMsg msg; - azstrcpy(msg.msg, AZ_ARRAY_SIZE(msg.msg), szString); + constexpr size_t maxArraySize = AZ_ARRAY_SIZE(msg.msg); + azstrncpy(msg.msg, maxArraySize, szString, maxArraySize - 1); msg.bAdd = bAdd; msg.destination = destination; msg.logType = logType; From ff4d65dc2d29f57fa15f423b3c38f21c92711254 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 16 Aug 2021 18:22:37 -0500 Subject: [PATCH 085/101] added functions to remove and clear trace logger filters Signed-off-by: Guthrie Adams --- .../AzToolsFramework/Logger/TraceLogger.cpp | 20 +++++++++++++++++++ .../AzToolsFramework/Logger/TraceLogger.h | 16 +++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp index 547d328c45..e81aaed6c9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp @@ -91,8 +91,28 @@ namespace AzToolsFramework m_windowFilters.insert(filter); } + void TraceLogger::RemoveWindowFilter(const AZStd::string& filter) + { + m_windowFilters.erase(filter); + } + + void TraceLogger::ClearWindowFilter() + { + m_windowFilters.clear(); + } + void TraceLogger::AddMessageFilter(const AZStd::string& filter) { m_messageFilters.insert(filter); } + + void TraceLogger::RemoveMessageFilter(const AZStd::string& filter) + { + m_messageFilters.erase(filter); + } + + void TraceLogger::ClearMessageFilter() + { + m_messageFilters.clear(); + } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h index ac1455452a..10708e3239 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h @@ -25,12 +25,24 @@ namespace AzToolsFramework //! Open log file and dump log sink into it void PrepareLogFile(const AZStd::string& logFileName); - //! Ignore messages sent to windowd with names matching filter + //! Add filter to ignore messages for windows with matching names void AddWindowFilter(const AZStd::string& filter); - //! Ignore messages with text matching filter + //! Remove window filter + void RemoveWindowFilter(const AZStd::string& filter); + + //! Clear window filters + void ClearWindowFilter(); + + //! Add filter to ignore messages with matching names void AddMessageFilter(const AZStd::string& filter); + //! Remove message filter + void RemoveMessageFilter(const AZStd::string& filter); + + //! Clear message filters + void ClearMessageFilter(); + protected: ////////////////////////////////////////////////////////////////////////// // AZ::Debug::TraceMessageBus::Handler overrides... From ae4ad7dcac8c84736332d6c3261d03eafbb2e594 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 16 Aug 2021 18:29:16 -0500 Subject: [PATCH 086/101] fixed formatting Signed-off-by: Guthrie Adams --- .../Code/Source/Window/SettingsDialog/SettingsWidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp index e8254edb28..c7d4b195a3 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp @@ -52,7 +52,8 @@ namespace MaterialEditor const AZStd::string groupDisplayName = "Document System Settings"; const AZStd::string groupDescription = "Document System Settings"; - const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup")); AddGroup( + const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup")); + AddGroup( groupNameId, groupDisplayName, groupDescription, new AtomToolsFramework::InspectorPropertyGroupWidget( m_documentSystemSettings.get(), nullptr, m_documentSystemSettings->TYPEINFO_Uuid(), this, this, saveStateKey)); From 4e3ec08c6a1fdd0a99d4f6acee302acd211f3612 Mon Sep 17 00:00:00 2001 From: abrmich Date: Mon, 16 Aug 2021 18:03:13 -0700 Subject: [PATCH 087/101] Fix script canvases not loading if on a UI canvas element Signed-off-by: abrmich --- Gems/LyShine/Code/Source/UiCanvasFileObject.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/LyShine/Code/Source/UiCanvasFileObject.h b/Gems/LyShine/Code/Source/UiCanvasFileObject.h index 4cfec60bea..167405355b 100644 --- a/Gems/LyShine/Code/Source/UiCanvasFileObject.h +++ b/Gems/LyShine/Code/Source/UiCanvasFileObject.h @@ -24,7 +24,8 @@ public: AZ_CLASS_ALLOCATOR(UiCanvasFileObject, AZ::SystemAllocator, 0); AZ_RTTI(UiCanvasFileObject, "{1F02632F-F113-49B1-85AD-8CD0FA78B8AA}"); - static UiCanvasFileObject* LoadCanvasFromStream(AZ::IO::GenericStream& stream, const AZ::ObjectStream::FilterDescriptor& filterDesc = AZ::ObjectStream::FilterDescriptor(AZ::ObjectStream::AssetFilterAssetTypesOnly)); + // Load canvas from stream with an optional asset filter. No asset references are ignored by default + static UiCanvasFileObject* LoadCanvasFromStream(AZ::IO::GenericStream& stream, const AZ::ObjectStream::FilterDescriptor& filterDesc = AZ::ObjectStream::FilterDescriptor()); static void SaveCanvasToStream(AZ::IO::GenericStream& stream, UiCanvasFileObject* canvasFileObject); static AZ::Entity* LoadCanvasEntitiesFromStream(AZ::IO::GenericStream& stream, AZ::Entity*& rootSliceEntity); From d9ea329cbde12eb973a9942562c18ae40e5e052b Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Tue, 17 Aug 2021 13:48:51 +0100 Subject: [PATCH 088/101] Fixes #2796 Collider retains phys mesh asset reference after changing to shape (#3162) Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- .../PhysX/Code/Source/EditorColliderComponent.cpp | 15 ++++++++++++++- Gems/PhysX/Code/Source/EditorColliderComponent.h | 9 ++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index d3f1c63974..2445aba9bd 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -88,7 +88,7 @@ namespace PhysX ->EnumAttribute(Physics::ShapeType::Box, "Box") ->EnumAttribute(Physics::ShapeType::Capsule, "Capsule") ->EnumAttribute(Physics::ShapeType::PhysicsAsset, "PhysicsAsset") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorProxyShapeConfig::OnShapeTypeChanged) // note: we do not want the user to be able to change shape types while in ComponentMode (there will // potentially be different ComponentModes for different shape types) ->Attribute(AZ::Edit::Attributes::ReadOnly, &AzToolsFramework::ComponentModeFramework::InComponentMode) @@ -116,6 +116,19 @@ namespace PhysX } } + AZ::u32 EditorProxyShapeConfig::OnShapeTypeChanged() + { + //reset the physics asset if the shape type was Physics Asset + if (m_shapeType != Physics::ShapeType::PhysicsAsset && + m_lastShapeType == Physics::ShapeType::PhysicsAsset) + { + m_physicsAsset.m_pxAsset.Reset(); + m_physicsAsset.m_configuration = Physics::PhysicsAssetShapeConfiguration(); + } + m_lastShapeType = m_shapeType; + return AZ::Edit::PropertyRefreshLevels::EntireTree; + } + AZ::u32 EditorProxyShapeConfig::OnConfigurationChanged() { return AZ::Edit::PropertyRefreshLevels::ValuesOnly; diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.h b/Gems/PhysX/Code/Source/EditorColliderComponent.h index 8a78cc1cb8..50cf9d0c8b 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.h @@ -58,8 +58,8 @@ namespace PhysX //! Proxy container for only displaying a specific shape configuration depending on the shapeType selected. struct EditorProxyShapeConfig { - AZ_CLASS_ALLOCATOR(EditorProxyShapeConfig, AZ::SystemAllocator, 0); - AZ_RTTI(EditorProxyShapeConfig, "{531FB42A-42A9-4234-89BA-FD349EF83D0C}"); + AZ_CLASS_ALLOCATOR(PhysX::EditorProxyShapeConfig, AZ::SystemAllocator, 0); + AZ_RTTI(PhysX::EditorProxyShapeConfig, "{531FB42A-42A9-4234-89BA-FD349EF83D0C}"); static void Reflect(AZ::ReflectContext* context); EditorProxyShapeConfig() = default; @@ -84,9 +84,12 @@ namespace PhysX AZStd::shared_ptr CloneCurrent() const; + private: bool ShowingSubdivisionLevel() const; - + AZ::u32 OnShapeTypeChanged(); AZ::u32 OnConfigurationChanged(); + + Physics::ShapeType m_lastShapeType = Physics::ShapeType::PhysicsAsset; }; class EditorColliderComponentDescriptor; From d1cedba042c4847def1101eecbf99739dfa69ed2 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 17 Aug 2021 06:20:33 -0700 Subject: [PATCH 089/101] Fix NativeWindow_Windows returning the wrong size. (#3153) Make sure WM_WINDOWPOSCHANGED bubbles up so that we can see WM_SIZE. Signed-off-by: nvsickle --- .../AzFramework/Windowing/NativeWindow_Windows.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp index 2c1d97dcf6..8312f9fa63 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp @@ -207,7 +207,10 @@ namespace AzFramework // Handles Win32 Window Event callbacks LRESULT CALLBACK NativeWindowImpl_Win32::WindowCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - NativeWindowImpl_Win32* nativeWindowImpl = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + NativeWindowImpl_Win32* nativeWindowImpl = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + + // If set to true, call DefWindowProc to ensure the default Windows behavior occurs + bool shouldBubbleEventUp = false; switch (message) { @@ -276,14 +279,19 @@ namespace AzFramework uint32_t refreshRate = DisplayConfig.dmDisplayFrequency; WindowNotificationBus::Event( nativeWindowImpl->GetWindowHandle(), &WindowNotificationBus::Events::OnRefreshRateChanged, refreshRate); + shouldBubbleEventUp = true; break; } default: - return DefWindowProc(hWnd, message, wParam, lParam); + shouldBubbleEventUp = true; break; } - return 0; + if (!shouldBubbleEventUp) + { + return 0; + } + return DefWindowProc(hWnd, message, wParam, lParam); } void NativeWindowImpl_Win32::WindowSizeChanged(const uint32_t width, const uint32_t height) From 4cac87558901899265faec9f1bb79e7b9d42c171 Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Tue, 17 Aug 2021 08:21:39 -0500 Subject: [PATCH 090/101] [ATOM-15058] Remove Automatic Entry Point Detection (#3150) .shader files must declare at least one entry function. Signed-off-by: garrieta --- .../AzslShaderBuilderSystemComponent.cpp | 2 +- .../Code/Source/Editor/ShaderAssetBuilder.cpp | 25 +++--- .../Source/Editor/ShaderBuilderUtility.cpp | 85 ------------------- .../Code/Source/Editor/ShaderBuilderUtility.h | 8 -- .../Editor/ShaderVariantAssetBuilder.cpp | 15 ++-- .../Materials/Special/ShadowCatcher.shader | 15 ++++ .../Assets/Shaders/Depth/DepthPass.shader | 11 +++ .../Depth/DepthPassTransparentMax.shader | 11 +++ .../Depth/DepthPassTransparentMin.shader | 11 +++ 9 files changed, 65 insertions(+), 118 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp index 29e6fb7a6f..16cebef6ac 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp @@ -81,7 +81,7 @@ namespace AZ // Register Shader Asset Builder AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor; shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder"; - shaderAssetBuilderDescriptor.m_version = 102; // ATOM-15472 + shaderAssetBuilderDescriptor.m_version = 103; // ATOM-15058 // .shader file changes trigger rebuilds shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderAssetBuilderDescriptor.m_busId = azrtti_typeid(); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index 606502fb22..2332f4522b 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -226,11 +226,9 @@ namespace AZ if (!hasRasterProgram && !hasComputeProgram && !hasRayTracingProgram) { - AZStd::string entryPointNames = ShaderBuilderUtility::GetAcceptableDefaultEntryPointNames(azslData); return AZ::Failure( - AZStd::string::format( "Shader asset descriptor has a program variant that does not define any entry points. Either declare entry " - "points in the .shader file, or use one of the available default names (not case-sensitive): [%s]", - entryPointNames.c_str())); + AZStd::string( "Shader asset descriptor has a program variant that does not define any entry points." + " Please declare entry points in the .shader file.")); } return AZ::Success(attributeMaps); @@ -478,21 +476,18 @@ namespace AZ } } - // Discover entry points & type of programs. - MapOfStringToStageType shaderEntryPoints; if (shaderSourceData.m_programSettings.m_entryPoints.empty()) { - AZ_TracePrintf( - ShaderAssetBuilderName, - "ProgramSettings do not specify entry points, will use GetDefaultEntryPointsFromShader()\n"); - ShaderBuilderUtility::GetDefaultEntryPointsFromFunctionDataList(azslData.m_functions, shaderEntryPoints); + AZ_Error( ShaderAssetBuilderName, false, "ProgramSettings must specify entry points."); + response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; + return; } - else + + // Discover entry points & type of programs. + MapOfStringToStageType shaderEntryPoints; + for (const auto& entryPoint : shaderSourceData.m_programSettings.m_entryPoints) { - for (const auto& entryPoint : shaderSourceData.m_programSettings.m_entryPoints) - { - shaderEntryPoints[entryPoint.m_name] = entryPoint.m_type; - } + shaderEntryPoints[entryPoint.m_name] = entryPoint.m_type; } bool hasRasterProgram = false; diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index d7c3de48c0..0018f2ead8 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -809,91 +809,6 @@ namespace AZ return success; } - - //! Returns a list of acceptable default entry point names - static void GetAcceptableDefaultEntryPoints( - const AZStd::vector& azslFunctionDataList, - AZStd::unordered_map& defaultEntryPoints) - { - for (const auto& func : azslFunctionDataList) - { - if (!func.m_hasShaderStageVaryings) - { - // Not declaring any semantics for a shader entry is valid, but unusual. - // A shader entry with no semantics must be explicitly listed and won't be selected by default. - continue; - } - - if (func.m_name.starts_with("VS") || func.m_name.ends_with("VS")) - { - defaultEntryPoints[func.m_name] = RPI::ShaderStageType::Vertex; - AZ_TracePrintf( - ShaderBuilderUtilityName, "Assuming \"%s\" is a valid Vertex shader entry point.\n", func.m_name.c_str()); - } - else if (func.m_name.starts_with("PS") || func.m_name.ends_with("PS")) - { - defaultEntryPoints[func.m_name] = RPI::ShaderStageType::Fragment; - AZ_TracePrintf( - ShaderBuilderUtilityName, "Assuming \"%s\" is a valid Fragment shader entry point.\n", - func.m_name.c_str()); - } - else if (func.m_name.starts_with("CS") || func.m_name.ends_with("CS")) - { - defaultEntryPoints[func.m_name] = RPI::ShaderStageType::Compute; - AZ_TracePrintf( - ShaderBuilderUtilityName, "Assuming \"%s\" is a valid Compute shader entry point.\n", func.m_name.c_str()); - } - } - } - - - // DEPRECATED [ATOM-15472 - //! Returns a list of acceptable default entry point names - //! This function - static void GetAcceptableDefaultEntryPoints( - const AzslData& azslData, AZStd::unordered_map& defaultEntryPoints) - { - return GetAcceptableDefaultEntryPoints(azslData.m_functions, defaultEntryPoints); - } - - - void GetDefaultEntryPointsFromFunctionDataList( - const AZStd::vector azslFunctionDataList, - AZStd::unordered_map& shaderEntryPoints) - { - AZStd::unordered_map defaultEntryPoints; - GetAcceptableDefaultEntryPoints(azslFunctionDataList, defaultEntryPoints); - - for (const auto& functionData : azslFunctionDataList) - { - for (const auto& defaultEntryPoint : defaultEntryPoints) - { - // Equal defaults to case insensitive compares... - if (AzFramework::StringFunc::Equal(defaultEntryPoint.first.c_str(), functionData.m_name.c_str())) - { - shaderEntryPoints[defaultEntryPoint.first] = defaultEntryPoint.second; - break; // stop looping default entry points and go to the next shader function - } - } - } - } - - AZStd::string GetAcceptableDefaultEntryPointNames(const AzslData& azslData) - { - AZStd::unordered_map defaultEntryPointList; - GetAcceptableDefaultEntryPoints(azslData, defaultEntryPointList); - - AZStd::vector defaultEntryPointNamesList; - for (const auto& shaderEntryPoint : defaultEntryPointList) - { - defaultEntryPointNamesList.push_back(shaderEntryPoint.first); - } - AZStd::string shaderEntryPoints; - AzFramework::StringFunc::Join( - shaderEntryPoints, defaultEntryPointNamesList.begin(), defaultEntryPointNamesList.end(), ", "); - return AZStd::move(shaderEntryPoints); - } - } // namespace ShaderBuilderUtility } // namespace ShaderBuilder } // AZ diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h index 9310bf2e2f..c000ba9df6 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h @@ -94,10 +94,6 @@ namespace AZ RPI::ShaderOutputContract& shaderOutputContract, size_t& colorAttachmentCount); - //! Returns a list of acceptable default entry point names as a single string for debug messages. - AZStd::string GetAcceptableDefaultEntryPointNames(const AzslData& shaderData); - - //! Create a file from a string's content. //! That file will be named filename.api.azslin //! This is meant to be used at this stage: @@ -138,10 +134,6 @@ namespace AZ AZStd::vector GetSupervariantListFromShaderSourceData( const RPI::ShaderSourceData& shaderSourceData); - void GetDefaultEntryPointsFromFunctionDataList( - const AZStd::vector azslFunctionDataList, - AZStd::unordered_map& shaderEntryPoints); - void LogProfilingData(const char* builderName, AZStd::string_view shaderPath); //! Returns the asset path of a product artifact produced by ShaderAssetBuilder. diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 1da4623774..59660440e4 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -843,17 +843,14 @@ namespace AZ MapOfStringToStageType shaderEntryPoints; if (shaderSourceDescriptor.m_programSettings.m_entryPoints.empty()) { - AZ_TracePrintf( - ShaderVariantAssetBuilderName, - "ProgramSettings do not specify entry points, will use GetDefaultEntryPointsFromShader()\n"); - ShaderBuilderUtility::GetDefaultEntryPointsFromFunctionDataList(azslFunctions, shaderEntryPoints); + AZ_Error(ShaderVariantAssetBuilderName, false, "ProgramSettings must specify entry points."); + response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; + return; } - else + + for (const auto& entryPoint : shaderSourceDescriptor.m_programSettings.m_entryPoints) { - for (const auto& entryPoint : shaderSourceDescriptor.m_programSettings.m_entryPoints) - { - shaderEntryPoints[entryPoint.m_name] = entryPoint.m_type; - } + shaderEntryPoints[entryPoint.m_name] = entryPoint.m_type; } // 3- hlslCode diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.shader b/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.shader index f4784440b1..7df4169498 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.shader +++ b/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.shader @@ -18,5 +18,20 @@ "BlendOp": "Add" }, + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "ShadowCatcherVS", + "type" : "Vertex" + }, + { + "name": "ShadowCatcherPS", + "type" : "Fragment" + } + ] + }, + "DrawList": "transparent" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.shader index fe76eb06cb..463db025e7 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.shader @@ -9,5 +9,16 @@ "DisableOptimizations" : false }, + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "DepthPassVS", + "type" : "Vertex" + } + ] + }, + "DrawList" : "depth" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMax.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMax.shader index a56959e357..5bfdc8bcc1 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMax.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMax.shader @@ -13,5 +13,16 @@ "CompilerHints" : { }, + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "DepthPassVS", + "type" : "Vertex" + } + ] + }, + "DrawList" : "depthTransparentMax" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMin.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMin.shader index 709e467479..5cd8ea7c33 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMin.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMin.shader @@ -11,5 +11,16 @@ "DisableOptimizations" : false }, + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "DepthPassVS", + "type" : "Vertex" + } + ] + }, + "DrawList" : "depthTransparentMin" } From eb1593a19c7107ab5cc8f6fae8f62504da224790 Mon Sep 17 00:00:00 2001 From: amzn-victor <86271008+amzn-victor@users.noreply.github.com> Date: Tue, 17 Aug 2021 06:52:20 -0700 Subject: [PATCH 091/101] Changes to SDK wrappers and functions to allow more flexible scene file processing (#3112) These changes allow for usage of different asset import SDKs to process scene files. Move AssImp specific code out of node, scene & material wrapper parent classes and into child wrapper classes (AssImpNodeWrapper, etc.), allowing child classes to expose import SDK code. Allows for more convenient implementation of other import SDK's elsewhere (such as in a gem). Add a loadingComponentUuid parameter to LoadSceneFromVerifiedPath to allow for usage of different loading components. Changed tests and all calls to this function accordingly. * Move AssImp specific code out of wrapper parent classes and into child classes for gem usage Signed-off-by: Victor Huang * Add loadingComponentUuid parameter to LoadSceneFromVerifiedPath function Signed-off-by: Victor Huang * Make wrapper members protected, change pointer cast Signed-off-by: Victor Huang * Adding spaces to fix style Signed-off-by: Victor Huang * Fix for pointer cast causing test failures Signed-off-by: Victor Huang --- .../SceneSerializationHandler.cpp | 3 ++- .../SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp | 7 ++++++- .../SceneAPI/SDKWrapper/AssImpMaterialWrapper.h | 4 ++++ .../SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp | 6 ++++-- .../Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h | 6 +++++- .../SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp | 12 ++++++------ .../SceneAPI/SDKWrapper/AssImpSceneWrapper.h | 5 +++-- .../Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp | 15 --------------- Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h | 8 +------- Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp | 15 --------------- Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h | 8 +------- Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp | 13 ------------- Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h | 6 ------ .../Importers/AssImpMaterialImporter.cpp | 4 ++-- .../Tools/SceneAPI/SceneBuilder/SceneImporter.cpp | 7 ++++++- .../SceneCore/Events/AssetImportRequest.cpp | 4 ++-- .../SceneCore/Events/AssetImportRequest.h | 3 ++- .../Tests/Events/AssetImporterRequestTests.cpp | 13 +++++++------ .../SceneBuilder/SceneSerializationHandler.cpp | 6 ++++-- 19 files changed, 55 insertions(+), 90 deletions(-) diff --git a/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp b/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp index 441fb362d6..c087a27ba4 100644 --- a/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp +++ b/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -96,7 +97,7 @@ namespace AZ } AZStd::shared_ptr scene = - AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath, sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor); + AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath, sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid()); if (!scene) { AZ_TracePrintf(Utilities::ErrorWindow, "Failed to load the requested scene."); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp index 8ea25a2ff0..68b00eb811 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp @@ -21,11 +21,16 @@ namespace AZ { AssImpMaterialWrapper::AssImpMaterialWrapper(aiMaterial* aiMaterial) - :SDKMaterial::MaterialWrapper(aiMaterial) + :m_assImpMaterial(aiMaterial) { AZ_Assert(aiMaterial, "Asset Importer Material cannot be null"); } + aiMaterial* AssImpMaterialWrapper::GetAssImpMaterial() const + { + return m_assImpMaterial; + } + AZStd::string AssImpMaterialWrapper::GetName() const { return m_assImpMaterial->GetName().C_Str(); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.h index 8d7138db16..776e73ebfb 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.h @@ -20,6 +20,7 @@ namespace AZ AZ_RTTI(AssImpMaterialWrapper, "{66992628-CFCE-441B-8849-9344A49AFAC9}", SDKMaterial::MaterialWrapper); AssImpMaterialWrapper(aiMaterial* aiMaterial); ~AssImpMaterialWrapper() override = default; + aiMaterial* GetAssImpMaterial() const; AZStd::string GetName() const override; AZ::u64 GetUniqueId() const override; AZ::Vector3 GetDiffuseColor() const override; @@ -38,6 +39,9 @@ namespace AZ AZStd::optional GetUseEmissiveMap() const; AZStd::optional GetEmissiveIntensity() const; AZStd::optional GetUseAOMap() const; + + protected: + aiMaterial* m_assImpMaterial = nullptr; }; } // namespace AssImpSDKWrapper }// namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp index 9bd9b191ec..87583a961b 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp @@ -17,14 +17,16 @@ namespace AZ namespace AssImpSDKWrapper { AssImpNodeWrapper::AssImpNodeWrapper(aiNode* sourceNode) - :SDKNode::NodeWrapper(sourceNode) + : m_assImpNode(sourceNode) { AZ_Assert(m_assImpNode, "Asset Importer Node cannot be null"); } - AssImpNodeWrapper::~AssImpNodeWrapper() + aiNode* AssImpNodeWrapper::GetAssImpNode() const { + return m_assImpNode; } + const char* AssImpNodeWrapper::GetName() const { return m_assImpNode->mName.C_Str(); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h index bcf9eb9234..266653ca51 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h @@ -20,7 +20,8 @@ namespace AZ public: AZ_RTTI(AssImpNodeWrapper, "{1043260B-9076-49B7-AD38-EF62E85F7C1D}", SDKNode::NodeWrapper); AssImpNodeWrapper(aiNode* sourceNode); - ~AssImpNodeWrapper() override; + ~AssImpNodeWrapper() override = default; + aiNode* GetAssImpNode() const; const char* GetName() const override; AZ::u64 GetUniqueId() const override; int GetChildCount() const override; @@ -28,6 +29,9 @@ namespace AZ const bool ContainsMesh(); bool ContainsBones(const aiScene& scene) const; int GetMaterialCount() const override; + + protected: + aiNode* m_assImpNode = nullptr; }; } // namespace AssImpSDKWrapper }// namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp index 12aefca00c..14f9bc0fe3 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp @@ -25,15 +25,10 @@ namespace AZ namespace AssImpSDKWrapper { AssImpSceneWrapper::AssImpSceneWrapper() - : SDKScene::SceneWrapperBase() { } AssImpSceneWrapper::AssImpSceneWrapper(aiScene* aiScene) - : SDKScene::SceneWrapperBase(aiScene) - { - } - - AssImpSceneWrapper::~AssImpSceneWrapper() + : m_assImpScene(aiScene) { } @@ -114,6 +109,11 @@ namespace AZ m_importer.FreeScene(); } + const aiScene* AssImpSceneWrapper::GetAssImpScene() const + { + return m_assImpScene; + } + AZStd::pair AssImpSceneWrapper::GetUpVectorAndSign() const { AZStd::pair result(AxisVector::Z, 1); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h index 5747f7025d..57f82cc4b1 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h @@ -21,13 +21,14 @@ namespace AZ AZ_RTTI(AssImpSceneWrapper, "{43A61F62-DCD4-4132-B80B-F2FBC80740BC}", SDKScene::SceneWrapperBase); AssImpSceneWrapper(); AssImpSceneWrapper(aiScene* aiScene); - ~AssImpSceneWrapper(); + ~AssImpSceneWrapper() override = default; bool LoadSceneFromFile(const char* fileName) override; bool LoadSceneFromFile(const AZStd::string& fileName) override; const std::shared_ptr GetRootNode() const override; std::shared_ptr GetRootNode() override; + virtual const aiScene* GetAssImpScene() const; void Clear() override; enum class AxisVector @@ -43,7 +44,7 @@ namespace AZ AZStd::string GetSceneFileName() const { return m_sceneFileName; } protected: - + const aiScene* m_assImpScene = nullptr; Assimp::Importer m_importer; // FBX SDK automatically resolved relative paths to textures based on the current file location. diff --git a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp index 8209bd4bd0..9e7225ac9d 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp @@ -12,21 +12,6 @@ namespace AZ { namespace SDKMaterial { - MaterialWrapper::MaterialWrapper(aiMaterial* assImpMaterial) - : m_assImpMaterial(assImpMaterial) - { - } - - MaterialWrapper::~MaterialWrapper() - { - m_assImpMaterial = nullptr; - } - - aiMaterial* MaterialWrapper::GetAssImpMaterial() - { - return m_assImpMaterial; - } - AZStd::string MaterialWrapper::GetName() const { return AZStd::string(); diff --git a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h index db351f208c..53778ea783 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h @@ -34,10 +34,7 @@ namespace AZ BaseColor }; - MaterialWrapper(aiMaterial* assImpmaterial); - virtual ~MaterialWrapper(); - - aiMaterial* GetAssImpMaterial(); + virtual ~MaterialWrapper() = default; virtual AZStd::string GetName() const; virtual AZ::u64 GetUniqueId() const; @@ -47,9 +44,6 @@ namespace AZ virtual AZ::Vector3 GetEmissiveColor() const; virtual float GetOpacity() const; virtual float GetShininess() const; - - protected: - aiMaterial* m_assImpMaterial = nullptr; }; } // namespace SDKMaterial } // namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp index 21a4de7c44..6b1c4ba99a 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp @@ -12,21 +12,6 @@ namespace AZ { namespace SDKNode { - NodeWrapper::NodeWrapper(aiNode* aiNode) - : m_assImpNode(aiNode) - { - } - - NodeWrapper::~NodeWrapper() - { - m_assImpNode = nullptr; - } - - aiNode* NodeWrapper::GetAssImpNode() - { - return m_assImpNode; - } - const char* NodeWrapper::GetName() const { return ""; diff --git a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h index bef3cf0db4..dfd216912a 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h @@ -20,9 +20,7 @@ namespace AZ public: AZ_RTTI(NodeWrapper, "{5EB0897B-9728-44B7-B056-BA34AAF14715}"); - NodeWrapper() = default; - NodeWrapper(aiNode* aiNode); - virtual ~NodeWrapper(); + virtual ~NodeWrapper() = default; enum CurveNodeComponent { @@ -31,16 +29,12 @@ namespace AZ Component_Z }; - aiNode* GetAssImpNode(); - virtual const char* GetName() const; virtual AZ::u64 GetUniqueId() const; virtual int GetMaterialCount() const; virtual int GetChildCount()const; virtual const std::shared_ptr GetChild(int childIndex) const; - - aiNode* m_assImpNode = nullptr; }; } //namespace Node } //namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp index 37e92a1eac..42f07618e5 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp @@ -13,12 +13,6 @@ namespace AZ { const char* SceneWrapperBase::s_defaultSceneName = "myScene"; - SceneWrapperBase::SceneWrapperBase(aiScene* aiScene) - : m_assImpScene(aiScene) - { - } - - bool SceneWrapperBase::LoadSceneFromFile([[maybe_unused]] const char* fileName) { return false; @@ -40,12 +34,5 @@ namespace AZ void SceneWrapperBase::Clear() { } - - const aiScene* SceneWrapperBase::GetAssImpScene() const - { - return m_assImpScene; - } - - } //namespace Scene }// namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h index d4776174d9..67128134d1 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h @@ -20,9 +20,7 @@ namespace AZ { public: AZ_RTTI(SceneWrapperBase, "{703CD344-2C75-4F30-8CE2-6BDEF2511AFD}"); - SceneWrapperBase() = default; virtual ~SceneWrapperBase() = default; - SceneWrapperBase(aiScene* aiScene); virtual bool LoadSceneFromFile(const char* fileName); virtual bool LoadSceneFromFile(const AZStd::string& fileName); @@ -31,10 +29,6 @@ namespace AZ virtual std::shared_ptr GetRootNode(); virtual void Clear(); - - virtual const aiScene* GetAssImpScene() const; - - const aiScene* m_assImpScene = nullptr; static const char* s_defaultSceneName; }; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp index 8983c76bac..aa53f8be9b 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp @@ -56,9 +56,9 @@ namespace AZ Events::ProcessingResultCombiner combinedMaterialImportResults; AZStd::unordered_map> materialMap; - for (unsigned int idx = 0; idx < context.m_sourceNode.m_assImpNode->mNumMeshes; ++idx) + for (unsigned int idx = 0; idx < context.m_sourceNode.GetAssImpNode()->mNumMeshes; ++idx) { - int meshIndex = context.m_sourceNode.m_assImpNode->mMeshes[idx]; + int meshIndex = context.m_sourceNode.GetAssImpNode()->mMeshes[idx]; const aiMesh* assImpMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[meshIndex]; AZ_Assert(assImpMesh, "Asset Importer Mesh should not be null."); int materialIndex = assImpMesh->mMaterialIndex; diff --git a/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp index 3f2ec6c1eb..c0c0fe1330 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp @@ -222,7 +222,12 @@ namespace AZ int childCount = node.m_node->GetChildCount(); for (int i = 0; i < childCount; ++i) { - std::shared_ptr child = std::make_shared(node.m_node->GetChild(i)->GetAssImpNode()); + const std::shared_ptr nodeWrapper = node.m_node->GetChild(i); + auto assImpNodeWrapper = azrtti_cast(nodeWrapper.get()); + + AZ_Assert(assImpNodeWrapper, "Child node is not the expected AssImpNodeWrapper type"); + + std::shared_ptr child = std::make_shared(assImpNodeWrapper->GetAssImpNode()); if (child) { nodes.emplace(AZStd::move(child), newNode); diff --git a/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.cpp b/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.cpp index 7950eff130..a182e4f02d 100644 --- a/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.cpp @@ -104,7 +104,7 @@ namespace AZ } AZStd::shared_ptr AssetImportRequest::LoadSceneFromVerifiedPath(const AZStd::string& assetFilePath, const Uuid& sourceGuid, - RequestingApplication requester) + RequestingApplication requester, const Uuid& loadingComponentUuid) { AZStd::string sceneName; AzFramework::StringFunc::Path::GetFileName(assetFilePath.c_str(), sceneName); @@ -113,7 +113,7 @@ namespace AZ // Unique pointer, will deactivate and clean up once going out of scope. SceneCore::EntityConstructor::EntityPointer loaders = - SceneCore::EntityConstructor::BuildEntity("Scene Loading", SceneCore::LoadingComponent::TYPEINFO_Uuid()); + SceneCore::EntityConstructor::BuildEntity("Scene Loading", loadingComponentUuid); ProcessingResultCombiner areAllPrepared; AssetImportRequestBus::BroadcastResult(areAllPrepared, &AssetImportRequestBus::Events::PrepareForAssetLoading, *scene, requester); diff --git a/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.h b/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.h index 2a071a4001..8b6e119f99 100644 --- a/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.h +++ b/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.h @@ -102,8 +102,9 @@ namespace AZ //! @param sourceGuid The guid assigned to the source file (not the manifest). //! @param requester The application making the request to load the file. This can be used to optimize the type and amount of data //! to load. + //! @param loadingComponentUuid The UUID assigned to the loading component. static AZStd::shared_ptr LoadSceneFromVerifiedPath(const AZStd::string& assetFilePath, - const Uuid&sourceGuid, RequestingApplication requester); + const Uuid& sourceGuid, RequestingApplication requester, const Uuid& loadingComponentUuid); //! Utility function to determine if a given file path points to a scene manifest file (.assetinfo). //! @param filePath A relative or absolute path to the file to check. diff --git a/Code/Tools/SceneAPI/SceneCore/Tests/Events/AssetImporterRequestTests.cpp b/Code/Tools/SceneAPI/SceneCore/Tests/Events/AssetImporterRequestTests.cpp index a610cee5a4..42ddc0139c 100644 --- a/Code/Tools/SceneAPI/SceneCore/Tests/Events/AssetImporterRequestTests.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Tests/Events/AssetImporterRequestTests.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace AZ @@ -184,7 +185,7 @@ namespace AZ EXPECT_CALL(handler, UpdateManifest(_, _, _)).Times(0); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -207,7 +208,7 @@ namespace AZ EXPECT_CALL(handler, UpdateManifest(_, _, _)).Times(0); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -230,7 +231,7 @@ namespace AZ EXPECT_CALL(handler, UpdateManifest(_, _, _)).Times(0); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -253,7 +254,7 @@ namespace AZ EXPECT_CALL(handler, UpdateManifest(_, _, _)).Times(0); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -285,7 +286,7 @@ namespace AZ EXPECT_CALL(manifestHandler, UpdateManifest(_, _, _)).Times(1); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -313,7 +314,7 @@ namespace AZ EXPECT_CALL(manifestHandler, UpdateManifest(_, _, _)).Times(1); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_NE(nullptr, result); } diff --git a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneSerializationHandler.cpp b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneSerializationHandler.cpp index feab5863e6..0e3f86471c 100644 --- a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneSerializationHandler.cpp +++ b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneSerializationHandler.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace SceneBuilder { @@ -79,8 +80,9 @@ namespace SceneBuilder return nullptr; } - AZStd::shared_ptr scene = - AssetImportRequest::LoadSceneFromVerifiedPath(filePath, sceneSourceGuid, AssetImportRequest::RequestingApplication::AssetProcessor); + AZStd::shared_ptr scene = AssetImportRequest::LoadSceneFromVerifiedPath( + filePath, sceneSourceGuid, AssetImportRequest::RequestingApplication::AssetProcessor, + AZ::SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid()); if (!scene) { From b98a67e836c32bd7989e7b20d574e36af222ae21 Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Tue, 17 Aug 2021 08:21:40 -0700 Subject: [PATCH 092/101] Better error reporting on mixing skinned and unskinned meshes. (#3158) Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- .../Model/ModelAssetBuilderComponent.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index fb8708fb88..8e54e5e90f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -1235,7 +1235,8 @@ namespace AZ // ProductMesh. That large buffer gets set on the LOD directly // rather than a Mesh in the LOD. ProductMeshContentAllocInfo lodBufferInfo; - + + bool isFirstMesh = true; for (const ProductMeshContent& mesh : lodMeshList) { if (lodBufferInfo.m_uvSetFloatCounts.size() < mesh.m_uvSets.size()) @@ -1347,6 +1348,14 @@ namespace AZ if (!mesh.m_skinJointIndices.empty() && !mesh.m_skinWeights.empty()) { + if (!isFirstMesh && lodBufferInfo.m_skinInfluencesCount == 0) + { + AZ_Error( + s_builderName, false, + "Attempting to merge a mix of static and skinned meshes, this will fail on buffer generation later. Mesh with " + "name %s is skinned, but previous meshes were not skinned.", + mesh.m_name.GetCStr()); + } AZ_Assert(mesh.m_skinJointIndices.size() == mesh.m_skinWeights.size(), "Number of skin influence joint indices (%d) should match the number of weights (%d).", mesh.m_skinJointIndices.size(), mesh.m_skinWeights.size()); @@ -1363,6 +1372,11 @@ namespace AZ lodBufferInfo.m_skinInfluencesCount += numNewSkinInfluences; } + else if (lodBufferInfo.m_skinInfluencesCount > 0) + { + AZ_Error(s_builderName, false, "Attempting to merge a mix of static and skinned meshes, this will fail on buffer generation later. Mesh with name %s is not skinned, but previous meshes were skinned.", + mesh.m_name.GetCStr()); + } if (!mesh.m_morphTargetVertexData.empty()) { @@ -1375,6 +1389,7 @@ namespace AZ } meshViews.emplace_back(AZStd::move(meshView)); + isFirstMesh = false; } // Now that we have the views settled, we can just merge the mesh From 7f603c59ad99eece18a62dddd6e83dc1ee1130e9 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Tue, 17 Aug 2021 17:09:17 +0100 Subject: [PATCH 093/101] Fix for events that should have been consumed by manipulators (#3108) * fix for events that should have been consumed by manipulators making their way to the main viewport handler Signed-off-by: hultonha * add missing include for SANDBOX_API macro Signed-off-by: hultonha * add dependency on Qt::Test for AzToolsFrameworkTestCommon Signed-off-by: hultonha * fix order of buttons passed to QMouseEvent Signed-off-by: hultonha * potential fix for vtable error on linux Signed-off-by: hultonha * potential fix for vtable error on linux again Signed-off-by: hultonha --- Code/Editor/CMakeLists.txt | 4 + .../test_ViewportManipulatorController.cpp | 152 ++++++++++++++++++ Code/Editor/ViewportManipulatorController.cpp | 23 ++- Code/Editor/ViewportManipulatorController.h | 20 ++- Code/Editor/editor_lib_test_files.cmake | 1 + .../Input/QtEventToAzInputManager.cpp | 49 +++--- .../Input/QtEventToAzInputManager.h | 4 - .../UnitTest/AzToolsFrameworkTestHelpers.cpp | 29 ++++ .../UnitTest/AzToolsFrameworkTestHelpers.h | 15 ++ .../Viewport/ViewportMessages.h | 2 +- .../Framework/AzToolsFramework/CMakeLists.txt | 4 +- .../AzToolsFramework/Tests/SpinBoxTests.cpp | 25 --- 12 files changed, 253 insertions(+), 75 deletions(-) create mode 100644 Code/Editor/Lib/Tests/test_ViewportManipulatorController.cpp diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt index fca16a2093..9baa83179b 100644 --- a/Code/Editor/CMakeLists.txt +++ b/Code/Editor/CMakeLists.txt @@ -238,9 +238,13 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) 3rdParty::Qt::Core 3rdParty::Qt::Gui 3rdParty::Qt::Widgets + 3rdParty::Qt::Test Legacy::CryCommon AZ::AzToolsFramework + AZ::AzToolsFramework.Tests + AZ::AzToolsFrameworkTestCommon Legacy::EditorLib + Gem::AtomToolsFramework.Static RUNTIME_DEPENDENCIES Gem::LmbrCentral ) diff --git a/Code/Editor/Lib/Tests/test_ViewportManipulatorController.cpp b/Code/Editor/Lib/Tests/test_ViewportManipulatorController.cpp new file mode 100644 index 0000000000..a2a7617083 --- /dev/null +++ b/Code/Editor/Lib/Tests/test_ViewportManipulatorController.cpp @@ -0,0 +1,152 @@ +/* + * 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 +#include +#include +#include +#include +#include + +namespace UnitTest +{ + using AzToolsFramework::ViewportInteraction::MouseInteractionEvent; + + class EditorInteractionViewportSelectionFake : public AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Handler + { + public: + void Connect(); + void Disconnect(); + + // EditorInteractionSystemViewportSelectionRequestBus overrides ... + void SetHandler(const AzToolsFramework::ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder); + void SetDefaultHandler(); + bool InternalHandleMouseViewportInteraction(const MouseInteractionEvent& mouseInteraction); + bool InternalHandleMouseManipulatorInteraction(const MouseInteractionEvent& mouseInteraction); + + AZStd::function m_internalHandleMouseViewportInteraction; + AZStd::function m_internalHandleMouseManipulatorInteraction; + }; + + void EditorInteractionViewportSelectionFake::Connect() + { + AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); + } + + void EditorInteractionViewportSelectionFake::Disconnect() + { + AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Handler::BusDisconnect(); + } + + void EditorInteractionViewportSelectionFake::SetHandler( + [[maybe_unused]] const AzToolsFramework::ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder) + { + // noop + } + + void EditorInteractionViewportSelectionFake::SetDefaultHandler() + { + // noop + } + + bool EditorInteractionViewportSelectionFake::InternalHandleMouseViewportInteraction(const MouseInteractionEvent& mouseInteraction) + { + if (m_internalHandleMouseViewportInteraction) + { + return m_internalHandleMouseViewportInteraction(mouseInteraction); + } + + return false; + } + + bool EditorInteractionViewportSelectionFake::InternalHandleMouseManipulatorInteraction(const MouseInteractionEvent& mouseInteraction) + { + if (m_internalHandleMouseManipulatorInteraction) + { + return m_internalHandleMouseManipulatorInteraction(mouseInteraction); + } + + return false; + } + + class ViewportManipulatorControllerFixture : public AllocatorsTestFixture + { + public: + static const AzFramework::ViewportId TestViewportId = AzFramework::ViewportId(0); + + void SetUp() override + { + AllocatorsTestFixture::SetUp(); + + m_rootWidget = AZStd::make_unique(); + m_rootWidget->setFixedSize(QSize(100, 100)); + + m_controllerList = AZStd::make_shared(); + m_controllerList->RegisterViewportContext(TestViewportId); + + m_inputChannelMapper = AZStd::make_unique(m_rootWidget.get(), TestViewportId); + } + + void TearDown() + { + m_inputChannelMapper.reset(); + + m_controllerList->UnregisterViewportContext(TestViewportId); + m_controllerList.reset(); + m_rootWidget.reset(); + + AllocatorsTestFixture::TearDown(); + } + + AZStd::unique_ptr m_rootWidget; + AzFramework::ViewportControllerListPtr m_controllerList; + AZStd::unique_ptr m_inputChannelMapper; + }; + + TEST_F(ViewportManipulatorControllerFixture, An_event_is_not_propagated_to_the_viewport_when_a_manipulator_handles_it_first) + { + // forward input events to our controller list + QObject::connect( + m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(), + [this](const AzFramework::InputChannel* inputChannel, [[maybe_unused]] QEvent* event) + { + m_controllerList->HandleInputChannelEvent( + AzFramework::ViewportControllerInputEvent{ TestViewportId, nullptr, *inputChannel }); + }); + + EditorInteractionViewportSelectionFake editorInteractionViewportFake; + editorInteractionViewportFake.m_internalHandleMouseManipulatorInteraction = [](const MouseInteractionEvent&) + { + // report the event was handled (manipulator was interacted with) + return true; + }; + + bool viewportInteractionCalled = false; + editorInteractionViewportFake.m_internalHandleMouseViewportInteraction = [&viewportInteractionCalled](const MouseInteractionEvent&) + { + // we should not call this as the manipulator will have consumed this event + viewportInteractionCalled = true; + return true; + }; + + editorInteractionViewportFake.Connect(); + + m_controllerList->Add(AZStd::make_shared()); + + // simulate a press and move + MousePressAndMove(m_rootWidget.get(), QPoint(10, 10), QPoint(10, 10), Qt::MouseButton::LeftButton); + MouseMove(m_rootWidget.get(), QPoint(20, 20), QPoint(10, 10), Qt::MouseButton::LeftButton); + MouseMove(m_rootWidget.get(), QPoint(30, 30), QPoint(0, 0), Qt::MouseButton::LeftButton); + QTest::mouseRelease(m_rootWidget.get(), Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier, QPoint(30, 30)); + + // ensure the viewport did not receive the event when it was intercepted first by the manipulator + EXPECT_FALSE(viewportInteractionCalled); + + editorInteractionViewportFake.Disconnect(); + } +} // namespace UnitTest diff --git a/Code/Editor/ViewportManipulatorController.cpp b/Code/Editor/ViewportManipulatorController.cpp index 0b519f0787..5282af009f 100644 --- a/Code/Editor/ViewportManipulatorController.cpp +++ b/Code/Editor/ViewportManipulatorController.cpp @@ -28,6 +28,8 @@ namespace SandboxEditor { } + ViewportManipulatorControllerInstance::~ViewportManipulatorControllerInstance() = default; + AzToolsFramework::ViewportInteraction::MouseButton ViewportManipulatorControllerInstance::GetMouseButton( const AzFramework::InputChannel& inputChannel) { @@ -103,14 +105,21 @@ namespace SandboxEditor // Cache the ray trace results when doing manipulator interaction checks, no need to recalculate after if (event.m_priority == ManipulatorPriority) { - AzFramework::ScreenPoint screenPosition = AzFramework::ScreenPoint(0, 0); - ViewportMouseCursorRequestBus::EventResult( - screenPosition, GetViewportId(), &ViewportMouseCursorRequestBus::Events::ViewportCursorScreenPosition); + const auto* position = event.m_inputChannel.GetCustomData(); + AZ_Assert(position, "Expected PositionData2D but found nullptr"); - m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPosition; + AzFramework::WindowSize windowSize; + AzFramework::WindowRequestBus::EventResult( + windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize); + + auto screenPoint = AzFramework::ScreenPoint( + position->m_normalizedPosition.GetX() * windowSize.m_width, + position->m_normalizedPosition.GetY() * windowSize.m_height); + + m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPoint; AZStd::optional ray; ViewportInteractionRequestBus::EventResult( - ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPosition); + ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPoint); if (ray.has_value()) { @@ -118,6 +127,7 @@ namespace SandboxEditor m_mouseInteraction.m_mousePick.m_rayDirection = ray.value().direction; } } + eventType = MouseEvent::Move; } else if (auto mouseButton = GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None) @@ -217,8 +227,7 @@ namespace SandboxEditor interactionHandled, AzToolsFramework::GetEntityContextId(), targetInteractionEvent, mouseInteractionEvent); } - // Only filter button/key press events, not release events - return interactionHandled && event.m_inputChannel.IsActive(); + return interactionHandled; } void ViewportManipulatorControllerInstance::ResetInputChannels() diff --git a/Code/Editor/ViewportManipulatorController.h b/Code/Editor/ViewportManipulatorController.h index 968b6745c1..d551eb3647 100644 --- a/Code/Editor/ViewportManipulatorController.h +++ b/Code/Editor/ViewportManipulatorController.h @@ -8,25 +8,29 @@ #pragma once -#include -#include #include +#include +#include #include +#include + namespace SandboxEditor { class ViewportManipulatorControllerInstance; - using ViewportManipulatorController = AzFramework::MultiViewportController; + using ViewportManipulatorController = AzFramework:: + MultiViewportController; class ViewportManipulatorControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface { public: - explicit ViewportManipulatorControllerInstance(AzFramework::ViewportId viewport, ViewportManipulatorController* controller); + SANDBOX_API ViewportManipulatorControllerInstance(AzFramework::ViewportId viewport, ViewportManipulatorController* controller); + SANDBOX_API ~ViewportManipulatorControllerInstance(); - bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; - void ResetInputChannels() override; - void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; + SANDBOX_API bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; + SANDBOX_API void ResetInputChannels() override; + SANDBOX_API void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; private: bool IsDoubleClick(AzToolsFramework::ViewportInteraction::MouseButton) const; @@ -39,4 +43,4 @@ namespace SandboxEditor AZStd::unordered_map m_pendingDoubleClicks; AZ::ScriptTimePoint m_curTime; }; -} //namespace SandboxEditor +} // namespace SandboxEditor diff --git a/Code/Editor/editor_lib_test_files.cmake b/Code/Editor/editor_lib_test_files.cmake index c67e70ddbd..49f707b1f6 100644 --- a/Code/Editor/editor_lib_test_files.cmake +++ b/Code/Editor/editor_lib_test_files.cmake @@ -20,6 +20,7 @@ set(FILES Lib/Tests/test_ViewPanePythonBindings.cpp Lib/Tests/test_ViewportTitleDlgPythonBindings.cpp Lib/Tests/test_DisplaySettingsPythonBindings.cpp + Lib/Tests/test_ViewportManipulatorController.cpp DisplaySettingsPythonFuncs.cpp DisplaySettingsPythonFuncs.h ) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp index f8665d583e..b7776238ba 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp @@ -162,7 +162,6 @@ namespace AzToolsFramework : QObject(sourceWidget) , m_sourceWidget(sourceWidget) , m_keyboardModifiers(AZStd::make_shared()) - , m_cursorPosition(AZStd::make_shared()) { InitializeKeyMappings(); InitializeMouseButtonMappings(); @@ -230,24 +229,17 @@ namespace AzToolsFramework return false; } - // Because there's no "end" to mouse movement and wheel events, we reset mouse movement channels that have been opened - // during the next processed non-mouse event. - if (m_mouseChannelsNeedUpdate && event->type() != QEvent::Type::MouseMove && event->type() != QEvent::Type::Wheel) - { - m_cursorPosition->m_normalizedPositionDelta = AZ::Vector2::CreateZero(); - ProcessPendingMouseEvents(); - m_mouseChannelsNeedUpdate = false; - } + const auto eventType = event->type(); // Only accept mouse & key release events that originate from an object that is not our target widget, // as we don't want to erroneously intercept user input meant for another component. - if (object != m_sourceWidget && event->type() != QEvent::Type::KeyRelease && event->type() != QEvent::Type::MouseButtonRelease) + if (object != m_sourceWidget && eventType != QEvent::Type::KeyRelease && eventType != QEvent::Type::MouseButtonRelease) { return false; } // If our focus changes, go ahead and reset all input devices. - if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) + if (eventType == QEvent::FocusIn || eventType == QEvent::FocusOut) { HandleFocusChange(event); } @@ -255,27 +247,28 @@ namespace AzToolsFramework // ShortcutOverride is used in lieu of KeyPress for high priority input channels like Alt // that need to be accepted and stopped before they bubble up and cause unintended behavior. else if ( - event->type() == QEvent::Type::KeyPress || event->type() == QEvent::Type::KeyRelease || - event->type() == QEvent::Type::ShortcutOverride) + eventType == QEvent::Type::KeyPress || eventType == QEvent::Type::KeyRelease || eventType == QEvent::Type::ShortcutOverride) { QKeyEvent* keyEvent = static_cast(event); HandleKeyEvent(keyEvent); } // Map mouse events to input channels. - else if (event->type() == QEvent::Type::MouseButtonPress || event->type() == QEvent::Type::MouseButtonRelease || event->type() == QEvent::Type::MouseButtonDblClick) + else if ( + eventType == QEvent::Type::MouseButtonPress || eventType == QEvent::Type::MouseButtonRelease || + eventType == QEvent::Type::MouseButtonDblClick) { QMouseEvent* mouseEvent = static_cast(event); HandleMouseButtonEvent(mouseEvent); } // Map mouse movement to the movement input channels. // This includes SystemCursorPosition alongside Movement::X and Movement::Y. - else if (event->type() == QEvent::Type::MouseMove) + else if (eventType == QEvent::Type::MouseMove) { QMouseEvent* mouseEvent = static_cast(event); HandleMouseMoveEvent(mouseEvent); } // Map wheel events to the mouse Z movement channel. - else if (event->type() == QEvent::Type::Wheel) + else if (eventType == QEvent::Type::Wheel) { QWheelEvent* wheelEvent = static_cast(event); HandleWheelEvent(wheelEvent); @@ -303,14 +296,16 @@ namespace AzToolsFramework auto mouseWheelChannel = GetInputChannel(AzFramework::InputDeviceMouse::Movement::Z); - systemCursorChannel->ProcessRawInputEvent(m_cursorPosition->m_normalizedPositionDelta.GetLength()); + systemCursorChannel->ProcessRawInputEvent(m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetLength()); // Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation // of cursor movement velocity. movementXChannel->ProcessRawInputEvent( - m_cursorPosition->m_normalizedPositionDelta.GetX() * aznumeric_cast(m_sourceWidget->width()) / m_sourceWidget->devicePixelRatioF()); + m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetX() * aznumeric_cast(m_sourceWidget->width()) / + m_sourceWidget->devicePixelRatioF()); movementYChannel->ProcessRawInputEvent( - m_cursorPosition->m_normalizedPositionDelta.GetY() * aznumeric_cast(m_sourceWidget->height()) / m_sourceWidget->devicePixelRatioF()); - mouseWheelChannel->ProcessRawInputEvent(0.f); + m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetY() * aznumeric_cast(m_sourceWidget->height()) / + m_sourceWidget->devicePixelRatioF()); + mouseWheelChannel->ProcessRawInputEvent(0.0f); NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr); NotifyUpdateChannelIfNotIdle(movementXChannel, nullptr); @@ -358,14 +353,13 @@ namespace AzToolsFramework void QtEventToAzInputMapper::HandleMouseMoveEvent(QMouseEvent* mouseEvent) { - AZ::Vector2 lastCursorPosition = m_cursorPosition->m_normalizedPosition; + AZ::Vector2 lastCursorPosition = m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition; const QPoint mousePos = mouseEvent->pos(); const AZ::Vector2 normalizedPosition = WidgetPositionToNormalizedPosition(mousePos); - m_cursorPosition->m_normalizedPositionDelta = normalizedPosition - m_cursorPosition->m_normalizedPosition; - m_cursorPosition->m_normalizedPosition = normalizedPosition; + m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta = normalizedPosition - m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition; + m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = normalizedPosition; ProcessPendingMouseEvents(); - m_mouseChannelsNeedUpdate = true; if (m_capturingCursor) { @@ -376,7 +370,7 @@ namespace AzToolsFramework // Even though we just set the cursor position, there are edge cases such as remote desktop that will leave // the cursor position unchanged. For safety, we re-cache our last cursor position for delta generation. QPoint actualWidgetPosition = m_sourceWidget->mapFromGlobal(QCursor::pos()); - m_cursorPosition->m_normalizedPosition = WidgetPositionToNormalizedPosition(actualWidgetPosition); + m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = WidgetPositionToNormalizedPosition(actualWidgetPosition); } } @@ -427,21 +421,18 @@ namespace AzToolsFramework } cursorZChannel->ProcessRawInputEvent(aznumeric_cast(wheelAngle)); NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent); - m_mouseChannelsNeedUpdate = true; } void QtEventToAzInputMapper::HandleFocusChange(QEvent* event) { for (auto& channelData : m_channels) { - // If resetting the input device changed the channel state, submit it to the mapped channel list - // for processing. + // If resetting the input device changed the channel state, submit it to the mapped channel list for processing. if (channelData.second->IsActive()) { channelData.second->UpdateState(false); NotifyUpdateChannelIfNotIdle(channelData.second, event); } } - m_mouseChannelsNeedUpdate = false; } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h index 919d8fcc2a..0187cb2e5b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h @@ -138,8 +138,6 @@ namespace AzToolsFramework // The current keyboard modifier state used by our synthetic key input channels. AZStd::shared_ptr m_keyboardModifiers; - // The current normalized cursor position used by our synthetic system cursor event. - AZStd::shared_ptr m_cursorPosition; // A lookup table for Qt key -> AZ input channel. AZStd::unordered_map m_keyMappings; // A lookup table for Qt mouse button -> AZ input channel. @@ -152,8 +150,6 @@ namespace AzToolsFramework AZStd::unordered_map m_channels; // The source widget to map events from, used to calculate the relative mouse position within the widget bounds. QWidget* m_sourceWidget; - // Flags when mouse movement channels have been opened and may need to be closed (as there are no movement ended events). - bool m_mouseChannelsNeedUpdate = false; // Flags whether or not Qt events should currently be processed. bool m_enabled = true; // Flags whether or not the cursor is being constrained to the source widget (for invisible mouse movement). diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp index 1bec929223..6608e87784 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp @@ -27,6 +27,35 @@ using namespace AzToolsFramework; namespace UnitTest { + void MousePressAndMove( + QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton) + { + QPoint position = widget->mapToGlobal(initialPositionWidget); + QTest::mousePress(widget, mouseButton, Qt::NoModifier, position); + + MouseMove(widget, initialPositionWidget, mouseDelta, mouseButton); + } + + // Note: There are a series of bugs in Qt that appear to be preventing mouseMove events + // firing when sent through the QTest framework. This is a work around for our version + // of Qt. In future this can hopefully be simplified. See ^1 for workaround. + // More info: Issues with mouse move in Qt + // - https://bugreports.qt.io/browse/QTBUG-5232 + // - https://bugreports.qt.io/browse/QTBUG-69414 + // - https://lists.qt-project.org/pipermail/development/2019-July/036873.html + void MouseMove(QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton) + { + QPoint nextPosition = widget->mapToGlobal(initialPositionWidget + mouseDelta); + + // ^1 To ensure a mouse move event is fired we must call the test mouse move function + // and also send a mouse move event that matches. Each on their own do not appear to + // work - please see the links above for more context. + QTest::mouseMove(widget, nextPosition); + QMouseEvent mouseMoveEvent( + QEvent::MouseMove, QPointF(nextPosition), QPointF(nextPosition), Qt::NoButton, mouseButton, Qt::NoModifier); + QApplication::sendEvent(widget, &mouseMoveEvent); + } + bool TestWidget::eventFilter(QObject* watched, QEvent* event) { AZ_UNUSED(watched); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index 3c413fd21e..b3a660d0f2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -59,6 +59,21 @@ namespace UnitTest { constexpr AZStd::string_view prefabSystemSetting = "/Amazon/Preferences/EnablePrefabSystem"; + /// Performs a mouse press and move event on the provided widget. + /// @param widget The widget to perform the mouse press and move on. + /// @param initialPositionWidget The position of the mouse relative to the widget (will be remapped to a global position internally). + /// @param mouseDelta How far to move the mouse. + /// @param mouseButton The button to be used during the press and move. + void MousePressAndMove( + QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, Qt::MouseButton mouseButton = Qt::LeftButton); + + /// Performs a mouse move event on the provided widget. + /// @param widget The widget to perform the mouse move on. + /// @param initialPositionWidget The position of the mouse relative to the widget (will be remapped to a global position internally). + /// @param mouseDelta How far to move the mouse (note: mouseDelta may be zero and the mouse will only be moved to initialPosition). + /// @param mouseButton The button to be held during the move. + void MouseMove(QWidget* widget, const QPoint& initialPosition, const QPoint& mouseDelta, Qt::MouseButton mouseButton = Qt::NoButton); + /// Test widget to store QActions generated by EditorTransformComponentSelection. class TestWidget : public QWidget { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index ef1dfb0414..543d5fb3a5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -313,7 +313,7 @@ namespace AzToolsFramework //! Utility function to return EntityContextId. inline AzFramework::EntityContextId GetEntityContextId() { - AzFramework::EntityContextId entityContextId; + auto entityContextId = AzFramework::EntityContextId::CreateNull(); EditorEntityContextRequestBus::BroadcastResult(entityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); return entityContextId; diff --git a/Code/Framework/AzToolsFramework/CMakeLists.txt b/Code/Framework/AzToolsFramework/CMakeLists.txt index 62f4f43d93..4ee329bd93 100644 --- a/Code/Framework/AzToolsFramework/CMakeLists.txt +++ b/Code/Framework/AzToolsFramework/CMakeLists.txt @@ -60,6 +60,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PUBLIC AZ::AzTestShared PRIVATE + 3rdParty::Qt::Test 3rdParty::googletest::GMock 3rdParty::GoogleBenchmark AZ::AzToolsFramework @@ -76,8 +77,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PRIVATE Tests BUILD_DEPENDENCIES - PRIVATE + PUBLIC AZ::AzTestShared + PRIVATE 3rdParty::Qt::Test AZ::AzFrameworkTestShared AZ::AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp b/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp index a88cb68638..2d524cbcf4 100644 --- a/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp @@ -107,31 +107,6 @@ namespace UnitTest EXPECT_THAT(m_doubleSpinBoxWithLineEdit, Ne(nullptr)); } - // Note: There are a series of bugs in Qt that appear to be preventing mouseMove events - // firing when sent through the QTest framework. This is a work around for our version - // of Qt. In future this can hopefully be simplified. See ^1 for workaround. - // More info: Issues with mouse move in Qt - // - https://bugreports.qt.io/browse/QTBUG-5232 - // - https://bugreports.qt.io/browse/QTBUG-69414 - // - https://lists.qt-project.org/pipermail/development/2019-July/036873.html - void MousePressAndMove( - QWidget* widget, const QPoint& widgetScreenPosition, const QPoint& mouseDelta) - { - QPoint position = widget->mapToGlobal(widgetScreenPosition); - QPoint nextPosition = widget->mapToGlobal(widgetScreenPosition + mouseDelta); - - QTest::mousePress(widget, Qt::LeftButton, Qt::NoModifier, position); - - // ^1 To ensure a mouse move event is fired we must call the test mouse move function - // and also send a mouse move event that matches. Each on their own do not appear to - // work - please see the links above for more context. - QTest::mouseMove(widget, nextPosition); - QMouseEvent mouseMoveEvent( - QEvent::MouseMove, QPointF(nextPosition), QPointF(nextPosition), - Qt::NoButton, Qt::LeftButton, Qt::NoModifier); - QApplication::sendEvent(widget, &mouseMoveEvent); - } - TEST_F(SpinBoxFixture, SpinBoxMousePressAndMoveRightScrollsValue) { m_doubleSpinBox->setValue(10.0); From eb6569357b582882e4c9e9f4ed93eb1a13ac0391 Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Tue, 17 Aug 2021 11:38:10 -0500 Subject: [PATCH 094/101] {SPEC7767} Fix for PythonAssetBuilding auto tests (#3089) Fix for PythonAssetBuilding auto tests by updating the logic plus the names of the output models fix an access violation for auto complete in the console Signed-off-by: Jackson <23512001+jackalbe@users.noreply.github.com> --- .../PythonAssetBuilder/AssetBuilder_test.py | 16 +++++++------- .../AssetBuilder_test_case.py | 22 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py index 1fe60e3707..45e633a979 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py @@ -27,19 +27,19 @@ class TestPythonAssetProcessing(object): unexpected_lines = [] expected_lines = [ 'Mock asset exists', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found' + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel) found' ] timeout = 180 halt_on_unexpected = False test_directory = os.path.join(os.path.dirname(__file__)) testFile = os.path.join(test_directory, 'AssetBuilder_test_case.py') - editor.args.extend(['-NullRenderer', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile]) + editor.args.extend(['-NullRenderer', '-rhi=Null', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile]) with editor.start(): editorlog_file = os.path.join(editor.workspace.paths.project_log(), 'Editor.log') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py index c1519a6fdb..8d418222ce 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py @@ -29,21 +29,21 @@ if (assetIdString.endswith(':528cca58') is False): print ('Mock asset exists') # These tests detect if the geom_group.fbx file turns into a number of azmodel product assets -def test_azmodel_product(generatedModelAssetPath, expectedSubId): +def test_azmodel_product(generatedModelAssetPath): azModelAssetType = azlmbr.math.Uuid_CreateString('{2C7477B6-69C5-45BE-8163-BCD6A275B6D8}', 0) assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False) assetIdString = assetId.to_string() - if (assetIdString.endswith(':' + expectedSubId) is False): - raise_and_stop(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString}) for ({generatedModelAssetPath}), expected {expectedSubId}!') + if (assetId.is_valid()): + print(f'AssetId found for asset ({generatedModelAssetPath}) found') else: - print(f'Expected subId for asset ({generatedModelAssetPath}) found') + raise_and_stop(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString})!') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive.azmodel', '1024be55') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative.azmodel', '1052c94e') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive.azmodel', '10130556') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative.azmodel', '1065724d') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive.azmodel', '10d16e68') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative.azmodel', '10a71973') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel', '10412075') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel') azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt') From 2b5f77683ce5b6843c9921bf52bdf116f243b93d Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Tue, 17 Aug 2021 11:53:22 -0500 Subject: [PATCH 095/101] [ATOM-13679] ShaderAssetBuilder: Create UnitTest To Validate (#3096) * [ATOM-13679] ShaderAssetBuilder: Create UnitTest To Validate STDOUT Data Capture From MCPP azvsnprintf was being used improperly, in particular in windows if the data to print was larger than the local buffer in the stack, then azvsnprintf returns -1. Also azvsnprintf needs a +1 in buffer size to accomodate for the '\0' character at the end and that was not done. Added UnitTest to validate all cases: 1. Data to print is smaller than the local buffer. 2. Data to print is the same size as the local buffer. 3. Data to print is bigger than the local buffer. Signed-off-by: garrieta * Fix for MacOS & Linux, they require va_start to be called each time azvsnprintf is called Signed-off-by: garrieta --- .../Editor/CommonFiles/Preprocessor.cpp | 202 +++++++++--------- .../Source/Editor/CommonFiles/Preprocessor.h | 71 ++++++ .../Shader/Code/Tests/McppBinderTests.cpp | 92 ++++++++ ...om_asset_shader_builders_tests_files.cmake | 1 + 4 files changed, 262 insertions(+), 104 deletions(-) create mode 100644 Gems/Atom/Asset/Shader/Code/Tests/McppBinderTests.cpp diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp index 945f9734ca..9c77ae6b35 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp @@ -8,11 +8,6 @@ #include -#define MCPP_DLL_IMPORT 1 -#define MCPP_DONT_USE_SHORT_NAMES 1 -#include -#undef MCPP_DLL_IMPORT - #include #include @@ -31,8 +26,6 @@ #include -#include - namespace AZ { namespace ShaderBuilder @@ -83,124 +76,125 @@ namespace AZ } } - //! Binder helper to Matsui C-Pre-Processor library - class McppBinder + /////////////////////////////////////////////////////////////////////// + // McppBinder starts + bool McppBinder::StartPreprocessWithCommandLine(int argc, const char* argv[]) { - public: - McppBinder(PreprocessorData& out, bool plugERR) - : m_outputData(out), - m_plugERR(plugERR) + int errorCode = mcpp_lib_main(argc, argv); + // convert from std::ostringstring to AZStd::string + m_outputData.code = m_outStream.str().c_str(); + m_outputData.diagnostics = m_errStream.str().c_str(); + return errorCode == 0; + } + + int McppBinder::Putc_StaticHinge(int c, MCPP_OUTDEST od) + { + char asString[2] = { aznumeric_cast(c), 0 }; + return Fputs_StaticHinge(asString, od); + } + + int McppBinder::Fputs_StaticHinge(const char* s, MCPP_OUTDEST od) + { + if (!OkToLog(od)) { - // single live instance - s_mcppExclusiveProtection.lock(); - s_currentInstance = this; - SetupMcppCallbacks(); + return 0; } - ~McppBinder() + // chose the proper stream + auto& selectedStream = od == MCPP_OUT ? s_currentInstance->m_outStream : s_currentInstance->m_errStream; + auto tellBefore = selectedStream.tellp(); + // append that message to it + selectedStream << s; + return aznumeric_cast(selectedStream.tellp() - tellBefore); + } + + int McppBinder::Fprintf_StaticHinge(MCPP_OUTDEST od, const char* format, ...) + { + if (!OkToLog(od)) { - s_currentInstance = nullptr; - s_mcppExclusiveProtection.unlock(); + return 0; } + // run the formatting on stack memory first, in case it's enough + char localBuffer[DefaultFprintfBufferSize]; - bool StartPreprocessWithCommandLine(int argc, const char* argv[]) + va_list args; + + va_start(args, format); + int count = azvsnprintf(localBuffer, DefaultFprintfBufferSize, format, args); + va_end(args); + + char* result = localBuffer; + + // @result will be bound to @biggerData in case @localBuffer is not big enough. + std::unique_ptr biggerData; + // ">=" is the right comparison because in case count == bufferSize + // We will need an extra byte to accomodate the '\0' ending character. + if (count >= DefaultFprintfBufferSize) { - int errorCode = mcpp_lib_main(argc, argv); - // convert from std::ostringstring to AZStd::string - m_outputData.code = m_outStream.str().c_str(); - m_outputData.diagnostics = m_errStream.str().c_str(); - return errorCode == 0; - } - - private: - - // ====== C-API compatible "Static Hinges" (plain free functions) ====== - // : capturing-lambdas, function-objects, bind-expression; can't be decayed to function pointers, - // because they hold runtime-dynamic type-erased states. So we need intermediates - - // entry point from mcpp. hijacking its output - static int Putc_StaticHinge(int c, MCPP_OUTDEST od) - { - char asString[2] = { aznumeric_cast(c), 0 }; - return Fputs_StaticHinge(asString, od); - } - - // entry point from mcpp. hijacking its output - static int Fputs_StaticHinge(const char* s, MCPP_OUTDEST od) - { - if (!OkToLog(od)) - { - return 0; - } - // chose the proper stream - auto& selectedStream = od == MCPP_OUT ? s_currentInstance->m_outStream : s_currentInstance->m_errStream; - auto tellBefore = selectedStream.tellp(); - // append that message to it - selectedStream << s; - return aznumeric_cast(selectedStream.tellp() - tellBefore); - } - - // entry point from mcpp. hijacking its output - static int Fprintf_StaticHinge(MCPP_OUTDEST od, const char* format, ...) - { - if (!OkToLog(od)) - { - return 0; - } - // run the formatting on stack memory first, in case it's enough - constexpr int bufferSize = 256; - char localBuffer[bufferSize]; - va_list args; + // There wasn't enough space in the local store. + count++; // vsnprintf returns a size that doesn't include the null character. + biggerData.reset(new char[count]); + result = &biggerData[0]; + + // Remark: for MacOS & Linux it is important to call va_start again before + // each call to azvsnprintf. Not required for Windows. va_start(args, format); - int count = azvsnprintf(localBuffer, 256, format, args); - AZStd::unique_ptr biggerData; // will be bound to a bigger array if necessary. - char* result = localBuffer; - if (count > bufferSize) - { // there wasn't enough space in the local store. - biggerData.reset(new char[count]); - result = &biggerData[0]; // change `result`'s pointee - count = azvsnprintf(result, count, format, args); - } - AZ_Error("Preprocessor", count >= 0, "String formatting of pre-precessor output failed"); + count = azvsnprintf(result, count, format, args); va_end(args); - return Fputs_StaticHinge(result, od); } - - static void IncludeReport_StaticHinge(FILE*, const char*, const char*, const char* path) + else if (count == -1) { - s_currentInstance->m_outputData.includedPaths.insert(path); + // In Windows azvsnprintf will always return -1 if @localBuffer is not big enough, + // But it will write in @localBuffer what it could. + // See: + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/vsnprintf-vsnprintf-vsnprintf-l-vsnwprintf-vsnwprintf-l?view=msvc-160 + // In particular: "If the number of characters to write is greater than count, + // these functions return -1 indicating that output has been truncated." + + // There wasn't enough space in the local store. + // Remark: for MacOS & Linux it is important to call va_start again before + // each call to azvsnprintf. Not required for Windows. + va_start(args, format); + count = azvscprintf(format, args) + 1; // vscprintf returns a size that doesn't include the null character. + va_end(args); + + biggerData.reset(new char[count]); + result = &biggerData[0]; + + va_start(args, format); + count = azvsnprintf(result, count, format, args); + va_end(args); } - // ====== utility methods ===== + AZ_Error("Preprocessor", count >= 0, "String formatting of pre-precessor output failed"); + return Fputs_StaticHinge(result, od); + } - static bool OkToLog(MCPP_OUTDEST od) - { - bool isErrButOk = od == MCPP_ERR && s_currentInstance->m_plugERR; - return od == MCPP_OUT || isErrButOk; - } + void McppBinder::IncludeReport_StaticHinge(FILE*, const char*, const char*, const char* path) + { + s_currentInstance->m_outputData.includedPaths.insert(path); + } - static void SetupMcppCallbacks() - { - // callback for header included notification - mcpp_set_report_include_callback(IncludeReport_StaticHinge); - // callback for output redirection - mcpp_set_out_func(Putc_StaticHinge, Fputs_StaticHinge, Fprintf_StaticHinge); - } + bool McppBinder::OkToLog(MCPP_OUTDEST od) + { + bool isErrButOk = od == MCPP_ERR && s_currentInstance->m_plugERR; + return od == MCPP_OUT || isErrButOk; + } - // ====== instance data ====== - PreprocessorData& m_outputData; - std::ostringstream m_outStream, m_errStream; - bool m_plugERR; - - // ====== shared data ====== - // MCPP is a library with tons of non TLS global states, it can only be accessed by one client at a time. - static AZStd::mutex s_mcppExclusiveProtection; - static McppBinder* s_currentInstance; - }; + void McppBinder::SetupMcppCallbacks() + { + // callback for header included notification + mcpp_set_report_include_callback(IncludeReport_StaticHinge); + // callback for output redirection + mcpp_set_out_func(Putc_StaticHinge, Fputs_StaticHinge, Fprintf_StaticHinge); + } // definitions for the linker AZStd::mutex McppBinder::s_mcppExclusiveProtection; McppBinder* McppBinder::s_currentInstance = nullptr; + // McppBinder ends + /////////////////////////////////////////////////////////////////////// + bool PreprocessFile(const AZStd::string& fullPath, PreprocessorData& outputData, const PreprocessorOptions& options , bool collectDiagnostics, bool preprocessIncludedFiles) { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h index bb4388999f..9f3c770e78 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h @@ -14,6 +14,18 @@ #include #include +#define MCPP_DLL_IMPORT 1 +#define MCPP_DONT_USE_SHORT_NAMES 1 +#include +#undef MCPP_DLL_IMPORT + +#include + +namespace UnitTest +{ + class McppBinderTests; +} + namespace AZ { namespace ShaderBuilder @@ -93,5 +105,64 @@ namespace AZ AZStd::string& sourceCode, AZStd::string newFileOrigin); + //! Binder helper to Matsui C-Pre-Processor library + class McppBinder + { + public: + McppBinder(PreprocessorData& out, bool plugERR) + : m_outputData(out) + , m_plugERR(plugERR) + { + // single live instance + s_mcppExclusiveProtection.lock(); + s_currentInstance = this; + SetupMcppCallbacks(); + } + ~McppBinder() + { + s_currentInstance = nullptr; + s_mcppExclusiveProtection.unlock(); + } + + // This constant is in the header so McppBinderTests can see it. + static constexpr int DefaultFprintfBufferSize = 256; + + bool StartPreprocessWithCommandLine(int argc, const char* argv[]); + + private: + friend class ::UnitTest::McppBinderTests; + + // ====== C-API compatible "Static Hinges" (plain free functions) ====== + // : capturing-lambdas, function-objects, bind-expression; can't be decayed to function pointers, + // because they hold runtime-dynamic type-erased states. So we need intermediates + + // entry point from mcpp. hijacking its output + static int Putc_StaticHinge(int c, MCPP_OUTDEST od); + + // entry point from mcpp. hijacking its output + static int Fputs_StaticHinge(const char* s, MCPP_OUTDEST od); + + // entry point from mcpp. hijacking its output + static int Fprintf_StaticHinge(MCPP_OUTDEST od, const char* format, ...); + + static void IncludeReport_StaticHinge(FILE*, const char*, const char*, const char* path); + + // ====== utility methods ===== + + static bool OkToLog(MCPP_OUTDEST od); + + static void SetupMcppCallbacks(); + + // ====== instance data ====== + PreprocessorData& m_outputData; + std::ostringstream m_outStream, m_errStream; + bool m_plugERR; + + // ====== shared data ====== + // MCPP is a library with tons of non TLS global states, it can only be accessed by one client at a time. + static AZStd::mutex s_mcppExclusiveProtection; + static McppBinder* s_currentInstance; + }; + } // ShaderBuilder } // AZ diff --git a/Gems/Atom/Asset/Shader/Code/Tests/McppBinderTests.cpp b/Gems/Atom/Asset/Shader/Code/Tests/McppBinderTests.cpp new file mode 100644 index 0000000000..926f9b0a76 --- /dev/null +++ b/Gems/Atom/Asset/Shader/Code/Tests/McppBinderTests.cpp @@ -0,0 +1,92 @@ +/* + * 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 +#include + +#include "Common/ShaderBuilderTestFixture.h" + +#include + +namespace UnitTest +{ + using namespace AZ; + + // The main purpose of this class is to test ShaderBuilder::McppBinder::Fprintf_StaticHinge() + // Which has three common scenarios to validate. + // 1- The formatted string is expected to yield less bytes than McppBinder::DefaultFprintfBufferSize. + // 2- The formatted string is expected to yield exactly McppBinder::DefaultFprintfBufferSize number of bytes. + // 3- The formatted string is expectedc to yield more bytes than McppBinder::DefaultFprintfBufferSize. + class McppBinderTests : public ShaderBuilderTestFixture + { + public: + + // Fills @buffer with 'a' to 'z' for up to @bufferSize number of bytes. + // This function will null('\0') char terminate @buffer. + void FillBufferWithAlphabet(char* buffer, int bufferSize) + { + for (int bufferPos = 0, rollback = 0; bufferPos < (bufferSize - 1); ++bufferPos) + { + const char value = 'a' + rollback++; + buffer[bufferPos] = value; + if (value == 'z') + { + rollback = 0; + } + } + buffer[bufferSize - 1] = '\0'; + } + + // Pushes the null terminated string, @inputString, into McppBinder capture stream + // using McppBinder::Fprintf_StaticHinge(). + // Returns the content of the McppBinder capture stream as a string. + AZStd::string PrintStringThroughStaticHinge(const char* inputString) + { + ShaderBuilder::PreprocessorData preprocessorData; + ShaderBuilder::McppBinder mcppBinder(preprocessorData, false); + ShaderBuilder::McppBinder::Fprintf_StaticHinge(MCPP_OUTDEST::MCPP_OUT, "%s", inputString); + // convert from std::ostringstring to AZStd::string + return AZStd::string(mcppBinder.m_outStream.str().c_str()); + } + }; // class McppBinderTests + + + TEST_F(McppBinderTests, ShouldPrintLessBytesThanDefaultSize) + { + constexpr int bufferSize = (ShaderBuilder::McppBinder::DefaultFprintfBufferSize / 2) + 1; + EXPECT_TRUE(bufferSize > 0); + char buffer[bufferSize] = ""; + FillBufferWithAlphabet(buffer, bufferSize); + auto printedString = PrintStringThroughStaticHinge(buffer); + EXPECT_EQ(AZStd::string(buffer), printedString); + } + + TEST_F(McppBinderTests, ShouldPrintSameBytesAsDefaultSize) + { + constexpr int bufferSize = ShaderBuilder::McppBinder::DefaultFprintfBufferSize + 1; + EXPECT_TRUE(bufferSize > 0); + char buffer[bufferSize] = ""; + FillBufferWithAlphabet(buffer, bufferSize); + auto printedString = PrintStringThroughStaticHinge(buffer); + EXPECT_EQ(AZStd::string(buffer), printedString); + } + + TEST_F(McppBinderTests, ShouldPrintMoreBytesThanDefaultSize) + { + constexpr int bufferSize = (ShaderBuilder::McppBinder::DefaultFprintfBufferSize * 2) + 1; + EXPECT_TRUE(bufferSize > 0); + char buffer[bufferSize] = ""; + FillBufferWithAlphabet(buffer, bufferSize); + auto printedString = PrintStringThroughStaticHinge(buffer); + EXPECT_EQ(AZStd::string(buffer), printedString); + } + +} //namespace UnitTest + +//AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); + diff --git a/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake b/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake index bfddb5ce8e..033b399478 100644 --- a/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake +++ b/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake @@ -10,4 +10,5 @@ set(FILES Tests/Common/ShaderBuilderTestFixture.h Tests/Common/ShaderBuilderTestFixture.cpp Tests/SupervariantCmdArgumentTests.cpp + Tests/McppBinderTests.cpp ) From a20428d3933beb532430e09950ef26b104bc982f Mon Sep 17 00:00:00 2001 From: mnaumov Date: Mon, 16 Aug 2021 23:16:04 -0700 Subject: [PATCH 096/101] Fixing non unity build Signed-off-by: Mikhail Naumov --- .../AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h index 77b4b752a6..7cab24ad9f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h @@ -159,6 +159,8 @@ namespace AzToolsFramework struct LinkIdMetadata { AZ_RTTI(LinkIdMetadata, "{8FF7D299-14E3-41D4-90C5-393A240FAE7C}"); + + virtual ~LinkIdMetadata() {} }; } // namespace PrefabDomUtils } // namespace Prefab From 8f4a35b146af277ad903ab5522c33a2362ce2cb7 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 17 Aug 2021 13:21:13 -0500 Subject: [PATCH 097/101] AtomTools: fix unused variable errors Signed-off-by: Guthrie Adams --- .../Code/Source/Document/AtomToolsDocument.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp index 48212fe154..e8eb9401d4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -40,29 +40,35 @@ namespace AtomToolsFramework const AZStd::any& AtomToolsDocument::GetPropertyValue(const AZ::Name& propertyFullName) const { + AZ_UNUSED(propertyFullName); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return m_invalidValue; } const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty(const AZ::Name& propertyFullName) const { + AZ_UNUSED(propertyFullName); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return m_invalidProperty; } bool AtomToolsDocument::IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const { + AZ_UNUSED(propertyGroupFullName); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } void AtomToolsDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) { + AZ_UNUSED(propertyFullName); + AZ_UNUSED(value); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); } bool AtomToolsDocument::Open(AZStd::string_view loadPath) { + AZ_UNUSED(loadPath); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } @@ -81,6 +87,7 @@ namespace AtomToolsFramework bool AtomToolsDocument::SaveAsCopy(AZStd::string_view savePath) { + AZ_UNUSED(savePath); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } @@ -88,6 +95,7 @@ namespace AtomToolsFramework bool AtomToolsDocument::SaveAsChild(AZStd::string_view savePath) { + AZ_UNUSED(savePath); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } From e865ad5d2368096caf00896dd0fdb0eee846c139 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard <64656371+jcbhl@users.noreply.github.com> Date: Tue, 17 Aug 2021 11:33:13 -0700 Subject: [PATCH 098/101] Profiler: implement loading from saved captures (#3026) * Profiler: implement loading from saved capture Adds functionality for finding a saved capture on disk and then deserializing it using rapidjson's built-in buffered stream reader. This does require use of raw file pointers since saved captures can be hundreds of megabytes. Actually showing the data in the visualizer is TODO. * Profiler: use heap buffer over stack buffer * Profiler: move deserialization logic to ImGuiCpuProfiler Signed-off-by: Jacob Hilliard --- .../ProfilingCaptureSystemComponent.cpp | 98 +----------- .../Code/Include/Atom/RHI/CpuProfilerImpl.h | 31 +++- .../RHI/Code/Source/RHI/CpuProfilerImpl.cpp | 63 +++++++- .../Include/Atom/RPI.Edit/Common/JsonUtils.h | 3 +- .../Include/Atom/Utils/ImGuiCpuProfiler.h | 15 ++ .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 151 +++++++++++++++++- 6 files changed, 260 insertions(+), 101 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index add6d0e098..7c6dfcf744 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -9,6 +9,7 @@ #include "ProfilingCaptureSystemComponent.h" #include +#include #include #include #include @@ -141,36 +142,6 @@ namespace AZ AZStd::vector m_pipelineStatisticsEntries; }; - // Intermediate class to serialize Cpu TimedRegion data. - class CpuProfilingStatisticsSerializer - { - public: - class CpuProfilingStatisticsSerializerEntry - { - public: - AZ_TYPE_INFO(CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry, "{26B78F65-EB96-46E2-BE7E-A1233880B225}"); - static void Reflect(AZ::ReflectContext* context); - - CpuProfilingStatisticsSerializerEntry() = default; - CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion); - - private: - Name m_groupName; - Name m_regionName; - uint16_t m_stackDepth; - AZStd::sys_time_t m_startTick; - AZStd::sys_time_t m_endTick; - }; - - AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}"); - static void Reflect(AZ::ReflectContext* context); - - CpuProfilingStatisticsSerializer() = default; - CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData); - - AZStd::vector m_cpuProfilingStatisticsSerializerEntries; - }; - // Intermediate class to serialize benchmark metadata. class BenchmarkMetadataSerializer { @@ -327,65 +298,6 @@ namespace AZ } } - // --- CpuProfilingStatisticsSerializer --- - - CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData) - { - // Create serializable entries - for (const auto& timeRegionMap : continuousData) - { - for (const auto& threadEntry : timeRegionMap) - { - for (const auto& cachedRegionEntry : threadEntry.second) - { - m_cpuProfilingStatisticsSerializerEntries.insert( - m_cpuProfilingStatisticsSerializerEntries.end(), - cachedRegionEntry.second.begin(), - cachedRegionEntry.second.end()); - } - } - } - } - - void CpuProfilingStatisticsSerializer::Reflect(AZ::ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("cpuProfilingStatisticsSerializerEntry", &CpuProfilingStatisticsSerializer::m_cpuProfilingStatisticsSerializerEntries) - ; - } - - CpuProfilingStatisticsSerializerEntry::Reflect(context); - } - - // --- CpuProfilingStatisticsSerializerEntry --- - - CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion) - { - m_groupName = cachedTimeRegion.m_groupRegionName->m_groupName; - m_regionName = cachedTimeRegion.m_groupRegionName->m_regionName; - m_stackDepth = cachedTimeRegion.m_stackDepth; - m_startTick = cachedTimeRegion.m_startTick; - m_endTick = cachedTimeRegion.m_endTick; - } - - void CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::Reflect(AZ::ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("groupName", &CpuProfilingStatisticsSerializerEntry::m_groupName) - ->Field("regionName", &CpuProfilingStatisticsSerializerEntry::m_regionName) - ->Field("stackDepth", &CpuProfilingStatisticsSerializerEntry::m_stackDepth) - ->Field("startTick", &CpuProfilingStatisticsSerializerEntry::m_startTick) - ->Field("endTick", &CpuProfilingStatisticsSerializerEntry::m_endTick) - ; - } - } - // --- BenchmarkMetadataSerializer --- BenchmarkMetadataSerializer::BenchmarkMetadataSerializer(const AZStd::string& benchmarkName, const RHI::PhysicalDeviceDescriptor& gpuDescriptor) @@ -458,7 +370,7 @@ namespace AZ TimestampSerializer::Reflect(context); CpuFrameTimeSerializer::Reflect(context); PipelineStatisticsSerializer::Reflect(context); - CpuProfilingStatisticsSerializer::Reflect(context); + RHI::CpuProfilingStatisticsSerializer::Reflect(context); BenchmarkMetadataSerializer::Reflect(context); } @@ -651,10 +563,10 @@ namespace AZ JsonSerializerSettings serializationSettings; serializationSettings.m_keepDefaults = true; - CpuProfilingStatisticsSerializer serializer(data); + RHI::CpuProfilingStatisticsSerializer serializer(data); const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer, - outputFilePath, (CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings); + outputFilePath, (RHI::CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings); AZStd::string captureInfo = outputFilePath; if (!saveResult.IsSuccess()) @@ -694,7 +606,7 @@ namespace AZ const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]() { // Blocking call for a single frame of data, avoid thread overhead - AZStd::ring_buffer singleFrameData; + AZStd::ring_buffer singleFrameData(1); singleFrameData.push_back(RHI::CpuProfiler::Get()->GetTimeRegionMap()); SerializeCpuProfilingData(singleFrameData, outputFilePath, wasEnabled); }); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h index 2e4ca67db8..9372977d8e 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -161,5 +162,33 @@ namespace AZ AZStd::ring_buffer m_continuousCaptureData; }; - }; // namespace RPI + // Intermediate class to serialize Cpu TimedRegion data. + class CpuProfilingStatisticsSerializer + { + public: + class CpuProfilingStatisticsSerializerEntry + { + public: + AZ_TYPE_INFO(CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry, "{26B78F65-EB96-46E2-BE7E-A1233880B225}"); + static void Reflect(AZ::ReflectContext* context); + + CpuProfilingStatisticsSerializerEntry() = default; + CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion); + + Name m_groupName; + Name m_regionName; + uint16_t m_stackDepth; + AZStd::sys_time_t m_startTick; + AZStd::sys_time_t m_endTick; + }; + + AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}"); + static void Reflect(AZ::ReflectContext* context); + + CpuProfilingStatisticsSerializer() = default; + CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData); + + AZStd::vector m_cpuProfilingStatisticsSerializerEntries; + }; + }; // namespace RHI }; // namespace AZ diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index d41b5d656e..5585cc7032 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -409,5 +409,64 @@ namespace AZ m_cachedTimeRegionMutex.unlock(); } } - } -} + + // --- CpuProfilingStatisticsSerializer --- + + CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData) + { + // Create serializable entries + for (const auto& timeRegionMap : continuousData) + { + for (const auto& threadEntry : timeRegionMap) + { + for (const auto& cachedRegionEntry : threadEntry.second) + { + m_cpuProfilingStatisticsSerializerEntries.insert( + m_cpuProfilingStatisticsSerializerEntries.end(), + cachedRegionEntry.second.begin(), + cachedRegionEntry.second.end()); + } + } + } + } + + void CpuProfilingStatisticsSerializer::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("cpuProfilingStatisticsSerializerEntries", &CpuProfilingStatisticsSerializer::m_cpuProfilingStatisticsSerializerEntries) + ; + } + + CpuProfilingStatisticsSerializerEntry::Reflect(context); + } + + // --- CpuProfilingStatisticsSerializerEntry --- + + CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion) + { + m_groupName = cachedTimeRegion.m_groupRegionName->m_groupName; + m_regionName = cachedTimeRegion.m_groupRegionName->m_regionName; + m_stackDepth = cachedTimeRegion.m_stackDepth; + m_startTick = cachedTimeRegion.m_startTick; + m_endTick = cachedTimeRegion.m_endTick; + } + + void CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("groupName", &CpuProfilingStatisticsSerializerEntry::m_groupName) + ->Field("regionName", &CpuProfilingStatisticsSerializerEntry::m_regionName) + ->Field("stackDepth", &CpuProfilingStatisticsSerializerEntry::m_stackDepth) + ->Field("startTick", &CpuProfilingStatisticsSerializerEntry::m_startTick) + ->Field("endTick", &CpuProfilingStatisticsSerializerEntry::m_endTick) + ; + } + } + } // namespace RHI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h index 3e3fbec8fe..549f787ac9 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h @@ -10,7 +10,9 @@ #include #include + #include + #include #include @@ -118,7 +120,6 @@ namespace AZ AZ_Error("AZ::RPI::JsonUtils", false, "Failed to load object from json string: %s", loadResult.GetError().c_str()); return false; } - } // namespace JsonUtils } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index 75b7ec9fdd..bdaf38a64a 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include @@ -102,6 +103,12 @@ namespace AZ //! Draws the statistical view of the CPU profiling data. void DrawStatisticsView(); + //! Callback invoked when the "Load File" button is pressed in the file picker. + void LoadFile(); + + //! Draws the file picker window. + void DrawFilePicker(); + //! Draws the CPU profiling visualizer. void DrawVisualizer(); @@ -198,6 +205,14 @@ namespace AZ AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause; AZStd::string m_lastCapturedFilePath; + + bool m_showFilePicker = false; + + // Cached file paths to previous traces on disk, sorted with the most recent trace at the front. + AZStd::vector m_cachedCapturePaths; + + // Index into the file picker, used to determine which file to load when "Load File" is pressed. + int m_currentFileIndex = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index a24fdbf1d8..9b4eebf043 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -9,9 +9,14 @@ #include #include #include +#include +#include #include -#include +#include +#include +#include +#include #include #include #include @@ -45,6 +50,74 @@ namespace AZ AZ_Assert(ticksPerSecond >= 1000, "Error in converting ticks to ms, expected ticksPerSecond >= 1000"); return static_cast((ticks * 1000) / (ticksPerSecond / 1000)) / 1000.0f; } + + using DeserializedCpuData = AZStd::vector; + inline Outcome LoadSavedCpuProfilingStatistics(const AZStd::string& capturePath) + { + auto* base = IO::FileIOBase::GetInstance(); + + char resolvedPath[IO::MaxPathLength]; + if (!base->ResolvePath(capturePath.c_str(), resolvedPath, IO::MaxPathLength)) + { + return Failure(AZStd::string::format("Could not resolve the path to file %s, is the path correct?", resolvedPath)); + } + + u64 captureSizeBytes; + const IO::Result fileSizeResult = base->Size(resolvedPath, captureSizeBytes); + if (!fileSizeResult) + { + return Failure(AZStd::string::format("Could not read the size of file %s, is the path correct?", resolvedPath)); + } + + // NOTE: this uses raw file pointers over the abstractions and utility functions provided by AZ::JsonSerializationUtils because + // saved profiling captures can be upwards of 400 MB. This necessitates a buffered approach to avoid allocating huge chunks of memory. + FILE* fp = nullptr; + azfopen(&fp, resolvedPath, "rb"); + if (!fp) + { + return Failure(AZStd::string::format("Could not fopen file %s, is the path correct?\n", resolvedPath)); + } + + constexpr AZStd::size_t MaxBufSize = 65536; + const AZStd::size_t bufSize = AZStd::min(MaxBufSize, aznumeric_cast(captureSizeBytes)); + char* buf = reinterpret_cast(azmalloc(bufSize)); + + rapidjson::Document document; + rapidjson::FileReadStream inputStream(fp, buf, bufSize); + document.ParseStream(inputStream); + + azfree(buf); + fclose(fp); + + if (document.HasParseError()) + { + const auto pe = document.GetParseError(); + return Failure(AZStd::string::format( + "Rapidjson could not parse the document with ParseErrorCode %u. See 3rdParty/rapidjson/error.h for definitions.\n", pe)); + } + + if (!document.IsObject() || !document.HasMember("ClassData")) + { + return Failure(AZStd::string::format( + "Error in loading saved capture: top-level object does not have a ClassData field. Did the serialization format change recently?\n")); + } + + AZ_TracePrintf("JsonUtils", "Successfully loaded JSON into memory.\n"); + + const auto& root = document["ClassData"]; + RHI::CpuProfilingStatisticsSerializer serializer; + const JsonSerializationResult::ResultCode deserializationResult = JsonSerialization::Load(serializer, root); + if (deserializationResult.GetProcessing() == JsonSerializationResult::Processing::Halted + || serializer.m_cpuProfilingStatisticsSerializerEntries.empty()) + { + return Failure(AZStd::string::format("Error in deserializing document: %s\n", deserializationResult.ToString(capturePath.c_str()).c_str())); + } + + AZ_TracePrintf("JsonUtils", "Successfully loaded CPU profiling data with %zu profiling entries.\n", + serializer.m_cpuProfilingStatisticsSerializerEntries.size()); + + return Success(AZStd::move(serializer.m_cpuProfilingStatisticsSerializerEntries)); + } } // namespace CpuProfilerImGuiHelper inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics) @@ -80,6 +153,11 @@ namespace AZ { DrawStatisticsView(); } + + if (m_showFilePicker) + { + DrawFilePicker(); + } } ImGui::End(); @@ -110,6 +188,11 @@ namespace AZ inline void ImGuiCpuProfiler::DrawCommonHeader() { + if (!m_lastCapturedFilePath.empty()) + { + ImGui::Text("Saved: %s", m_lastCapturedFilePath.c_str()); + } + if (ImGui::Button(m_enableVisualizer ? "Swap to statistics" : "Swap to visualizer")) { m_enableVisualizer = !m_enableVisualizer; @@ -157,10 +240,31 @@ namespace AZ } } - if (!m_lastCapturedFilePath.empty()) + ImGui::SameLine(); + if (ImGui::Button("Load file")) { - ImGui::SameLine(); - ImGui::Text("Saved: %s", m_lastCapturedFilePath.c_str()); + m_showFilePicker = true; + + // Only update the cached file list when opened so that we aren't making IO calls on every frame. + auto* base = AZ::IO::FileIOBase::GetInstance(); + const AZStd::string defaultSavedCapturePath = "@user@/CpuProfiler"; + + m_cachedCapturePaths.clear(); + base->FindFiles( + defaultSavedCapturePath.c_str(), "*.json", + [&paths = m_cachedCapturePaths](const char* path) -> bool + { + auto foundPath = IO::Path(path); + paths.push_back(foundPath); + return true; + }); + + // Sort by decreasing modification time (most recent at the top) + AZStd::sort(m_cachedCapturePaths.begin(), m_cachedCapturePaths.end(), + [&base](const IO::Path& lhs, const IO::Path& rhs) + { + return base->ModificationTime(lhs.c_str()) > base->ModificationTime(rhs.c_str()); + }); } } @@ -313,6 +417,45 @@ namespace AZ } } + inline void ImGuiCpuProfiler::DrawFilePicker() + { + ImGui::SetNextWindowSize({ 500, 200 }, ImGuiCond_Once); + if (ImGui::Begin("File Picker", &m_showFilePicker)) + { + if (ImGui::Button("Load selected")) + { + LoadFile(); + } + + auto getter = [](void* vectorPointer, int idx, const char** out_text) -> bool + { + const auto& pathVec = *static_cast*>(vectorPointer); + if (idx < 0 || idx >= pathVec.size()) + { + return false; + } + *out_text = pathVec[idx].c_str(); + return true; + }; + + ImGui::SetNextItemWidth(ImGui::GetWindowContentRegionWidth()); + ImGui::ListBox("", &m_currentFileIndex, getter, &m_cachedCapturePaths, aznumeric_cast(m_cachedCapturePaths.size())); + } + ImGui::End(); + } + + inline void ImGuiCpuProfiler::LoadFile() + { + const IO::Path& pathToLoad = m_cachedCapturePaths[m_currentFileIndex]; + auto res = CpuProfilerImGuiHelper::LoadSavedCpuProfilingStatistics(pathToLoad.String()); + if (!res.IsSuccess()) + { + AZ_TracePrintf("ImGuiCpuProfiler", "%s", res.GetError().c_str()); + return; + } + // TODO ATOM-16022 Parse this data and display it in the visualizer widget. + } + // -- CPU Visualizer -- inline void ImGuiCpuProfiler::DrawVisualizer() { From fb05beffe3c7059f14e0a13f269b8e150ad25456 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 17 Aug 2021 12:05:51 -0700 Subject: [PATCH 099/101] Change LY_UNITY_BUILD default to "ON" (#3244) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/LYWrappers.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index e4398099d1..1a8e805f91 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -6,7 +6,7 @@ # # -set(LY_UNITY_BUILD OFF CACHE BOOL "UNITY builds") +set(LY_UNITY_BUILD ON CACHE BOOL "UNITY builds") include(CMakeFindDependencyMacro) include(cmake/LyAutoGen.cmake) From 401d0c1ad5e17a03409eb5267271ff6504df4f86 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Tue, 17 Aug 2021 15:17:48 -0700 Subject: [PATCH 100/101] Update the AWSNativeSDK version and hash for Mac (#3259) --- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index e66dfdaca1..a0001d3e4e 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -32,7 +32,7 @@ ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev2-ma ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac TARGETS SPIRVCross PACKAGE_HASH 78c6376ed2fd195b9b1f5fb2b56e5267a32c3aa21fb399e905308de470eb4515) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) -ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-mac TARGETS AWSNativeSDK PACKAGE_HASH 21920372e90355407578b45ac19580df1463a39a25a867bcd0ffd8b385c8254a) +ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-mac TARGETS AWSNativeSDK PACKAGE_HASH 89e1651cde6b4e6bd80cdb96ed6b624accad9f9688ff38bfca226777f4fcb678) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-mac TARGETS PhysX PACKAGE_HASH 5e092a11d5c0a50c4dd99bb681a04b566a4f6f29aa08443d9bffc8dc12c27c8e) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818) From 3e51240a05117c9573f91392e8ee4acecd3e9293 Mon Sep 17 00:00:00 2001 From: Shirang Jia Date: Tue, 17 Aug 2021 15:25:32 -0700 Subject: [PATCH 101/101] Allow customized Jenkins parameters for different pipelines and add aws integration deployment pipeline (#3248) Allow customized Jenkins parameters for different pipelines so that we can define different Jenkins parameters for a new pipeline and doesn't affect AR build parameters. Add aws integration deployment pipeline. --- scripts/build/Jenkins/Jenkinsfile | 34 +++++++++++++++++++ .../build/Platform/Windows/build_config.json | 5 +++ scripts/build/Platform/Windows/pipeline.json | 32 +++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 30efdc00ad..1c0409ceec 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -634,6 +634,40 @@ try { pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) } } + // Add additional Jenkins parameters + pipelineConfig.platforms.each { platform -> + platformEnv = platform.value.PIPELINE_ENV + pipelineJenkinsParameters = platformEnv['PIPELINE_JENKINS_PARAMETERS'] ?: [:] + jenkinsParametersToAdd = pipelineJenkinsParameters[pipelineName] ?: [:] + jenkinsParametersToAdd.each{ jenkinsParameter -> + defaultValue = jenkinsParameter['default_value'] + // Use last run's value as default value so we can save values in different Jenkins environment + if (jenkinsParameter['use_last_run_value']?.toBoolean()) { + defaultValue = params."$jenkinsParameter['parameter_name']" ?: jenkinsParameter['default_value'] + } + switch (jenkinsParameter['parameter_type']) { + case 'string': + pipelineParameters.add(stringParam(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + case 'boolean': + pipelineParameters.add(booleanParam(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + case 'password': + pipelineParameters.add(password(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + } + } + } + pipelineProperties.add(parameters(pipelineParameters)) properties(pipelineProperties) diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 0268412aea..8928794a43 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -376,5 +376,10 @@ "install_profile_vs2019", "project_engineinstall_profile_vs2019" ] + }, + "awsi_deployment": { + "TAGS": ["awsi-deployment"], + "COMMAND": "deploy_cdk_applications.cmd", + "PARAMETERS": {} } } diff --git a/scripts/build/Platform/Windows/pipeline.json b/scripts/build/Platform/Windows/pipeline.json index 622fa9d5ae..4cfc6f696a 100644 --- a/scripts/build/Platform/Windows/pipeline.json +++ b/scripts/build/Platform/Windows/pipeline.json @@ -16,5 +16,37 @@ "nightly-clean": { "CLEAN_WORKSPACE": true } + }, + "PIPELINE_JENKINS_PARAMETERS": { + "awsi-deployment": [ + { + "parameter_name": "O3DE_AWS_PROJECT_NAME", + "parameter_type": "string", + "default_value": "", + "use_last_run_value": true, + "description": "" + }, + { + "parameter_name": "O3DE_AWS_DEPLOY_REGION", + "parameter_type": "string", + "default_value": "", + "use_last_run_value": true, + "description": "" + }, + { + "parameter_name": "ASSUME_ROLE_ARN", + "parameter_type": "string", + "default_value": "", + "use_last_run_value": true, + "description": "" + }, + { + "parameter_name": "COMMIT_ID", + "parameter_type": "string", + "default_value": "", + "use_last_run_value": true, + "description": "" + } + ] } } \ No newline at end of file