EditorCOmponent build pipeline WIP

Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
This commit is contained in:
chcurran
2021-11-22 20:34:11 -08:00
parent 205b2c27ee
commit 24b3167d48
12 changed files with 233 additions and 160 deletions
@@ -22,18 +22,26 @@
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
#include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Core/SerializationListener.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
namespace ScriptCanvasFileHandlingCpp
{
using namespace ScriptCanvas;
void AppendTabs(AZStd::string& result, size_t depth)
{
for (size_t i = 0; i < depth; ++i)
{
result += "\t";
}
}
void CollectNodes(const GraphData::NodeContainer& container, SerializationListeners& listeners)
void CollectNodes(const ScriptCanvas::GraphData::NodeContainer& container, ScriptCanvas::SerializationListeners& listeners)
{
for (auto& nodeEntity : container)
{
if (nodeEntity)
{
if (auto listener = azrtti_cast<SerializationListener*>(AZ::EntityUtils::FindFirstDerivedComponent<Node>(nodeEntity)))
if (auto listener = azrtti_cast<ScriptCanvas::SerializationListener*>
( AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::Node>(nodeEntity)))
{
listeners.push_back(listener);
}
@@ -44,6 +52,38 @@ namespace ScriptCanvasFileHandlingCpp
namespace ScriptCanvasEditor
{
EditorAssetTree* EditorAssetTree::ModRoot()
{
if (!m_parent)
{
return this;
}
return m_parent->ModRoot();
}
void EditorAssetTree::SetParent(EditorAssetTree& parent)
{
m_parent = &parent;
}
AZStd::string EditorAssetTree::ToString(size_t depth) const
{
AZStd::string result;
ScriptCanvasFileHandlingCpp::AppendTabs(result, depth);
result += m_asset.ToString();
depth += m_dependencies.empty() ? 0 : 1;
for (const auto& dependency : m_dependencies)
{
result += "\n";
ScriptCanvasFileHandlingCpp::AppendTabs(result, depth);
result += dependency.ToString(depth);
}
return result;
}
AZ::Outcome<void, AZStd::string> LoadDataFromJson
( ScriptCanvas::ScriptCanvasData& dataTarget
, AZStd::string_view source
@@ -87,6 +127,88 @@ namespace ScriptCanvasEditor
return AZ::Success();
}
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(SourceHandle handle, EditorAssetTree* parent)
{
if (!CompleteDescriptionInPlace(handle))
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to describe graph from %s", handle.ToString().c_str()));
}
auto loadAssetOutcome = LoadFromFile(handle.Path().c_str());
if (!loadAssetOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load graph from %s: %s"
, handle.ToString().c_str(), loadAssetOutcome.GetError().c_str()));
}
AZStd::vector<SourceHandle> dependentAssets;
auto filterCB = [&dependentAssets](const AZ::Data::AssetFilterInfo& filterInfo)->bool
{
if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>()
|| filterInfo.m_assetType == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>())
{
dependentAssets.push_back(SourceHandle(nullptr, filterInfo.m_assetId.m_guid, {}));
}
return true;
};
const auto subgraphInterfaceAssetTypeID = azrtti_typeid<AZ::Data::Asset<ScriptCanvas::SubgraphInterfaceAsset>>();
auto beginElementCB = [&subgraphInterfaceAssetTypeID, &dependentAssets]
( void* instance
, const AZ::SerializeContext::ClassData* classData
, const AZ::SerializeContext::ClassElement* classElement) -> bool
{
if (classElement)
{
// if we are a pointer, then we may be pointing to a derived type.
if (classElement->m_flags & AZ::SerializeContext::ClassElement::FLG_POINTER)
{
// if ptr is a pointer-to-pointer, cast its value to a void* (or const void*) and dereference to get to the actual object pointer.
instance = *(void**)(instance);
}
if (classData->m_typeId == subgraphInterfaceAssetTypeID)
{
auto id = reinterpret_cast<AZ::Data::Asset<ScriptCanvas::SubgraphInterfaceAsset>*>(instance)->GetId();
dependentAssets.push_back(SourceHandle(nullptr, id.m_guid, {}));
}
}
return true;
};
AZ::SerializeContext* serializeContext = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
serializeContext->EnumerateObject( handle.Get(), beginElementCB, nullptr, AZ::SerializeContext::ENUM_ACCESS_FOR_READ);
EditorAssetTree result;
for (auto& dependentAsset : dependentAssets)
{
auto loadDependentOutcome = LoadEditorAssetTree(dependentAsset, &result);
if (!loadDependentOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load graph from %s: %s"
, dependentAsset.ToString().c_str(), loadDependentOutcome.GetError().c_str()));
}
result.m_dependencies.push_back(loadDependentOutcome.TakeValue());
}
if (parent)
{
result.SetParent(*parent);
}
result.m_asset = loadAssetOutcome.TakeValue();
return AZ::Success(result);
}
AZ::Outcome<ScriptCanvasEditor::SourceHandle, AZStd::string> LoadFromFile(AZStd::string_view path)
{
namespace JSRU = AZ::JsonSerializationUtils;
@@ -137,7 +259,7 @@ namespace ScriptCanvasEditor
graph->MarkOwnership(*scriptCanvasData);
}
return AZ::Success(ScriptCanvasEditor::SourceHandle(scriptCanvasData, {}, path));
return AZ::Success(ScriptCanvasEditor::SourceHandle(scriptCanvasData, path));
}
AZ::Outcome<void, AZStd::string> SaveToStream(const SourceHandle& source, AZ::IO::GenericStream& stream)
@@ -134,7 +134,7 @@ namespace ScriptCanvasEditor
}
ScriptCanvasBuilder::BuildVariableOverrides overrides;
overrides.m_source = AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>(assetHolder.GetAssetId(), assetHolder.GetAssetType(), assetHolder.GetAssetHint());;
overrides.m_source = SourceHandle(nullptr, assetHolder.GetAssetId().m_guid, {});
for (auto& variable : editableData.GetVariables())
{
@@ -197,14 +197,15 @@ namespace ScriptCanvasEditor
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Level", 0x9aeacc13))
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/scripting/script-canvas/")
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_sourceHandle, "Script Canvas Source File", "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", &EditorScriptCanvasComponent::OpenEditor)
->Attribute(AZ::Edit::Attributes::AssetPickerTitle, "Script Canvas")
->Attribute(AZ::Edit::Attributes::SourceAssetFilterPattern, "*.scriptcanvas")
->Attribute("BrowseIcon", ":/stylesheet/img/UI20/browse-edit-select-files.svg")
->Attribute("EditButton", "")
->Attribute("EditDescription", "Open in Script Canvas Editor")
->Attribute("EditCallback", &EditorScriptCanvasComponent::OpenEditor)
->Attribute(AZ::Edit::Attributes::AssetPickerTitle, "Script Canvas")
->Attribute(AZ::Edit::Attributes::SourceAssetFilterPattern, "*.scriptcanvas")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorScriptCanvasComponent::OnFileSelectionChanged)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_variableOverrides, "Properties", "Script Canvas Graph Properties")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
;
}
}
@@ -319,7 +320,7 @@ namespace ScriptCanvasEditor
m_runtimeDataIsValid = false;
auto assetTreeOutcome = LoadEditorAssetTree(m_sourceHandle.Id(), m_sourceHandle.Path().c_str());
auto assetTreeOutcome = LoadEditorAssetTree(m_sourceHandle);
if (!assetTreeOutcome.IsSuccess())
{
AZ_Warning("ScriptCanvas", false, "EditorScriptCanvasComponent::BuildGameEntityData failed: %s", assetTreeOutcome.GetError().c_str());
@@ -386,6 +387,26 @@ namespace ScriptCanvasEditor
return m_sourceHandle.Id();
}
AZ::u32 EditorScriptCanvasComponent::OnFileSelectionChanged()
{
m_sourceHandle = SourceHandle(nullptr, m_sourceHandle.Path());
CompleteDescriptionInPlace(m_sourceHandle);
m_previousHandle = {};
m_removedHandle = {};
if (m_sourceHandle.IsDescriptionValid())
{
OnScriptCanvasAssetChanged(m_sourceHandle);
}
else
{
ClearVariables();
}
return AZ::Edit::PropertyRefreshLevels::EntireTree;
}
void EditorScriptCanvasComponent::OnScriptCanvasAssetChanged(const SourceHandle& assetId)
{
ScriptCanvas::GraphIdentifier newIdentifier = GetGraphIdentifier();
@@ -492,10 +513,6 @@ namespace ScriptCanvasEditor
UpdateName();
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
}
else
{
// #sc_editor_asset clear or disable something
}
}
void EditorScriptCanvasComponent::ClearVariables()
@@ -78,6 +78,19 @@ namespace ScriptCanvasEditor
return AZStd::nullopt;
}
bool CompleteDescriptionInPlace(SourceHandle& source)
{
if (auto completed = CompleteDescription(source))
{
source = *completed;
return true;
}
else
{
return false;
}
}
//////////////////////////
// NodeIdentifierFactory
//////////////////////////
@@ -26,6 +26,22 @@ namespace ScriptCanvas
namespace ScriptCanvasEditor
{
class EditorAssetTree
{
public:
AZ_CLASS_ALLOCATOR(EditorAssetTree, AZ::SystemAllocator, 0);
EditorAssetTree* m_parent = nullptr;
AZStd::vector<EditorAssetTree> m_dependencies;
SourceHandle m_asset;
EditorAssetTree* ModRoot();
void SetParent(EditorAssetTree& parent);
AZStd::string ToString(size_t depth = 0) const;
};
AZ::Outcome<SourceHandle, AZStd::string> LoadFromFile(AZStd::string_view path);
AZ::Outcome<void, AZStd::string> LoadDataFromJson
@@ -33,5 +49,7 @@ namespace ScriptCanvasEditor
, AZStd::string_view source
, AZ::SerializeContext& serializeContext);
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(SourceHandle handle, EditorAssetTree* parent = nullptr);
AZ::Outcome<void, AZStd::string> SaveToStream(const SourceHandle& source, AZ::IO::GenericStream& stream);
}
@@ -121,6 +121,8 @@ namespace ScriptCanvasEditor
void SourceFileRemoved(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
void SourceFileFailed(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid fileAssetId) override;
AZ::u32 OnFileSelectionChanged();
void OnScriptCanvasAssetChanged(const SourceHandle& sourceHandle);
void UpdateName();
@@ -25,6 +25,8 @@ namespace ScriptCanvasEditor
// If both Path and Id is valid, including after correction, returns the handle including source Data,
// otherwise, returns null
AZStd::optional<SourceHandle> CompleteDescription(const SourceHandle& source);
// if CompleteDescription() succeeds, sets the handle to the result, else does nothing
bool CompleteDescriptionInPlace(SourceHandle& source);
class Graph;
class NodePaletteModel;
@@ -154,6 +154,7 @@ namespace ScriptCanvasEditor
canvasWidget->SetDefaultBorderColor(ScriptCanvasAssetDescription().GetDisplayColorImpl());
metaData.m_canvasWidget = canvasWidget;
metaData.m_assetId = assetId;
metaData.m_fileState = fileState;
AZStd::string tabName;
AzFramework::StringFunc::Path::GetFileName(assetId.Path().c_str(), tabName);
@@ -138,7 +138,7 @@ namespace ScriptCanvasEditor
(void)index;
(void)node;
auto sourceHandle = SourceHandle(nullptr, {}, GUI->GetSelectedSourcePath());
auto sourceHandle = SourceHandle(nullptr, GUI->GetSelectedSourcePath());
auto completeSourceHandle = CompleteDescription(sourceHandle);
if (completeSourceHandle)
{