From e0d0bbfdaed37487b74cb02cd0156bd43b203347 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Tue, 3 Aug 2021 13:12:37 -0700 Subject: [PATCH 01/37] 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 02/37] 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 f85e8124a9ee10e2e337877d2f67e9033fa8eff4 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Mon, 9 Aug 2021 16:17:23 -0700 Subject: [PATCH 03/37] 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 04/37] 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 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 05/37] 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 06/37] 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 07/37] 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 08/37] 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 09/37] 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 10/37] 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 f1e8d37b86cc0eadad974a77c8e128af5317f1ba Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 11 Aug 2021 14:55:28 -0500 Subject: [PATCH 11/37] 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 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 12/37] 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 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 13/37] 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 5fd2d8e7eedac494aab05a17c7e2ee0694f5b74a Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 12 Aug 2021 10:48:09 -0500 Subject: [PATCH 14/37] 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 30fee96c435cae1276a6457d287382f610f62f23 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 12 Aug 2021 22:11:18 -0500 Subject: [PATCH 15/37] 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 364ac5150272c2931a1df36e277af8a913d1e00c Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 13 Aug 2021 00:19:43 -0500 Subject: [PATCH 16/37] 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 716089e803645f5b08f2b847d5e8c83d75a831e2 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Fri, 13 Aug 2021 09:57:40 -0700 Subject: [PATCH 17/37] 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 693b205747809ab0b6804fdd6975654e37c17cc4 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Fri, 13 Aug 2021 16:56:27 -0700 Subject: [PATCH 18/37] 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 2fa9a831b3d09240d786d0636a173f9c9d169fd7 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 13 Aug 2021 20:26:49 -0500 Subject: [PATCH 19/37] 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 fe3b30e42ca96e97c4609de60daacde6d3f4fe60 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 14 Aug 2021 14:07:36 -0500 Subject: [PATCH 20/37] 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 21/37] 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 22/37] 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 994403bfa018dd96e8494c5b57fa8ba08b849819 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 16 Aug 2021 11:56:50 -0500 Subject: [PATCH 23/37] 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 1c7f71f93a5bd42700f7f750d97ce50424048b13 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 16 Aug 2021 12:13:32 -0500 Subject: [PATCH 24/37] 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 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 25/37] 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 26/37] 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 27/37] 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 f76d09e2158bc6a310083f085cfc9dc99bf1be9e Mon Sep 17 00:00:00 2001 From: pereslav Date: Tue, 17 Aug 2021 00:19:57 +0100 Subject: [PATCH 28/37] 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 29/37] 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 30/37] 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 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 31/37] 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 32/37] 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 33/37] [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 34/37] 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 35/37] 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 36/37] 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 37/37] {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')