123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AzCore/Asset/AssetManagerBus.h>
- #include <AzCore/Component/ComponentApplicationBus.h>
- #include <AzCore/Serialization/EditContext.h>
- #include <AzCore/Serialization/IdUtils.h>
- #include <AzCore/Serialization/Json/RegistrationContext.h>
- #include <AzCore/Serialization/Utils.h>
- #include <AzFramework/Asset/AssetSystemBus.h>
- #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
- #include <AzToolsFramework/API/ToolsApplicationAPI.h>
- #include <LyViewPaneNames.h>
- #include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
- #include <Editor/Framework/Configuration.h>
- #include <ScriptCanvas/Components/EditorUtils.h>
- #include <ScriptCanvas/Bus/RequestBus.h>
- namespace ScriptCanvasEditor
- {
- class OnScopeEnd
- {
- public:
- using ScopeEndFunctor = std::function<void()>;
- private:
- ScopeEndFunctor m_functor;
- public:
- OnScopeEnd(ScopeEndFunctor&& functor)
- : m_functor(AZStd::move(functor))
- {}
- OnScopeEnd(const ScopeEndFunctor& functor)
- : m_functor(functor)
- {}
- ~OnScopeEnd()
- {
- m_functor();
- }
- };
- Configuration::Configuration()
- : Configuration(SourceHandle())
- {
- }
- Configuration::Configuration(const SourceHandle& sourceHandle)
- : m_sourceHandle(sourceHandle)
- {
- AzFramework::AssetCatalogEventBus::Handler::BusConnect();
- Refresh(m_sourceHandle);
- }
- Configuration::~Configuration()
- {
- ScriptCanvasBuilder::DataSystemSourceNotificationsBus::Handler::BusDisconnect();
- AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
- }
- void Configuration::ClearVariables()
- {
- m_propertyOverrides.Clear();
- }
- const ScriptCanvasBuilder::BuildVariableOverrides* Configuration::CompileLatest()
- {
- return CompileLatestInternal() == BuildStatusValidation::Good ? &m_propertyOverrides : nullptr;
- }
- Configuration::BuildStatusValidation Configuration::CompileLatestInternal()
- {
- ScriptCanvasBuilder::BuilderSourceResult result;
- ScriptCanvasBuilder::DataSystemSourceRequestsBus::BroadcastResult
- ( result
- , &ScriptCanvasBuilder::DataSystemSourceRequests::CompileBuilderData
- , m_sourceHandle);
- const auto validation = ValidateBuildResult(result);
- if (validation == BuildStatusValidation::Good)
- {
- MergeWithLatestCompilation(*result.data);
- }
- return validation;
- }
- AZ::EventHandler<const Configuration&> Configuration::ConnectToPropertiesChanged(AZStd::function<void(const Configuration&)>&& function) const
- {
- AZ::EventHandler<const Configuration&> handler(function);
- handler.Connect(m_eventPropertiesChanged);
- return handler;
- }
- AZ::EventHandler<const Configuration&> Configuration::ConnectToSourceCompiled(AZStd::function<void(const Configuration&)>&& function) const
- {
- AZ::EventHandler<const Configuration&> handler(function);
- handler.Connect(m_eventSourceCompiled);
- return handler;
- }
- AZ::EventHandler<const Configuration&> Configuration::ConnectToSourceFailed(AZStd::function<void(const Configuration&)>&& function) const
- {
- AZ::EventHandler<const Configuration&> handler(function);
- handler.Connect(m_eventSourceFailed);
- return handler;
- }
- const ScriptCanvasBuilder::BuildVariableOverrides& Configuration::GetOverrides() const
- {
- return m_propertyOverrides;
- }
- const SourceHandle& Configuration::GetSource() const
- {
- return m_sourceHandle;
- }
- bool Configuration::HasSource() const
- {
- return m_sourceHandle.IsDescriptionValid();
- }
- void Configuration::MergeWithLatestCompilation(const ScriptCanvasBuilder::BuildVariableOverrides& buildData)
- {
- ScriptCanvasBuilder::BuildVariableOverrides source(buildData);
- if (!m_propertyOverrides.IsEmpty())
- {
- source.CopyPreviousOverriddenValues(m_propertyOverrides);
- }
- m_propertyOverrides = AZStd::move(source);
- m_propertyOverrides.SetHandlesToDescription();
- }
- AZ::u32 Configuration::OnEditorChangeProperties()
- {
- m_eventPropertiesChanged.Signal(*this);
- return AZ::Edit::PropertyRefreshLevels::ValuesOnly;
- }
- AZ::u32 Configuration::OnEditorChangeSource()
- {
- ClearVariables();
- Refresh(m_sourceHandle);
- return AZ::Edit::PropertyRefreshLevels::EntireTree;
- }
- void Configuration::OpenEditor([[maybe_unused]] const AZ::Data::AssetId& assetId, const AZ::Data::AssetType&)
- {
- AzToolsFramework::OpenViewPane(LyViewPane::ScriptCanvas);
- if (m_sourceHandle.IsDescriptionValid())
- {
- AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
- GeneralRequestBus::BroadcastResult(openOutcome, &GeneralRequests::OpenScriptCanvasAsset, m_sourceHandle, Tracker::ScriptCanvasFileState::UNMODIFIED, -1);
- if (!openOutcome)
- {
- AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
- }
- }
- }
- void Configuration::Reflect(AZ::ReflectContext* context)
- {
- if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<Configuration>()
- ->Field("sourceHandle", &Configuration::m_sourceHandle)
- ->Field("sourceName", &Configuration::m_sourceName)
- ->Field("propertyOverrides", &Configuration::m_propertyOverrides)
- ;
- if (AZ::EditContext* editContext = serializeContext->GetEditContext())
- {
- editContext->Class<Configuration>("Script Canvas Configuration", "Select a Script Canvas graph and configure its properties.")
- ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
- ->Attribute(AZ::Edit::Attributes::Category, "Scripting")
- ->Attribute(AZ::Edit::Attributes::Icon, "Icons/ScriptCanvas/ScriptCanvas.svg")
- ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/ScriptCanvas/Viewport/ScriptCanvas.svg")
- ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
- ->DataElement(AZ::Edit::UIHandlers::Default, &Configuration::m_sourceHandle, "Source", "Script Canvas source file associated with this component")
- ->Attribute("BrowseIcon", ":/stylesheet/img/UI20/browse-edit-select-files.svg")
- ->Attribute("EditButton", "")
- ->Attribute("EditDescription", "Open in Script Canvas Editor")
- ->Attribute("EditCallback", &Configuration::OpenEditor)
- ->Attribute(AZ::Edit::Attributes::AssetPickerTitle, "Script Canvas")
- ->Attribute(AZ::Edit::Attributes::SourceAssetFilterPattern, "*.scriptcanvas")
- ->Attribute(AZ::Edit::Attributes::ChangeNotify, &Configuration::OnEditorChangeSource)
- // ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::HideChildren) // or just ::Hide
- ->DataElement(AZ::Edit::UIHandlers::Default, &Configuration::m_propertyOverrides, "Properties", "Script Canvas Graph Properties")
- ->Attribute(AZ::Edit::Attributes::ChangeNotify, &Configuration::OnEditorChangeProperties)
- ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
- ;
- }
- }
- }
- void Configuration::Refresh()
- {
- Refresh(m_sourceHandle);
- }
- void Configuration::Refresh(const SourceHandle& sourceHandle)
- {
- ScriptCanvasBuilder::DataSystemSourceNotificationsBus::Handler::BusDisconnect();
- m_sourceHandle = sourceHandle.Describe();
- CompleteDescriptionInPlace(m_sourceHandle);
- if (m_sourceHandle.IsDescriptionValid())
- {
- m_sourceName = m_sourceHandle.RelativePath().Filename().Native();
- }
- m_eventPropertiesChanged.Signal(*this);
- if (!m_sourceHandle.Id().IsNull())
- {
- ScriptCanvasBuilder::DataSystemSourceNotificationsBus::Handler::BusConnect(m_sourceHandle.Id());
- if (!m_sourceHandle.RelativePath().empty())
- {
- const auto validation = CompileLatestInternal();
- if (validation == BuildStatusValidation::Good)
- {
- m_eventSourceCompiled.Signal(*this);
- return;
- }
- else if (validation == BuildStatusValidation::IncompatibleScript)
- {
- AZ_Error("ScriptCanvas", false, "Selected Script is not compatible with this configuration.");
- m_eventIncompatibleScript.Signal(*this);
- return;
- }
- else
- {
- AZ_Warning("ScriptCanvasBuilder", false, "Runtime information did not build for ScriptCanvas Component using source: %s"
- , m_sourceHandle.ToString().c_str());
- }
- }
- else
- {
- AZ_Warning("ScriptCanvasBuilder", false, "Configuration had no valid path for %s and won't compile or expose variables."
- , m_sourceHandle.ToString().c_str());
- }
- }
- else
- {
- AZ_Warning("ScriptCanvas", m_sourceHandle.RelativePath().empty()
- , "Configuration had no valid ID for %s and won't compile or expose variables.", m_sourceHandle.RelativePath().c_str());
- }
- m_eventSourceFailed.Signal(*this);
- }
- void Configuration::SourceFileChanged
- ( const ScriptCanvasBuilder::BuilderSourceResult& result
- , [[maybe_unused]] AZStd::string_view relativePath
- , [[maybe_unused]] AZStd::string_view scanFolder)
- {
- const auto validation = ValidateBuildResult(result);
- if (validation == BuildStatusValidation::Good)
- {
- MergeWithLatestCompilation(*result.data);
- m_eventSourceCompiled.Signal(*this);
- }
- else if (validation == BuildStatusValidation::Bad)
- {
- m_eventSourceFailed.Signal(*this);
- }
- else if (validation == BuildStatusValidation::IncompatibleScript)
- {
- m_eventIncompatibleScript.Signal(*this);
- }
- }
- void Configuration::SourceFileFailed([[maybe_unused]] AZStd::string_view relativePath
- , [[maybe_unused]] AZStd::string_view scanFolder)
- {
- m_eventSourceFailed.Signal(*this);
- // display error icon
- }
- void Configuration::SourceFileRemoved([[maybe_unused]] AZStd::string_view relativePath
- , [[maybe_unused]] AZStd::string_view scanFolder)
- {
- m_eventSourceFailed.Signal(*this);
- // display removed icon
- }
- Configuration::BuildStatusValidation Configuration::ValidateBuildResult(const ScriptCanvasBuilder::BuilderSourceResult& result) const
- {
- if (result.status != ScriptCanvasBuilder::BuilderSourceStatus::Good || !result.data)
- {
- AZ_Error
- ( "ScriptCanvas"
- , !(result.status == ScriptCanvasBuilder::BuilderSourceStatus::Good && result.data)
- , "Configuration::SourceFileChanged received good status with no data");
- return BuildStatusValidation::Bad;
- }
- else if (result.data->m_isComponentScript && !m_acceptsComponentScript)
- {
- // #scriptcanvas_component_extension
- return BuildStatusValidation::IncompatibleScript;
- }
- else
- {
- return BuildStatusValidation::Good;
- }
- }
- // #scriptcanvas_component_extension ...
- bool Configuration::AcceptsComponentScript() const
- {
- return m_acceptsComponentScript;
- }
- void Configuration::SetAcceptsComponentScript(bool value)
- {
- m_acceptsComponentScript = value;
- }
- AZ::EventHandler<const Configuration&> Configuration::ConnectToIncompatilbleScript(AZStd::function<void(const Configuration&)>&& function) const
- {
- AZ::EventHandler<const Configuration&> handler(function);
- handler.Connect(m_eventIncompatibleScript);
- return handler;
- }
- // ... #scriptcanvas_component_extension
- }
|