Merge pull request #1657 from aws-lumberyard-dev/carlitosan/scriptcanvas/prefabs

Initial prefab integration
main
Sandeep 5 years ago committed by GitHub
commit 4c684b1a10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -58,8 +58,11 @@ class TestFileMenuDefaultNewOpen:
sc_main = sc.findChild(QtWidgets.QMainWindow) sc_main = sc.findChild(QtWidgets.QMainWindow)
sc_tabs = sc_main.findChild(QtWidgets.QTabWidget, "ScriptCanvasTabs") sc_tabs = sc_main.findChild(QtWidgets.QTabWidget, "ScriptCanvasTabs")
# 3) Trigger File->New action # wait for the intial tab count
general.idle_wait(GENERAL_WAIT)
initial_tabs_count = sc_tabs.count() initial_tabs_count = sc_tabs.count()
# 3) Trigger File->New action
action = pyside_utils.find_child_by_pattern( action = pyside_utils.find_child_by_pattern(
sc_main, {"objectName": "action_New_Script", "type": QtWidgets.QAction} sc_main, {"objectName": "action_New_Script", "type": QtWidgets.QAction}
) )

@ -689,6 +689,81 @@ namespace AZ
return 1; return 1;
} }
int Class__IndexAllowNil(lua_State* l)
{
LSV_BEGIN(l, 1);
// calling format __index(table,key)
lua_getmetatable(l, -2); // load the userdata metatable
int metaTableIndex = lua_gettop(l);
// Check if the key is string, if so we expect it to be a function or property name
// otherwise we allow users to provide custom index handlers
// Technically we can allow strings too, but it will clash with function/property names and it be hard to figure
// out what is going on from with in the system.
if (lua_type(l, -2) == LUA_TSTRING)
{
lua_pushvalue(l, -2); // duplicate the key
lua_rawget(l, -2); // load the value at this index
}
else
{
lua_pushliteral(l, "__AZ_Index");
lua_rawget(l, -2); // check if the user provided custom Index method in the class metatable
if (lua_isnil(l, -1)) // if not report an error
{
lua_rawgeti(l, -2, AZ_LUA_CLASS_METATABLE_NAME_INDEX); // load the class name for a better error
if (!lua_isstring(l, -1)) // if we failed it means we are the base metatable
{
lua_pop(l, 1);
lua_rawgeti(l, 1, AZ_LUA_CLASS_METATABLE_NAME_INDEX);
}
ScriptContext::FromNativeContext(l)->Error(ScriptContext::ErrorType::Warning, true, "Invalid index type [], should be string! '%s:%s'!", lua_tostring(l, -1), lua_tostring(l, -4));
}
else
{
// if we have custom index handler
lua_pushvalue(l, -4); // duplicate the table (class pointer)
lua_pushvalue(l, -4); // duplicate the index value for the call
lua_call(l, 2, 1); // call the function
}
lua_remove(l, metaTableIndex); // remove the metatable
return 1;
}
if (!lua_isnil(l, -1))
{
if (lua_tocfunction(l, -1) == &Internal::LuaPropertyTagHelper) // if it's a property
{
lua_getupvalue(l, -1, 1); // push on the stack the getter function
lua_remove(l, -2); // remove property object
if (lua_isnil(l, -1))
{
lua_rawgeti(l, -2, AZ_LUA_CLASS_METATABLE_NAME_INDEX); // load the class name for a better error
if (!lua_isstring(l, -1)) // if we failed it means we are the base metatable
{
lua_pop(l, 1);
lua_rawgeti(l, 1, AZ_LUA_CLASS_METATABLE_NAME_INDEX);
}
ScriptContext::FromNativeContext(l)->Error(ScriptContext::ErrorType::Warning, true, "Property '%s:%s' is write only", lua_tostring(l, -1), lua_tostring(l, -4));
lua_pop(l, 1); // pop class name
}
else
{
lua_pushvalue(l, -4); // copy the user data to be passed as a this pointer.
lua_call(l, 1, 1); // call a function with one argument (this pointer) and 1 result
}
}
}
lua_remove(l, metaTableIndex); // remove the metatable
return 1;
}
//========================================================================= //=========================================================================
// Class__NewIndex // Class__NewIndex
// [3/22/2012] // [3/22/2012]
@ -826,30 +901,6 @@ namespace AZ
return 1; return 1;
} }
//=========================================================================
// ClassMetatable__Index
// [3/24/2012]
//=========================================================================
int ClassMetatable__Index(lua_State* l)
{
// since the Class__Index is generic function (ask for the class metatable)
// we can reuse the code for the base metatable (which is a metatable
// of the class metatable)
return Class__Index(l);
}
//=========================================================================
// ClassMetatable__NewIndex
// [3/30/2012]
//=========================================================================
int ClassMetatable__NewIndex(lua_State* l)
{
// since the Class__NewIndex is generic function (ask for the class metatable)
// we can reuse the code for the base metatable (which is a metatable
// of the class metatable)
return Class__NewIndex(l);
}
inline size_t BufferStringCopy(const char* source, char* destination, size_t destinationSize) inline size_t BufferStringCopy(const char* source, char* destination, size_t destinationSize)
{ {
size_t srcLen = strlen(source); size_t srcLen = strlen(source);
@ -5053,9 +5104,20 @@ LUA_API const Node* lua_getDummyNode()
lua_pushcclosure(m_lua, &DefaultBehaviorCaller::Destroy, 0); lua_pushcclosure(m_lua, &DefaultBehaviorCaller::Destroy, 0);
lua_rawset(m_lua, -3); lua_rawset(m_lua, -3);
lua_pushliteral(m_lua, "__index"); {
lua_pushcclosure(m_lua, &Internal::Class__Index, 0); lua_pushliteral(m_lua, "__index");
lua_rawset(m_lua, -3);
if (FindAttribute(Script::Attributes::UseClassIndexAllowNil, behaviorClass->m_attributes))
{
lua_pushcclosure(m_lua, &Internal::Class__IndexAllowNil, 0);
}
else
{
lua_pushcclosure(m_lua, &Internal::Class__Index, 0);
}
lua_rawset(m_lua, -3);
}
lua_pushliteral(m_lua, "__newindex"); lua_pushliteral(m_lua, "__newindex");
lua_pushcclosure(m_lua, &Internal::Class__NewIndex, 0); lua_pushcclosure(m_lua, &Internal::Class__NewIndex, 0);

@ -16,19 +16,20 @@ namespace AZ
{ {
namespace Attributes namespace Attributes
{ {
const static AZ::Crc32 Ignore = AZ_CRC("ScriptIgnore", 0xeb7615e1); ///< Don't use the element in the script reflection static constexpr AZ::Crc32 Ignore = AZ_CRC_CE("ScriptIgnore"); ///< Don't use the element in the script reflection
const static AZ::Crc32 ClassNameOverride = AZ_CRC("ScriptClassNameOverride", 0x891238a3); ///< Provide a custom name for script reflection, that doesn't match the behavior Context name static constexpr AZ::Crc32 ClassNameOverride = AZ_CRC_CE("ScriptClassNameOverride"); ///< Provide a custom name for script reflection, that doesn't match the behavior Context name
const static AZ::Crc32 MethodOverride = AZ_CRC("ScriptFunctionOverride", 0xf89a7882); ///< Use a custom function in the attribute instead of the function static constexpr AZ::Crc32 MethodOverride = AZ_CRC_CE("ScriptFunctionOverride"); ///< Use a custom function in the attribute instead of the function
const static AZ::Crc32 ConstructorOverride = AZ_CRC("ConstructorOverride", 0xef5ce4aa); ///< You can provide a custom constructor to be called when created from Lua script static constexpr AZ::Crc32 ConstructorOverride = AZ_CRC_CE("ConstructorOverride"); ///< You can provide a custom constructor to be called when created from Lua script
const static AZ::Crc32 EventHandlerCreationFunction = AZ_CRC_CE("EventHandlerCreationFunction"); ///< helps create a handler for any script target so that script functions can be used for AZ::Event signals static constexpr AZ::Crc32 EventHandlerCreationFunction = AZ_CRC_CE("EventHandlerCreationFunction"); ///< helps create a handler for any script target so that script functions can be used for AZ::Event signals
const static AZ::Crc32 GenericConstructorOverride = AZ_CRC("GenericConstructorOverride", 0xe6a1698e); ///< You can provide a custom constructor to be called when creating a script static constexpr AZ::Crc32 GenericConstructorOverride = AZ_CRC_CE("GenericConstructorOverride"); ///< You can provide a custom constructor to be called when creating a script
const static AZ::Crc32 ReaderWriterOverride = AZ_CRC("ReaderWriterOverride", 0x1ad9ce2a); ///< paired with \ref ScriptContext::CustomReaderWriter allows you to customize read/write to Lua VM static constexpr AZ::Crc32 ReaderWriterOverride = AZ_CRC_CE("ReaderWriterOverride"); ///< paired with \ref ScriptContext::CustomReaderWriter allows you to customize read/write to Lua VM
const static AZ::Crc32 ConstructibleFromNil = AZ_CRC("ConstructibleFromNil", 0x23908169); ///< Applied to classes. Value (bool) specifies if the class be default constructed when nil is provided. static constexpr AZ::Crc32 ConstructibleFromNil = AZ_CRC_CE("ConstructibleFromNil"); ///< Applied to classes. Value (bool) specifies if the class be default constructed when nil is provided.
const static AZ::Crc32 ToolTip = AZ_CRC("ToolTip", 0xa1b95fb0); ///< Add a tooltip for a method/event/property static constexpr AZ::Crc32 ToolTip = AZ_CRC_CE("ToolTip"); ///< Add a tooltip for a method/event/property
const static AZ::Crc32 Category = AZ_CRC("Category", 0x064c19c1); ///< Provide a category to allow for partitioning/sorting/ordering of the element static constexpr AZ::Crc32 Category = AZ_CRC_CE("Category"); ///< Provide a category to allow for partitioning/sorting/ordering of the element
const static AZ::Crc32 Deprecated = AZ_CRC("Deprecated", 0xfe49a138); ///< Marks a reflected class, method, EBus or property as deprecated. static constexpr AZ::Crc32 Deprecated = AZ_CRC_CE("Deprecated"); ///< Marks a reflected class, method, EBus or property as deprecated.
const static AZ::Crc32 DisallowBroadcast = AZ_CRC("DisallowBroadcast", 0x389b0ac7); ///< Marks a reflected EBus as not allowing Broadcasts, only Events. static constexpr AZ::Crc32 DisallowBroadcast = AZ_CRC_CE("DisallowBroadcast"); ///< Marks a reflected EBus as not allowing Broadcasts, only Events.
const static AZ::Crc32 ClassConstantValue = AZ_CRC_CE("ClassConstantValue"); ///< Indicates the property is backed by a constant value static constexpr AZ::Crc32 ClassConstantValue = AZ_CRC_CE("ClassConstantValue"); ///< Indicates the property is backed by a constant value
static constexpr AZ::Crc32 UseClassIndexAllowNil = AZ_CRC_CE("UseClassIndexAllowNil"); ///< Use the Class__IndexAllowNil method, which will not report an error on accessing undeclared values (allows for nil)
//! Attribute which stores BehaviorAzEventDescription structure which contains //! Attribute which stores BehaviorAzEventDescription structure which contains
//! the script name of an AZ::Event and the name of it's parameter arguments //! the script name of an AZ::Event and the name of it's parameter arguments
@ -39,11 +40,11 @@ namespace AZ
static constexpr AZ::Crc32 EventParameterTypes = AZ_CRC_CE("EventParameterTypes"); static constexpr AZ::Crc32 EventParameterTypes = AZ_CRC_CE("EventParameterTypes");
///< Recommends that the Lua runtime look up the member function in the meta table of the first argument, rather than in the original table ///< Recommends that the Lua runtime look up the member function in the meta table of the first argument, rather than in the original table
const static AZ::Crc32 TreatAsMemberFunction = AZ_CRC("TreatAsMemberFunction", 0x64be831a); static constexpr AZ::Crc32 TreatAsMemberFunction = AZ_CRC_CE("TreatAsMemberFunction");
///< This attribute can be attached to the EditContext Attribute of a reflected class, the BehaviorContext Attribute of a reflected class, method, ebus or property. ///< This attribute can be attached to the EditContext Attribute of a reflected class, the BehaviorContext Attribute of a reflected class, method, ebus or property.
///< ExcludeFlags can be used to prevent elements from appearing in List, Documentation, etc... ///< ExcludeFlags can be used to prevent elements from appearing in List, Documentation, etc...
const static AZ::Crc32 ExcludeFrom = AZ_CRC("ExcludeFrom", 0xa98972fe); static constexpr AZ::Crc32 ExcludeFrom = AZ_CRC_CE("ExcludeFrom");
enum ExcludeFlags : AZ::u64 enum ExcludeFlags : AZ::u64
{ {
List = 1 << 0, //< The reflected item will be excluded from any list (e.g. node palette) List = 1 << 0, //< The reflected item will be excluded from any list (e.g. node palette)
@ -54,7 +55,7 @@ namespace AZ
}; };
//! Used to specify the usage of a Behavior Context element (e.g. Class or EBus) designed for automation scripts //! Used to specify the usage of a Behavior Context element (e.g. Class or EBus) designed for automation scripts
const static AZ::Crc32 Scope = AZ_CRC("Scope", 0x00af55d3); static constexpr AZ::Crc32 Scope = AZ_CRC_CE("Scope");
enum class ScopeFlags : AZ::u64 enum class ScopeFlags : AZ::u64
{ {
Launcher = 1 << 0, //< a type meant for game run-time Launcher client (default value) Launcher = 1 << 0, //< a type meant for game run-time Launcher client (default value)
@ -63,15 +64,15 @@ namespace AZ
}; };
//! Provide a partition hierarchy in a string dotted notation to namespace a script element //! Provide a partition hierarchy in a string dotted notation to namespace a script element
const static AZ::Crc32 Module = AZ_CRC("Module", 0x0c242628); static constexpr AZ::Crc32 Module = AZ_CRC_CE("Module");
//! Provide an alternate name for script elements such as helpful PEP8 Python methods and property aliases //! Provide an alternate name for script elements such as helpful PEP8 Python methods and property aliases
const static AZ::Crc32 Alias = AZ_CRC("Alias", 0xe16c6b94); static constexpr AZ::Crc32 Alias = AZ_CRC_CE("Alias");
const static AZ::Crc32 EnableAsScriptEventParamType = AZ_CRC("ScriptEventParam", 0xa41e4cb0); static constexpr AZ::Crc32 EnableAsScriptEventParamType = AZ_CRC_CE("ScriptEventParam");
const static AZ::Crc32 EnableAsScriptEventReturnType = AZ_CRC("ScriptEventReturn", 0xf89b5337); static constexpr AZ::Crc32 EnableAsScriptEventReturnType = AZ_CRC_CE("ScriptEventReturn");
const static AZ::Crc32 Storage = AZ_CRC("ScriptStorage", 0xcd95b44d); static constexpr AZ::Crc32 Storage = AZ_CRC_CE("ScriptStorage");
enum class StorageType enum class StorageType
{ {
ScriptOwn, // default, Host allocated memory, Lua will destruct object, Lua will free host-memory via host-supplied function ScriptOwn, // default, Host allocated memory, Lua will destruct object, Lua will free host-memory via host-supplied function
@ -79,7 +80,7 @@ namespace AZ
Value, // Object is Lua allocated memory, Lua will destruct object, Lua will free Lua-memory Value, // Object is Lua allocated memory, Lua will destruct object, Lua will free Lua-memory
}; };
const static AZ::Crc32 Operator = AZ_CRC("ScriptOperator", 0xfee681b6); static constexpr AZ::Crc32 Operator = AZ_CRC_CE("ScriptOperator");
enum class OperatorType enum class OperatorType
{ {
// note storage policy can be T*,T (only if we store raw pointers), shared_ptr<T>, intrusive pointer<T> // note storage policy can be T*,T (only if we store raw pointers), shared_ptr<T>, intrusive pointer<T>
@ -100,7 +101,7 @@ namespace AZ
IndexWrite, // given a key/index and a value, you can store it in the class IndexWrite, // given a key/index and a value, you can store it in the class
}; };
const static AZ::Crc32 AssetType = AZ_CRC("AssetType", 0xabbf8d5f); ///< Provide an asset type for a generic AssetId method static constexpr AZ::Crc32 AssetType = AZ_CRC_CE("AssetType"); ///< Provide an asset type for a generic AssetId method
} // Attributes } // Attributes
} // Script } // Script

@ -24,7 +24,6 @@ namespace AZ
//========================================================================= //=========================================================================
AZStd::string ExtractUserMessage(const ScriptDataContext& dc) AZStd::string ExtractUserMessage(const ScriptDataContext& dc)
{ {
AZStd::string userMessage = "Condition failed";
const int argCount = dc.GetNumArguments(); const int argCount = dc.GetNumArguments();
if (argCount > 0 && dc.IsString(argCount - 1)) if (argCount > 0 && dc.IsString(argCount - 1))
{ {
@ -33,12 +32,12 @@ namespace AZ
{ {
if (value) if (value)
{ {
userMessage = value; return value;
} }
} }
} }
return userMessage; return "ExtractUserMessage from print/Debug.Log/Warn/Error/Assert failed. Consider wrapping your argument in tostring().";
} }
//========================================================================= //=========================================================================

@ -19,7 +19,7 @@
#include <Builder/ScriptCanvasBuilderWorker.h> #include <Builder/ScriptCanvasBuilderWorker.h>
#include <LyViewPaneNames.h> #include <LyViewPaneNames.h>
// Undo this // Undo this
AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option") AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option")
#include <ScriptCanvas/Asset/RuntimeAsset.h> #include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h> #include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
@ -90,8 +90,8 @@ namespace ScriptCanvasEditor
void EditorAssetSystemComponent::Deactivate() void EditorAssetSystemComponent::Deactivate()
{ {
ScriptCanvas::Translation::RequestBus::Handler::BusDisconnect(); ScriptCanvas::Translation::RequestBus::Handler::BusDisconnect();
ScriptCanvas::Grammar::RequestBus::Handler::BusDisconnect(); ScriptCanvas::Grammar::RequestBus::Handler::BusDisconnect();
EditorAssetConversionBus::Handler::BusDisconnect(); EditorAssetConversionBus::Handler::BusDisconnect();
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
m_editorAssetRegistry.Unregister(); m_editorAssetRegistry.Unregister();
@ -119,8 +119,8 @@ namespace ScriptCanvasEditor
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> EditorAssetSystemComponent::LoadAsset(AZStd::string_view graphPath) AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> EditorAssetSystemComponent::LoadAsset(AZStd::string_view graphPath)
{ {
auto outcome = ScriptCanvasBuilder::LoadEditorAsset(graphPath); auto outcome = ScriptCanvasBuilder::LoadEditorAsset(graphPath, AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
if (outcome.IsSuccess()) if (outcome.IsSuccess())
{ {
return outcome.GetValue(); return outcome.GetValue();

@ -21,8 +21,10 @@ namespace ScriptCanvas
void RuntimeAssetSystemComponent::Reflect(AZ::ReflectContext* context) void RuntimeAssetSystemComponent::Reflect(AZ::ReflectContext* context)
{ {
ScriptCanvas::RuntimeData::Reflect(context); RuntimeData::Reflect(context);
ScriptCanvas::SubgraphInterfaceData::Reflect(context); RuntimeDataOverrides::Reflect(context);
SubgraphInterfaceData::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{ {
serializeContext->Class<RuntimeAssetSystemComponent, AZ::Component>() serializeContext->Class<RuntimeAssetSystemComponent, AZ::Component>()

@ -0,0 +1,376 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <Builder/ScriptCanvasBuilder.h>
#include <Builder/ScriptCanvasBuilderWorker.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Grammar/AbstractCodeModel.h>
namespace ScriptCanvasBuilderCpp
{
void AppendTabs(AZStd::string& result, size_t depth)
{
for (size_t i = 0; i < depth; ++i)
{
result += "\t";
}
}
}
namespace ScriptCanvasBuilder
{
void BuildVariableOverrides::Clear()
{
m_source.Reset();
m_variables.clear();
m_entityIds.clear();
m_dependencies.clear();
}
void BuildVariableOverrides::CopyPreviousOverriddenValues(const BuildVariableOverrides& source)
{
for (auto& overriddenValue : m_overrides)
{
auto iter = AZStd::find_if(source.m_overrides.begin(), source.m_overrides.end(), [&overriddenValue](const auto& candidate) { return candidate.GetVariableId() == overriddenValue.GetVariableId(); });
if (iter != source.m_overrides.end())
{
overriddenValue.DeepCopy(*iter);
overriddenValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
overriddenValue.SetAllowSignalOnChange(false);
// check that a name update is not necessary anymore
}
}
//////////////////////////////////////////////////////////////////////////
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
// the above will provide the data to handle the cases where only certain dependency nodes were removed
// until then we do a sanity check, if any part of the depenecies were altered, assume no overrides are valid.
if (m_dependencies.size() != source.m_dependencies.size())
{
return;
}
else
{
for (size_t index = 0; index != m_dependencies.size(); ++index)
{
if (m_dependencies[index].m_source != source.m_dependencies[index].m_source)
{
return;
}
}
}
//////////////////////////////////////////////////////////////////////////
for (size_t index = 0; index != m_dependencies.size(); ++index)
{
m_dependencies[index].CopyPreviousOverriddenValues(source.m_dependencies[index]);
}
}
bool BuildVariableOverrides::IsEmpty() const
{
return m_variables.empty() && m_entityIds.empty() && m_dependencies.empty();
}
void BuildVariableOverrides::Reflect(AZ::ReflectContext* reflectContext)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
{
serializeContext->Class<BuildVariableOverrides>()
->Version(0)
->Field("source", &BuildVariableOverrides::m_source)
->Field("variables", &BuildVariableOverrides::m_variables)
->Field("entityId", &BuildVariableOverrides::m_entityIds)
->Field("overrides", &BuildVariableOverrides::m_overrides)
->Field("dependencies", &BuildVariableOverrides::m_dependencies)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class< BuildVariableOverrides>("Variables", "Variables exposed by the attached Script Canvas Graph")
->ClassElement(AZ::Edit::ClassElements::Group, "Variable Fields")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &BuildVariableOverrides::m_overrides, "Variables", "Array of Variables within Script Canvas Graph")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &BuildVariableOverrides::m_dependencies, "Dependencies", "Variables in Dependencies of the Script Canvas Graph")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
;
}
}
}
// use this to initialize the new data, and make sure they have a editor graph variable for proper editor display
void BuildVariableOverrides::PopulateFromParsedResults(const ScriptCanvas::Grammar::ParsedRuntimeInputs& inputs, const ScriptCanvas::VariableData& variables)
{
for (auto& variable : inputs.m_variables)
{
auto graphVariable = variables.FindVariable(variable.first);
if (!graphVariable)
{
AZ_Error("ScriptCanvasBuilder", false, "Missing Variable from graph data that was just parsed");
continue;
}
m_variables.push_back(*graphVariable);
auto& buildVariable = m_variables.back();
buildVariable.DeepCopy(*graphVariable); // in case of BCO, a new one needs to be created
// copy to override list for editor display
m_overrides.push_back(*graphVariable);
auto& overrideValue = m_overrides.back();
overrideValue.DeepCopy(*graphVariable);
overrideValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
overrideValue.SetAllowSignalOnChange(false);
}
for (auto& entityId : inputs.m_entityIds)
{
m_entityIds.push_back(entityId);
if (!ScriptCanvas::Grammar::IsParserGeneratedId(entityId.first))
{
auto graphEntityId = variables.FindVariable(entityId.first);
if (!graphEntityId)
{
AZ_Error("ScriptCanvasBuilder", false, "Missing EntityId from graph data that was just parsed");
continue;
}
// copy to override list for editor display
if (graphEntityId->IsComponentProperty())
{
m_overrides.push_back(*graphEntityId);
auto& overrideValue = m_overrides.back();
overrideValue.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
overrideValue.SetAllowSignalOnChange(false);
}
}
}
}
EditorAssetTree* EditorAssetTree::ModRoot()
{
if (!m_parent)
{
return this;
}
return m_parent->ModRoot();
}
void EditorAssetTree::SetParent(EditorAssetTree& parent)
{
m_parent = &parent;
}
AZStd::string EditorAssetTree::ToString(size_t depth) const
{
AZStd::string result;
ScriptCanvasBuilderCpp::AppendTabs(result, depth);
result += m_asset.GetId().ToString<AZStd::string>();
result += m_asset.GetHint();
depth += m_dependencies.empty() ? 0 : 1;
for (const auto& dependency : m_dependencies)
{
result += "\n";
ScriptCanvasBuilderCpp::AppendTabs(result, depth);
result += dependency.ToString(depth);
}
return result;
}
ScriptCanvas::RuntimeDataOverrides ConvertToRuntime(const BuildVariableOverrides& buildOverrides)
{
ScriptCanvas::RuntimeDataOverrides runtimeOverrides;
runtimeOverrides.m_runtimeAsset = AZ::Data::Asset<ScriptCanvas::RuntimeAsset>
(AZ::Data::AssetId(buildOverrides.m_source.GetId().m_guid, AZ_CRC("RuntimeData", 0x163310ae)), azrtti_typeid<ScriptCanvas::RuntimeAsset>(), {});
runtimeOverrides.m_runtimeAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
runtimeOverrides.m_variableIndices.resize(buildOverrides.m_variables.size());
for (size_t index = 0; index != buildOverrides.m_variables.size(); ++index)
{
auto& variable = buildOverrides.m_variables[index];
auto iter = AZStd::find_if
( buildOverrides.m_overrides.begin()
, buildOverrides.m_overrides.end()
, [&variable](auto& candidate) { return candidate.GetVariableId() == variable.GetVariableId(); });
if (iter != buildOverrides.m_overrides.end())
{
if (iter->GetDatum())
{
runtimeOverrides.m_variables.push_back(ScriptCanvas::RuntimeVariable(iter->GetDatum()->ToAny()));
runtimeOverrides.m_variableIndices[index] = true;
}
else
{
AZ_Warning("ScriptCanvasBuilder", false, "build overrides missing variable override, Script may not function properly");
runtimeOverrides.m_variableIndices[index] = false;
}
}
else
{
runtimeOverrides.m_variableIndices[index] = false;
}
}
for (auto& entity : buildOverrides.m_entityIds)
{
auto& variableId = entity.first;
auto iter = AZStd::find_if(buildOverrides.m_overrides.begin(), buildOverrides.m_overrides.end(), [&variableId](auto& candidate) { return candidate.GetVariableId() == variableId; });
if (iter != buildOverrides.m_overrides.end())
{
// the entity was overridden on the instance
if (iter->GetDatum() && iter->GetDatum()->GetAs<AZ::EntityId>())
{
runtimeOverrides.m_entityIds.push_back(*iter->GetDatum()->GetAs<AZ::EntityId>());
}
else
{
AZ_Warning("ScriptCanvasBuilder", false, "build overrides missing EntityId, Script may not function properly");
runtimeOverrides.m_entityIds.push_back(AZ::EntityId{});
}
}
else
{
// the entity is overridden, as part of the required process of to instantiation
runtimeOverrides.m_entityIds.push_back(entity.second);
}
}
for (auto& buildDependency : buildOverrides.m_dependencies)
{
runtimeOverrides.m_dependencies.push_back(ConvertToRuntime(buildDependency));
}
return runtimeOverrides;
}
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(AZ::Data::AssetId editorAssetId, AZStd::string_view assetHint, EditorAssetTree* parent)
{
EditorAssetTree result;
AZ::Data::AssetInfo assetInfo;
AZStd::string watchFolder;
bool resultFound = false;
if (!AzToolsFramework::AssetSystemRequestBus::FindFirstHandler())
{
return AZ::Failure(AZStd::string("LoadEditorAssetTree found no handler for AzToolsFramework::AssetSystemRequestBus."));
}
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( resultFound
, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourceUUID
, editorAssetId.m_guid
, assetInfo
, watchFolder);
if (!resultFound)
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to get engine relative path from %s-%.*s.", editorAssetId.ToString<AZStd::string>().c_str(), aznumeric_cast<int>(assetHint.size()), assetHint.data()));
}
AZStd::vector<AZ::Data::AssetId> dependentAssets;
auto filterCB = [&dependentAssets](const AZ::Data::AssetFilterInfo& filterInfo)->bool
{
if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>())
{
dependentAssets.push_back(AZ::Data::AssetId(filterInfo.m_assetId.m_guid, 0));
}
else if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>())
{
dependentAssets.push_back(filterInfo.m_assetId);
}
return true;
};
auto loadAssetOutcome = ScriptCanvasBuilder::LoadEditorAsset(assetInfo.m_relativePath, editorAssetId, filterCB);
if (!loadAssetOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load graph from %s-%s: %s", editorAssetId.ToString<AZStd::string>().c_str(), assetHint.data(), loadAssetOutcome.GetError().c_str()));
}
for (auto& dependentAsset : dependentAssets)
{
auto loadDependentOutcome = LoadEditorAssetTree(dependentAsset, "", &result);
if (!loadDependentOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format("LoadEditorAssetTree failed to load dependent graph from %s-%s: %s", editorAssetId.ToString<AZStd::string>().c_str(), assetHint.data(), loadDependentOutcome.GetError().c_str()));
}
result.m_dependencies.push_back(loadDependentOutcome.TakeValue());
}
if (parent)
{
result.SetParent(*parent);
}
result.m_asset = loadAssetOutcome.TakeValue();
return AZ::Success(result);
}
AZ::Outcome<BuildVariableOverrides, AZStd::string> ParseEditorAssetTree(const EditorAssetTree& editorAssetTree)
{
auto buildEntity = editorAssetTree.m_asset->GetScriptCanvasEntity();
if (!buildEntity)
{
return AZ::Failure(AZStd::string("No entity from source asset"));
}
auto variableComponent = AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::GraphVariableManagerComponent>(buildEntity);
if (!variableComponent)
{
return AZ::Failure(AZStd::string("No GraphVariableManagerComponent in source Entity"));
}
const ScriptCanvas::VariableData* variableData = variableComponent->GetVariableDataConst(); // get this from the entity
if (!variableData)
{
return AZ::Failure(AZStd::string("No variableData in source GraphVariableManagerComponent"));
}
auto parseOutcome = ScriptCanvasBuilder::ParseGraph(*buildEntity, "");
if (!parseOutcome.IsSuccess() || !parseOutcome.GetValue())
{
return AZ::Failure(AZStd::string("graph failed to parse"));
}
BuildVariableOverrides result;
result.m_source = editorAssetTree.m_asset;
result.PopulateFromParsedResults(parseOutcome.GetValue()->GetRuntimeInputs(), *variableData);
// recurse...
for (auto& dependentAsset : editorAssetTree.m_dependencies)
{
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
auto parseDependentOutcome = ParseEditorAssetTree(dependentAsset);
if (!parseDependentOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string::format
("ParseEditorAssetTree failed to parse dependent graph from %s-%s: %s"
, dependentAsset.m_asset.GetId().ToString<AZStd::string>().c_str()
, dependentAsset.m_asset.GetHint().c_str()
, parseDependentOutcome.GetError().c_str()));
}
result.m_dependencies.push_back(parseDependentOutcome.TakeValue());
}
return AZ::Success(result);
}
}

@ -0,0 +1,82 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Variable/VariableCore.h>
namespace ScriptCanvas
{
namespace Grammar
{
struct ParsedRuntimeInputs;
}
}
namespace ScriptCanvasEditor
{
class ScriptCanvasAsset;
}
namespace ScriptCanvasBuilder
{
class BuildVariableOverrides
{
public:
AZ_TYPE_INFO(BuildVariableOverrides, "{8336D44C-8EDC-4C28-AEB4-3420D5FD5AE2}");
AZ_CLASS_ALLOCATOR(BuildVariableOverrides, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* reflectContext);
void Clear();
// use this to preserve old values that may have been overridden on the instance, and are still valid in the parsed graph
void CopyPreviousOverriddenValues(const BuildVariableOverrides& source);
bool IsEmpty() const;
// use this to initialize the new data, and make sure they have a editor graph variable for proper editor display
void PopulateFromParsedResults(const ScriptCanvas::Grammar::ParsedRuntimeInputs& inputs, const ScriptCanvas::VariableData& variables);
// #functions2 provide an identifier for the node/variable in the source that caused the dependency. the root will not have one.
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> m_source;
// all of the variables here are overrides
AZStd::vector<ScriptCanvas::GraphVariable> m_variables;
// the values here may or may not be overrides
AZStd::vector<AZStd::pair<ScriptCanvas::VariableId, AZ::EntityId>> m_entityIds;
// this is all that gets exposed to the edit context
AZStd::vector<ScriptCanvas::GraphVariable> m_overrides;
// AZStd::vector<size_t> m_entityIdRuntimeInputIndices; since all of the entity ids need to go in, they may not need indices
AZStd::vector<BuildVariableOverrides> m_dependencies;
};
class EditorAssetTree
{
public:
AZ_CLASS_ALLOCATOR(EditorAssetTree, AZ::SystemAllocator, 0);
EditorAssetTree* m_parent = nullptr;
AZStd::vector<EditorAssetTree> m_dependencies;
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> m_asset;
EditorAssetTree* ModRoot();
void SetParent(EditorAssetTree& parent);
AZStd::string ToString(size_t depth = 0) const;
};
// copy the variables overridden during editor / prefab build time back to runtime data
ScriptCanvas::RuntimeDataOverrides ConvertToRuntime(const BuildVariableOverrides& overrides);
AZ::Outcome<EditorAssetTree, AZStd::string> LoadEditorAssetTree(AZ::Data::AssetId editorAssetId, AZStd::string_view assetHint, EditorAssetTree* parent = nullptr);
AZ::Outcome<BuildVariableOverrides, AZStd::string> ParseEditorAssetTree(const EditorAssetTree& editorAssetTree);
}

@ -10,6 +10,7 @@
#include <AssetBuilderSDK/AssetBuilderBusses.h> #include <AssetBuilderSDK/AssetBuilderBusses.h>
#include <AzCore/std/containers/map.h> #include <AzCore/std/containers/map.h>
#include <AzToolsFramework/ToolsComponents/ToolsAssetCatalogBus.h> #include <AzToolsFramework/ToolsComponents/ToolsAssetCatalogBus.h>
#include <Builder/ScriptCanvasBuilder.h>
#include <Builder/ScriptCanvasBuilderComponent.h> #include <Builder/ScriptCanvasBuilderComponent.h>
#include <Builder/ScriptCanvasBuilderWorker.h> #include <Builder/ScriptCanvasBuilderWorker.h>
#include <ScriptCanvas/Asset/Functions/RuntimeFunctionAssetHandler.h> #include <ScriptCanvas/Asset/Functions/RuntimeFunctionAssetHandler.h>
@ -163,6 +164,8 @@ namespace ScriptCanvasBuilder
void PluginComponent::Reflect(AZ::ReflectContext* context) void PluginComponent::Reflect(AZ::ReflectContext* context)
{ {
BuildVariableOverrides::Reflect(context);
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{ {
serializeContext->Class<PluginComponent, AZ::Component>() serializeContext->Class<PluginComponent, AZ::Component>()

@ -70,6 +70,7 @@ namespace ScriptCanvasBuilder
AZ_Warning(s_scriptCanvasBuilder, false, "CreateJobs for \"%s\" failed because the source file could not be opened.", fullPath.data()); AZ_Warning(s_scriptCanvasBuilder, false, "CreateJobs for \"%s\" failed because the source file could not be opened.", fullPath.data());
return; return;
} }
AZStd::vector<AZ::u8> fileBuffer(ioStream.GetLength()); AZStd::vector<AZ::u8> fileBuffer(ioStream.GetLength());
size_t bytesRead = ioStream.Read(fileBuffer.size(), fileBuffer.data()); size_t bytesRead = ioStream.Read(fileBuffer.size(), fileBuffer.data());
if (bytesRead != ioStream.GetLength()) if (bytesRead != ioStream.GetLength())
@ -87,15 +88,15 @@ namespace ScriptCanvasBuilder
{ {
// force load these before processing // force load these before processing
if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>() if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>()
|| filterInfo.m_assetType == azrtti_typeid<ScriptEvents::ScriptEventsAsset>()) || filterInfo.m_assetType == azrtti_typeid<ScriptEvents::ScriptEventsAsset>())
{ {
this->m_processEditorAssetDependencies.push_back(filterInfo); this->m_processEditorAssetDependencies.push_back(filterInfo);
} }
// these trigger re-processing // these trigger re-processing
if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>() if (filterInfo.m_assetType == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>()
|| filterInfo.m_assetType == azrtti_typeid<ScriptEvents::ScriptEventsAsset>() || filterInfo.m_assetType == azrtti_typeid<ScriptEvents::ScriptEventsAsset>()
|| filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>()) || filterInfo.m_assetType == azrtti_typeid<ScriptCanvas::SubgraphInterfaceAsset>())
{ {
AssetBuilderSDK::SourceFileDependency dependency; AssetBuilderSDK::SourceFileDependency dependency;
dependency.m_sourceFileDependencyUUID = filterInfo.m_assetId.m_guid; dependency.m_sourceFileDependencyUUID = filterInfo.m_assetId.m_guid;
@ -210,7 +211,7 @@ namespace ScriptCanvasBuilder
bool pathFound = false; bool pathFound = false;
AZStd::string relativePath; AZStd::string relativePath;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( pathFound (pathFound
, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath , &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath
, request.m_fullPath.c_str(), relativePath); , request.m_fullPath.c_str(), relativePath);

@ -55,6 +55,8 @@ namespace ScriptCanvasBuilder
DependencyArguments, DependencyArguments,
DependencyRequirementsData, DependencyRequirementsData,
AddAssetDependencySearch, AddAssetDependencySearch,
PrefabIntegration,
CorrectGraphVariableVersion,
// add new entries above // add new entries above
Current, Current,
}; };
@ -130,10 +132,12 @@ namespace ScriptCanvasBuilder
int GetBuilderVersion(); int GetBuilderVersion();
AZ::Outcome<AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view graphPath); AZ::Outcome<AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view graphPath, AZ::Data::AssetId assetId, AZ::Data::AssetFilterCB assetFilterCB = {});
AZ::Outcome<AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasFunctionAsset>, AZStd::string> LoadEditorFunctionAsset(AZStd::string_view graphPath); AZ::Outcome<AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasFunctionAsset>, AZStd::string> LoadEditorFunctionAsset(AZStd::string_view graphPath);
AZ::Outcome<ScriptCanvas::Grammar::AbstractCodeModelConstPtr, AZStd::string> ParseGraph(AZ::Entity& buildEntity, AZStd::string_view graphPath);
AZ::Outcome<void, AZStd::string> ProcessTranslationJob(ProcessTranslationJobInput& input); AZ::Outcome<void, AZStd::string> ProcessTranslationJob(ProcessTranslationJobInput& input);
ScriptCanvasEditor::Graph* PrepareSourceGraph(AZ::Entity* const buildEntity); ScriptCanvasEditor::Graph* PrepareSourceGraph(AZ::Entity* const buildEntity);
@ -149,7 +153,7 @@ namespace ScriptCanvasBuilder
{ {
public: public:
static AZ::Uuid GetUUID(); static AZ::Uuid GetUUID();
Worker() = default; Worker() = default;
Worker(const Worker&) = delete; Worker(const Worker&) = delete;
@ -175,7 +179,7 @@ namespace ScriptCanvasBuilder
// cached on first time query // cached on first time query
mutable AZStd::string m_fingerprintString; mutable AZStd::string m_fingerprintString;
}; };
class FunctionWorker class FunctionWorker
: public AssetBuilderSDK::AssetBuilderCommandBus::Handler : public AssetBuilderSDK::AssetBuilderCommandBus::Handler
{ {
@ -195,7 +199,7 @@ namespace ScriptCanvasBuilder
int GetVersionNumber() const; int GetVersionNumber() const;
void ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const; void ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const;
void ShutDown() override {}; void ShutDown() override {};
private: private:

@ -17,9 +17,7 @@
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Script/ScriptComponent.h> #include <AzFramework/Script/ScriptComponent.h>
#include <AzFramework/StringFunc/StringFunc.h> #include <AzFramework/StringFunc/StringFunc.h>
#include <Builder/ScriptCanvasBuilderWorker.h> #include <Builder/ScriptCanvasBuilderWorker.h>
#include <ScriptCanvas/Asset/Functions/RuntimeFunctionAssetHandler.h> #include <ScriptCanvas/Asset/Functions/RuntimeFunctionAssetHandler.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h> #include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Asset/RuntimeAssetHandler.h> #include <ScriptCanvas/Asset/RuntimeAssetHandler.h>
@ -32,7 +30,6 @@
#include <ScriptCanvas/Grammar/AbstractCodeModel.h> #include <ScriptCanvas/Grammar/AbstractCodeModel.h>
#include <ScriptCanvas/Results/ErrorText.h> #include <ScriptCanvas/Results/ErrorText.h>
#include <ScriptCanvas/Utils/BehaviorContextUtils.h> #include <ScriptCanvas/Utils/BehaviorContextUtils.h>
#include <Source/Components/SceneComponent.h> #include <Source/Components/SceneComponent.h>
namespace ScriptCanvasBuilder namespace ScriptCanvasBuilder
@ -62,6 +59,26 @@ namespace ScriptCanvasBuilder
} }
} }
AZ::Outcome<ScriptCanvas::Grammar::AbstractCodeModelConstPtr, AZStd::string> ParseGraph(AZ::Entity& buildEntity, AZStd::string_view graphPath)
{
AZStd::string fileNameOnly;
AzFramework::StringFunc::Path::GetFullFileName(graphPath.data(), fileNameOnly);
ScriptCanvas::Grammar::Request request;
request.graph = PrepareSourceGraph(&buildEntity);
if (!request.graph)
{
return AZ::Failure(AZStd::string("build entity did not have source graph components"));
}
request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFileAtPrefabTime;
request.printModelToConsole = ScriptCanvas::Grammar::g_printAbstractCodeModelAtPrefabTime;
request.name = fileNameOnly.empty() ? fileNameOnly : "BuilderGraph";
request.addDebugInformation = false;
return ScriptCanvas::Translation::ParseGraph(request);
}
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(AZ::Entity* buildEntity, AZ::Data::AssetId scriptAssetId, AZStd::string_view rawLuaFilePath) AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> CreateLuaAsset(AZ::Entity* buildEntity, AZ::Data::AssetId scriptAssetId, AZStd::string_view rawLuaFilePath)
{ {
AZStd::string fullPath(rawLuaFilePath); AZStd::string fullPath(rawLuaFilePath);
@ -72,7 +89,7 @@ namespace ScriptCanvasBuilder
auto sourceGraph = PrepareSourceGraph(buildEntity); auto sourceGraph = PrepareSourceGraph(buildEntity);
ScriptCanvas::Grammar::Request request; ScriptCanvas::Grammar::Request request;
request.assetId = scriptAssetId; request.scriptAssetId = scriptAssetId;
request.graph = sourceGraph; request.graph = sourceGraph;
request.name = fileNameOnly; request.name = fileNameOnly;
request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile; request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile;
@ -82,7 +99,7 @@ namespace ScriptCanvasBuilder
bool pathFound = false; bool pathFound = false;
AZStd::string relativePath; AZStd::string relativePath;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult AzToolsFramework::AssetSystemRequestBus::BroadcastResult
( pathFound (pathFound
, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath , &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath
, fullPath.c_str(), relativePath); , fullPath.c_str(), relativePath);
@ -396,7 +413,7 @@ namespace ScriptCanvasBuilder
; ;
} }
AZ::Outcome < AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view filePath) AZ::Outcome < AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view filePath, AZ::Data::AssetId assetId, AZ::Data::AssetFilterCB assetFilterCB)
{ {
AZStd::shared_ptr<AZ::Data::AssetDataStream> assetDataStream = AZStd::make_shared<AZ::Data::AssetDataStream>(); AZStd::shared_ptr<AZ::Data::AssetDataStream> assetDataStream = AZStd::make_shared<AZ::Data::AssetDataStream>();
@ -425,9 +442,9 @@ namespace ScriptCanvasBuilder
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext); AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> asset; AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> asset;
asset.Create(AZ::Data::AssetId(AZ::Uuid::CreateRandom())); asset.Create(assetId);
if (editorAssetHandler.LoadAssetData(asset, assetDataStream, AZ::Data::AssetFilterCB{}) != AZ::Data::AssetHandler::LoadResult::LoadComplete) if (editorAssetHandler.LoadAssetData(asset, assetDataStream, assetFilterCB) != AZ::Data::AssetHandler::LoadResult::LoadComplete)
{ {
return AZ::Failure(AZStd::string::format("Failed to load ScriptCavas asset: %s", filePath.data())); return AZ::Failure(AZStd::string::format("Failed to load ScriptCavas asset: %s", filePath.data()));
} }
@ -513,10 +530,7 @@ namespace ScriptCanvasBuilder
} }
} }
if (buildEntity->GetState() == AZ::Entity::State::Constructed) ScriptCanvas::ScopedAuxiliaryEntityHandler entityHandler(buildEntity);
{
buildEntity->Init();
}
if (buildEntity->GetState() == AZ::Entity::State::Init) if (buildEntity->GetState() == AZ::Entity::State::Init)
{ {
@ -533,7 +547,7 @@ namespace ScriptCanvasBuilder
auto version = sourceGraph->GetVersion(); auto version = sourceGraph->GetVersion();
if (version.grammarVersion == ScriptCanvas::GrammarVersion::Initial if (version.grammarVersion == ScriptCanvas::GrammarVersion::Initial
|| version.runtimeVersion == ScriptCanvas::RuntimeVersion::Initial) || version.runtimeVersion == ScriptCanvas::RuntimeVersion::Initial)
{ {
return AZ::Failure(AZStd::string(ScriptCanvas::ParseErrors::SourceUpdateRequired)); return AZ::Failure(AZStd::string(ScriptCanvas::ParseErrors::SourceUpdateRequired));
} }
@ -542,7 +556,7 @@ namespace ScriptCanvasBuilder
request.path = input.fullPath; request.path = input.fullPath;
request.name = input.fileNameOnly; request.name = input.fileNameOnly;
request.namespacePath = input.namespacePath; request.namespacePath = input.namespacePath;
request.assetId = input.assetID; request.scriptAssetId = input.assetID;
request.graph = sourceGraph; request.graph = sourceGraph;
request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile; request.rawSaveDebugOutput = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile;
request.printModelToConsole = ScriptCanvas::Grammar::g_printAbstractCodeModel; request.printModelToConsole = ScriptCanvas::Grammar::g_printAbstractCodeModel;
@ -728,6 +742,6 @@ namespace ScriptCanvasBuilder
ScriptCanvas::Translation::Result TranslateToLua(ScriptCanvas::Grammar::Request& request) ScriptCanvas::Translation::Result TranslateToLua(ScriptCanvas::Grammar::Request& request)
{ {
request.translationTargetFlags = ScriptCanvas::Translation::TargetFlags::Lua; request.translationTargetFlags = ScriptCanvas::Translation::TargetFlags::Lua;
return ScriptCanvas::Translation::ParseGraph(request); return ScriptCanvas::Translation::ParseAndTranslateGraph(request);
} }
} }

@ -19,19 +19,30 @@
#include <AzFramework/StringFunc/StringFunc.h> #include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h> #include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Core/ScriptCanvasBus.h> #include <Core/ScriptCanvasBus.h>
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h> #include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h> #include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h> #include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
#include <ScriptCanvas/Bus/RequestBus.h> #include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/Components/EditorGraph.h> #include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h> #include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponent.h> #include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
#include <ScriptCanvas/Core/Node.h> #include <ScriptCanvas/Core/Node.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <ScriptCanvas/PerformanceStatisticsBus.h> #include <ScriptCanvas/PerformanceStatisticsBus.h>
namespace EditorScriptCanvasComponentCpp
{
enum Version
{
PrefabIntegration = 10,
// add description above
Current
};
}
namespace ScriptCanvasEditor namespace ScriptCanvasEditor
{ {
static bool EditorScriptCanvasComponentVersionConverter(AZ::SerializeContext& serializeContext, AZ::SerializeContext::DataElementNode& rootElement) static bool EditorScriptCanvasComponentVersionConverter(AZ::SerializeContext& serializeContext, AZ::SerializeContext::DataElementNode& rootElement)
@ -74,6 +85,63 @@ namespace ScriptCanvasEditor
rootElement.RemoveElementByName(AZ_CRC("m_variableEntityIdMap", 0xdc6c75a8)); rootElement.RemoveElementByName(AZ_CRC("m_variableEntityIdMap", 0xdc6c75a8));
} }
if (rootElement.GetVersion() <= EditorScriptCanvasComponentCpp::Version::PrefabIntegration)
{
auto variableDataElementIndex = rootElement.FindElement(AZ_CRC_CE("m_variableData"));
if (variableDataElementIndex == -1)
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: 'm_variableData' index was missing");
return false;
}
auto& variableDataElement = rootElement.GetSubElement(variableDataElementIndex);
ScriptCanvas::EditableVariableData editableData;
if (!variableDataElement.GetData(editableData))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: could not retrieve old 'm_variableData'");
return false;
}
auto scriptCanvasAssetHolderElementIndex = rootElement.FindElement(AZ_CRC_CE("m_assetHolder"));
if (scriptCanvasAssetHolderElementIndex == -1)
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: 'm_assetHolder' index was missing");
return false;
}
auto& scriptCanvasAssetHolderElement = rootElement.GetSubElement(scriptCanvasAssetHolderElementIndex);
ScriptCanvasAssetHolder assetHolder;
if (!scriptCanvasAssetHolderElement.GetData(assetHolder))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: could not retrieve old 'm_assetHolder'");
return false;
}
rootElement.RemoveElement(variableDataElementIndex);
if (!rootElement.AddElementWithData(serializeContext, "runtimeDataIsValid", true))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: failed to add 'runtimeDataIsValid'");
return false;
}
ScriptCanvasBuilder::BuildVariableOverrides overrides;
overrides.m_source = AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>(assetHolder.GetAssetId(), assetHolder.GetAssetType(), assetHolder.GetAssetHint());;
for (auto& variable : editableData.GetVariables())
{
overrides.m_overrides.push_back(variable.m_graphVariable);
}
if (!rootElement.AddElementWithData(serializeContext, "runtimeDataOverrides", overrides))
{
AZ_Error("ScriptCanvas", false, "EditorScriptCanvasComponent conversion failed: failed to add 'runtimeDataOverrides'");
return false;
}
}
return true; return true;
} }
@ -83,10 +151,11 @@ namespace ScriptCanvasEditor
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{ {
serializeContext->Class<EditorScriptCanvasComponent, EditorComponentBase>() serializeContext->Class<EditorScriptCanvasComponent, EditorComponentBase>()
->Version(8, &EditorScriptCanvasComponentVersionConverter) ->Version(EditorScriptCanvasComponentCpp::Version::Current, &EditorScriptCanvasComponentVersionConverter)
->Field("m_name", &EditorScriptCanvasComponent::m_name) ->Field("m_name", &EditorScriptCanvasComponent::m_name)
->Field("m_assetHolder", &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder) ->Field("m_assetHolder", &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder)
->Field("m_variableData", &EditorScriptCanvasComponent::m_editableData) ->Field("runtimeDataIsValid", &EditorScriptCanvasComponent::m_runtimeDataIsValid)
->Field("runtimeDataOverrides", &EditorScriptCanvasComponent::m_variableOverrides)
; ;
if (AZ::EditContext* editContext = serializeContext->GetEditContext()) if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@ -103,9 +172,9 @@ namespace ScriptCanvasEditor
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Level", 0x9aeacc13)) ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Level", 0x9aeacc13))
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/script-canvas/") ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/script-canvas/")
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder, "Script Canvas Asset", "Script Canvas asset associated with this component") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder, "Script Canvas Asset", "Script Canvas asset associated with this component")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_editableData, "Properties", "Script Canvas Graph Properties") ->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)
; ;
} }
} }
@ -133,6 +202,11 @@ namespace ScriptCanvasEditor
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
} }
const AZStd::string& EditorScriptCanvasComponent::GetName() const
{
return m_name;
}
void EditorScriptCanvasComponent::UpdateName() void EditorScriptCanvasComponent::UpdateName()
{ {
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId(); AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
@ -208,18 +282,7 @@ namespace ScriptCanvasEditor
if (fileAssetId.IsValid()) if (fileAssetId.IsValid())
{ {
AssetTrackerNotificationBus::Handler::BusConnect(fileAssetId); AssetTrackerNotificationBus::Handler::BusConnect(fileAssetId);
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
ScriptCanvasMemoryAsset::pointer memoryAsset;
AssetTrackerRequestBus::BroadcastResult(memoryAsset, &AssetTrackerRequests::GetAsset, fileAssetId);
if (memoryAsset && memoryAsset->GetAsset().GetStatus() == AZ::Data::AssetData::AssetStatus::Ready)
{
OnScriptCanvasAssetReady(memoryAsset);
}
else
{
AssetTrackerRequestBus::Broadcast(&AssetTrackerRequests::Load, m_scriptCanvasAssetHolder.GetAssetId(), m_scriptCanvasAssetHolder.GetAssetType(), nullptr);
}
} }
} }
@ -233,81 +296,67 @@ namespace ScriptCanvasEditor
EditorComponentBase::Deactivate(); EditorComponentBase::Deactivate();
//EditorScriptCanvasAssetNotificationBus::Handler::BusDisconnect();
EditorScriptCanvasComponentRequestBus::Handler::BusDisconnect(); EditorScriptCanvasComponentRequestBus::Handler::BusDisconnect();
EditorContextMenuRequestBus::Handler::BusDisconnect(); EditorContextMenuRequestBus::Handler::BusDisconnect();
} }
//========================================================================= void EditorScriptCanvasComponent::BuildGameEntityData()
void EditorScriptCanvasComponent::BuildGameEntity(AZ::Entity* gameEntity)
{ {
AZ::Data::AssetId editorAssetId = m_scriptCanvasAssetHolder.GetAssetId(); using namespace ScriptCanvasBuilder;
m_runtimeDataIsValid = false;
if (!editorAssetId.IsValid()) auto assetTreeOutcome = LoadEditorAssetTree(m_scriptCanvasAssetHolder.GetAssetId(), m_scriptCanvasAssetHolder.GetAssetHint());
if (!assetTreeOutcome.IsSuccess())
{ {
AZ_Warning("ScriptCanvas", false, "EditorScriptCanvasComponent::BuildGameEntityData failed: %s", assetTreeOutcome.GetError().c_str());
return; return;
} }
AZ::Data::AssetId runtimeAssetId(editorAssetId.m_guid, AZ_CRC("RuntimeData", 0x163310ae)); EditorAssetTree& editorAssetTree = assetTreeOutcome.GetValue();
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> runtimeAsset(runtimeAssetId, azrtti_typeid<ScriptCanvas::RuntimeAsset>(), {});
/* auto parseOutcome = ParseEditorAssetTree(editorAssetTree);
if (!parseOutcome.IsSuccess())
This defense against creating useless runtime components is pending changes the slice update system. {
It also would require better abilities to check asset integrity when building assets that depend AZ_Warning("ScriptCanvas", false, "EditorScriptCanvasComponent::BuildGameEntityData failed: %s", parseOutcome.GetError().c_str());
on ScriptCanvas assets. return;
}
AZ::Data::AssetInfo assetInfo; auto& variableOverrides = parseOutcome.GetValue();
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, runtimeAssetId);
if (assetInfo.m_assetType == AZ::Data::s_invalidAssetType) if (!m_variableOverrides.IsEmpty())
{ {
AZ_Warning("ScriptCanvas", false, "No ScriptCanvas Runtime Asset information for Entity ('%s' - '%s') Graph ('%s'), asset may be in error or deleted" variableOverrides.CopyPreviousOverriddenValues(m_variableOverrides);
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
return;
} }
AzFramework::AssetSystem::AssetStatus statusResult = AzFramework::AssetSystem::AssetStatus_Unknown; m_variableOverrides = parseOutcome.TakeValue();
AzFramework::AssetSystemRequestBus::BroadcastResult(statusResult, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, runtimeAssetId); m_runtimeDataIsValid = true;
}
if (statusResult != AzFramework::AssetSystem::AssetStatus_Compiled) void EditorScriptCanvasComponent::BuildGameEntity(AZ::Entity* gameEntity)
{
if (!m_runtimeDataIsValid)
{ {
AZ_Warning("ScriptCanvas", false, "No ScriptCanvas Runtime Asset for Entity ('%s' - '%s') Graph ('%s'), compilation may have failed or not completed" // this is fine, there could have been no graph set, or set to a graph that failed to compile
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
return; return;
} }
*/
// #functions2 dependency-ctor-args make recursive // build everything again as a sanity check against dependencies. All of the variable overrides that were valid will be copied over
auto executionComponent = gameEntity->CreateComponent<ScriptCanvas::RuntimeComponent>(runtimeAsset); BuildGameEntityData();
ScriptCanvas::VariableData varData;
for (const auto& varConfig : m_editableData.GetVariables()) if (!m_runtimeDataIsValid)
{ {
if (varConfig.m_graphVariable.GetDatum()->Empty()) AZ_Error("ScriptCanvasBuilder", false, "Runtime information did not build for ScriptCanvas Component using asset: %s", m_scriptCanvasAssetHolder.GetAssetId().ToString<AZStd::string>().c_str());
{ return;
AZ_Error("ScriptCanvas", false, "Data loss detected for GraphVariable ('%s') on Entity ('%s' - '%s') Graph ('%s')"
, varConfig.m_graphVariable.GetVariableName().data()
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
}
else
{
varData.AddVariable(varConfig.m_graphVariable.GetVariableName(), varConfig.m_graphVariable);
}
} }
executionComponent->SetVariableOverrides(varData); auto runtimeComponent = gameEntity->CreateComponent<ScriptCanvas::RuntimeComponent>();
auto runtimeOverrides = ConvertToRuntime(m_variableOverrides);
runtimeComponent->SetRuntimeDataOverrides(runtimeOverrides);
} }
void EditorScriptCanvasComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) void EditorScriptCanvasComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
{ {
// If we removed out asset due to the catalog removing. Just set it back.
if (m_removedCatalogId == assetId) if (m_removedCatalogId == assetId)
{ {
if (!m_scriptCanvasAssetHolder.GetAssetId().IsValid()) if (!m_scriptCanvasAssetHolder.GetAssetId().IsValid())
@ -317,12 +366,9 @@ namespace ScriptCanvasEditor
} }
} }
} }
void EditorScriptCanvasComponent::OnCatalogAssetRemoved(const AZ::Data::AssetId& removedAssetId, const AZ::Data::AssetInfo& /*assetInfo*/) void EditorScriptCanvasComponent::OnCatalogAssetRemoved(const AZ::Data::AssetId& removedAssetId, const AZ::Data::AssetInfo& /*assetInfo*/)
{ {
AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId(); AZ::Data::AssetId assetId = m_scriptCanvasAssetHolder.GetAssetId();
// If the Asset gets removed from disk while the Editor is loaded clear out the asset reference.
if (assetId == removedAssetId) if (assetId == removedAssetId)
{ {
m_removedCatalogId = assetId; m_removedCatalogId = assetId;
@ -355,8 +401,6 @@ namespace ScriptCanvasEditor
} }
} }
AzToolsFramework::ScopedUndoBatch undo("Update Entity With New SC Graph");
AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, GetEntityId());
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
} }
@ -448,7 +492,6 @@ namespace ScriptCanvasEditor
{ {
// Invalidate the previously removed catalog id if we are setting a new asset id // Invalidate the previously removed catalog id if we are setting a new asset id
m_removedCatalogId.SetInvalid(); m_removedCatalogId.SetInvalid();
SetPrimaryAsset(assetId); SetPrimaryAsset(assetId);
} }
} }
@ -469,125 +512,17 @@ namespace ScriptCanvasEditor
{ {
if (memoryAsset->GetFileAssetId() == m_scriptCanvasAssetHolder.GetAssetId()) if (memoryAsset->GetFileAssetId() == m_scriptCanvasAssetHolder.GetAssetId())
{ {
LoadVariables(memoryAsset); auto assetData = memoryAsset->GetAsset();
AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity");
BuildGameEntityData();
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
UpdateName(); UpdateName();
} }
} }
/*! Start Variable Block Implementation */
void EditorScriptCanvasComponent::AddVariable(AZStd::string_view varName, const ScriptCanvas::GraphVariable& graphVariable)
{
// We only add component properties to the component
if (!graphVariable.IsComponentProperty())
{
return;
}
const auto& variableId = graphVariable.GetVariableId();
ScriptCanvas::EditableVariableConfiguration* originalVarNameValuePair = m_editableData.FindVariable(variableId);
if (!originalVarNameValuePair)
{
m_editableData.AddVariable(varName, graphVariable);
originalVarNameValuePair = m_editableData.FindVariable(variableId);
}
if (!originalVarNameValuePair)
{
AZ_Error("Script Canvas", false, "Unable to find variable with id %s and name %s on the ScriptCanvas Component. There is an issue in AddVariable",
variableId.ToString().data(), varName.data());
return;
}
// Update the variable name as it may have changed
originalVarNameValuePair->m_graphVariable.SetVariableName(varName);
originalVarNameValuePair->m_graphVariable.SetExposureCategory(graphVariable.GetExposureCategory());
originalVarNameValuePair->m_graphVariable.SetScriptInputControlVisibility(AZ::Edit::PropertyVisibility::Hide);
originalVarNameValuePair->m_graphVariable.SetAllowSignalOnChange(false);
}
void EditorScriptCanvasComponent::AddNewVariables(const ScriptCanvas::VariableData& graphVarData)
{
for (auto&& variablePair : graphVarData.GetVariables())
{
AddVariable(variablePair.second.GetVariableName(), variablePair.second);
}
}
void EditorScriptCanvasComponent::RemoveVariable(const ScriptCanvas::VariableId& varId)
{
m_editableData.RemoveVariable(varId);
}
void EditorScriptCanvasComponent::RemoveOldVariables(const ScriptCanvas::VariableData& graphVarData)
{
AZStd::vector<ScriptCanvas::VariableId> oldVariableIds;
for (auto varConfig : m_editableData.GetVariables())
{
const auto& variableId = varConfig.m_graphVariable.GetVariableId();
// We only add component sourced graph properties to the script canvas component, so if this variable was switched to a graph-only property remove it.
// Also be sure to remove this variable if it's been deleted entirely.
auto graphVariable = graphVarData.FindVariable(variableId);
if (!graphVariable || !graphVariable->IsComponentProperty())
{
oldVariableIds.push_back(variableId);
}
}
for (const auto& oldVariableId : oldVariableIds)
{
RemoveVariable(oldVariableId);
}
}
bool EditorScriptCanvasComponent::UpdateVariable(const ScriptCanvas::GraphVariable& graphDatum, ScriptCanvas::GraphVariable& updateDatum, ScriptCanvas::GraphVariable& originalDatum)
{
// If the editable datum is the different than the original datum, then the "variable value" has been overridden on this component
// Variable values only propagate from the Script Canvas graph to this component if the original "variable value" has not been overridden
// by the editable "variable value" on this component and the "variable value" on the graph is different than the variable value on this component
auto isNotOverridden = (*updateDatum.GetDatum()) == (*originalDatum.GetDatum());
auto scGraphIsModified = (*originalDatum.GetDatum()) != (*graphDatum.GetDatum());
if (isNotOverridden && scGraphIsModified)
{
ScriptCanvas::ModifiableDatumView originalDatumView;
originalDatum.ConfigureDatumView(originalDatumView);
originalDatumView.AssignToDatum((*graphDatum.GetDatum()));
ScriptCanvas::ModifiableDatumView updatedDatumView;
updateDatum.ConfigureDatumView(updatedDatumView);
updatedDatumView.AssignToDatum((*graphDatum.GetDatum()));
return true;
}
return false;
}
void EditorScriptCanvasComponent::LoadVariables(const ScriptCanvasMemoryAsset::pointer memoryAsset)
{
auto assetData = memoryAsset->GetAsset();
AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity");
auto variableComponent = scriptCanvasEntity ? AZ::EntityUtils::FindFirstDerivedComponent<ScriptCanvas::GraphVariableManagerComponent>(scriptCanvasEntity) : nullptr;
if (variableComponent)
{
// Add properties from the SC Asset to the SC Component if they do not exist on the SC Component
AddNewVariables(*variableComponent->GetVariableData());
RemoveOldVariables(*variableComponent->GetVariableData());
}
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
}
void EditorScriptCanvasComponent::ClearVariables() void EditorScriptCanvasComponent::ClearVariables()
{ {
m_editableData.Clear(); m_variableOverrides.Clear();
} }
/* End Variable Block Implementation*/
} }

@ -19,8 +19,15 @@ namespace ScriptCanvas
namespace ScriptCanvasEditor namespace ScriptCanvasEditor
{ {
using LoadedInterpretedDependencies = AZStd::vector<AZStd::pair<AZStd::string, ScriptCanvas::Translation::LuaAssetResult>>; struct LoadedInterpretedDependency
AZ_INLINE LoadedInterpretedDependencies LoadInterpretedDepencies(const ScriptCanvas::DependencySet& dependencySet); {
AZStd::string path;
AZ::Data::Asset<ScriptCanvas::RuntimeAsset> runtimeAsset;
ScriptCanvas::Translation::LuaAssetResult luaAssetResult;
AZStd::vector<LoadedInterpretedDependency> dependencies;
};
AZ_INLINE AZStd::vector<LoadedInterpretedDependency> LoadInterpretedDepencies(const ScriptCanvas::DependencySet& dependencySet);
AZ_INLINE LoadTestGraphResult LoadTestGraph(AZStd::string_view path); AZ_INLINE LoadTestGraphResult LoadTestGraph(AZStd::string_view path);
@ -49,10 +56,11 @@ namespace ScriptCanvasEditor
AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, Reporter& reporter); AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, Reporter& reporter);
AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, LoadTestGraphResult& loadGraphResult, Reporter& reporter); AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, LoadTestGraphResult& loadGraphResult, Reporter& reporter);
AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, Reporters& reporters); AZ_INLINE void RunGraphImplementation(const RunGraphSpec& runGraphSpec, Reporters& reporters);
AZ_INLINE void Simulate(const DurationSpec& duration); AZ_INLINE void Simulate(const DurationSpec& duration);
AZ_INLINE void SimulateDuration(const DurationSpec& duration); AZ_INLINE void SimulateDuration(const DurationSpec& duration);
AZ_INLINE void SimulateSeconds(const DurationSpec& duration); AZ_INLINE void SimulateSeconds(const DurationSpec& duration);
AZ_INLINE void SimulateTicks(const DurationSpec& duration); AZ_INLINE void SimulateTicks(const DurationSpec& duration);
} // ScriptCanvasEditor } // ScriptCanvasEditor
#include <Editor/Framework/ScriptCanvasGraphUtilities.inl> #include <Editor/Framework/ScriptCanvasGraphUtilities.inl>

@ -26,9 +26,25 @@ namespace ScriptCanvasEditor
{ {
using namespace ScriptCanvas; using namespace ScriptCanvas;
AZ_INLINE LoadedInterpretedDependencies LoadInterpretedDepencies(const ScriptCanvas::DependencySet& dependencySet) // The runtime context (appropriately) always assumes that EntityIds are overridden, this step copies the values from the runtime data
// over to the override data to simulate build step that does this when building prefabs
AZ_INLINE void CopyAssetEntityIdsToOverrides(RuntimeDataOverrides& runtimeDataOverrides)
{ {
LoadedInterpretedDependencies loadedAssets; runtimeDataOverrides.m_entityIds.reserve(runtimeDataOverrides.m_runtimeAsset->GetData().m_input.m_entityIds.size());
for (auto& varEntityPar : runtimeDataOverrides.m_runtimeAsset->GetData().m_input.m_entityIds)
{
runtimeDataOverrides.m_entityIds.push_back(varEntityPar.second);
}
for (auto& dependency : runtimeDataOverrides.m_dependencies)
{
CopyAssetEntityIdsToOverrides(dependency);
}
}
AZ_INLINE AZStd::vector<LoadedInterpretedDependency> LoadInterpretedDepencies(const ScriptCanvas::DependencySet& dependencySet)
{
AZStd::vector<LoadedInterpretedDependency> loadedAssets;
if (!dependencySet.empty()) if (!dependencySet.empty())
{ {
@ -41,7 +57,7 @@ namespace ScriptCanvasEditor
AZ_Assert(namespacePath.size() >= 3, "This functions assumes unit test dependencies are in the ScriptCanvas gem unit test folder"); AZ_Assert(namespacePath.size() >= 3, "This functions assumes unit test dependencies are in the ScriptCanvas gem unit test folder");
AZStd::string originalPath = namespacePath[2].data(); AZStd::string originalPath = namespacePath[2].data();
for (size_t index = 3; index < namespacePath.size(); ++index) for (size_t index = 3; index < namespacePath.size(); ++index)
{ {
originalPath += "/"; originalPath += "/";
@ -52,11 +68,11 @@ namespace ScriptCanvasEditor
{ {
originalPath.resize(originalPath.size() - AZStd::string_view(Grammar::k_internalRuntimeSuffix).size()); originalPath.resize(originalPath.size() - AZStd::string_view(Grammar::k_internalRuntimeSuffix).size());
} }
AZStd::string path = AZStd::string::format("%s/%s.scriptcanvas", k_unitTestDirPathRelative, originalPath.data()); AZStd::string path = AZStd::string::format("%s/%s.scriptcanvas", k_unitTestDirPathRelative, originalPath.data());
LoadTestGraphResult loadResult = LoadTestGraph(path); LoadTestGraphResult loadResult = LoadTestGraph(path);
AZ_Assert(loadResult.m_runtimeAsset, "failed to load dependent asset"); AZ_Assert(loadResult.m_runtimeAsset, "failed to load dependent asset");
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> luaAssetOutcome = AZ::Failure(AZStd::string("lua asset creation for function failed")); AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> luaAssetOutcome = AZ::Failure(AZStd::string("lua asset creation for function failed"));
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_graphPath); ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_graphPath);
AZ_Assert(luaAssetOutcome.IsSuccess(), "failed to create Lua asset"); AZ_Assert(luaAssetOutcome.IsSuccess(), "failed to create Lua asset");
@ -69,8 +85,9 @@ namespace ScriptCanvasEditor
} }
const ScriptCanvas::Translation::LuaAssetResult& luaAssetResult = luaAssetOutcome.GetValue(); const ScriptCanvas::Translation::LuaAssetResult& luaAssetResult = luaAssetOutcome.GetValue();
loadedAssets.push_back({ modulePath, luaAssetResult }); // #functions2_recursive_unit_tests
} loadedAssets.push_back({ modulePath, loadResult.m_runtimeAsset, luaAssetResult, {} });
}
} }
return loadedAssets; return loadedAssets;
@ -182,7 +199,7 @@ namespace ScriptCanvasEditor
RuntimeData runtimeDataBuffer; RuntimeData runtimeDataBuffer;
AZStd::vector<RuntimeData> dependencyDataBuffer; AZStd::vector<RuntimeData> dependencyDataBuffer;
LoadedInterpretedDependencies dependencies; AZStd::vector<LoadedInterpretedDependency> dependencies;
if (runGraphSpec.runSpec.execution == ExecutionMode::Interpreted) if (runGraphSpec.runSpec.execution == ExecutionMode::Interpreted)
{ {
@ -202,9 +219,12 @@ namespace ScriptCanvasEditor
{ {
dependencies = LoadInterpretedDepencies(luaAssetResult.m_dependencies.source.userSubgraphs); dependencies = LoadInterpretedDepencies(luaAssetResult.m_dependencies.source.userSubgraphs);
RuntimeDataOverrides runtimeDataOverrides;
runtimeDataOverrides.m_runtimeAsset = loadResult.m_runtimeAsset;
if (!dependencies.empty()) if (!dependencies.empty())
{ {
// eventually, this will need to be recursive, or the full asset handling system will need to be integrated into the testing framework // #functions2_recursive_unit_tests eventually, this will need to be recursive, or the full asset handling system will need to be integrated into the testing framework
// in order to test functionality with a dependency stack greater than 2 // in order to test functionality with a dependency stack greater than 2
// load all script assets, and their dependencies, initialize statics on all those dependencies if it is the first time loaded // load all script assets, and their dependencies, initialize statics on all those dependencies if it is the first time loaded
@ -215,7 +235,7 @@ namespace ScriptCanvasEditor
for (auto& dependency : dependencies) for (auto& dependency : dependencies)
{ {
inMemoryModules.emplace_back(dependency.first, dependency.second.m_scriptAsset); inMemoryModules.emplace_back(dependency.path, dependency.luaAssetResult.m_scriptAsset);
} }
AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::UseInMemoryRequireHook, inMemoryModules, AZ::ScriptContextIds::DefaultScriptContextId); AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::UseInMemoryRequireHook, inMemoryModules, AZ::ScriptContextIds::DefaultScriptContextId);
@ -224,7 +244,11 @@ namespace ScriptCanvasEditor
for (size_t index = 0; index < dependencies.size(); ++index) for (size_t index = 0; index < dependencies.size(); ++index)
{ {
auto& dependency = dependencies[index]; auto& dependency = dependencies[index];
const ScriptCanvas::Translation::LuaAssetResult& depencyAssetResult = dependency.second; const ScriptCanvas::Translation::LuaAssetResult& depencyAssetResult = dependency.luaAssetResult;
RuntimeDataOverrides dependencyRuntimeDataOverrides;
dependencyRuntimeDataOverrides.m_runtimeAsset = dependency.runtimeAsset;
runtimeDataOverrides.m_dependencies.push_back(dependencyRuntimeDataOverrides);
RuntimeData& dependencyData = dependencyDataBuffer[index]; RuntimeData& dependencyData = dependencyDataBuffer[index];
dependencyData.m_input = depencyAssetResult.m_runtimeInputs; dependencyData.m_input = depencyAssetResult.m_runtimeInputs;
@ -239,7 +263,9 @@ namespace ScriptCanvasEditor
loadResult.m_runtimeAsset.Get()->GetData().m_script = loadResult.m_scriptAsset; loadResult.m_runtimeAsset.Get()->GetData().m_script = loadResult.m_scriptAsset;
loadResult.m_runtimeAsset.Get()->GetData().m_input = luaAssetResult.m_runtimeInputs; loadResult.m_runtimeAsset.Get()->GetData().m_input = luaAssetResult.m_runtimeInputs;
loadResult.m_runtimeAsset.Get()->GetData().m_debugMap = luaAssetResult.m_debugMap; loadResult.m_runtimeAsset.Get()->GetData().m_debugMap = luaAssetResult.m_debugMap;
loadResult.m_runtimeComponent = loadResult.m_entity->CreateComponent<ScriptCanvas::RuntimeComponent>(loadResult.m_runtimeAsset); loadResult.m_runtimeComponent = loadResult.m_entity->CreateComponent<ScriptCanvas::RuntimeComponent>();
CopyAssetEntityIdsToOverrides(runtimeDataOverrides);
loadResult.m_runtimeComponent->SetRuntimeDataOverrides(runtimeDataOverrides);
Execution::Context::InitializeActivationData(loadResult.m_runtimeAsset->GetData()); Execution::Context::InitializeActivationData(loadResult.m_runtimeAsset->GetData());
Execution::InitializeInterpretedStatics(loadResult.m_runtimeAsset->GetData()); Execution::InitializeInterpretedStatics(loadResult.m_runtimeAsset->GetData());
} }

@ -8,14 +8,14 @@
#pragma once #pragma once
#include <AzFramework/Asset/AssetCatalogBus.h> #include <AzFramework/Asset/AssetCatalogBus.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h> #include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
#include <Builder/ScriptCanvasBuilder.h>
#include <Editor/Assets/ScriptCanvasAssetHolder.h> #include <Editor/Assets/ScriptCanvasAssetHolder.h>
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h> #include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h> #include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <ScriptCanvas/Variable/VariableBus.h> #include <ScriptCanvas/Variable/VariableBus.h>
#include <ScriptCanvas/Variable/VariableData.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
namespace ScriptCanvasEditor namespace ScriptCanvasEditor
{ {
@ -27,11 +27,10 @@ namespace ScriptCanvasEditor
which it uses to maintain the asset data in memory. Therefore removing an open ScriptCanvasAsset from the file system which it uses to maintain the asset data in memory. Therefore removing an open ScriptCanvasAsset from the file system
will remove the reference from the EditorScriptCanvasComponent, but not the reference from the MainWindow allowing the will remove the reference from the EditorScriptCanvasComponent, but not the reference from the MainWindow allowing the
ScriptCanvas graph to still be modified while open ScriptCanvas graph to still be modified while open
Finally per graph instance variables values are stored on the EditorScriptCanvasComponent and injected into the runtime ScriptCanvas component in BuildGameEntity Finally per graph instance variables values are stored on the EditorScriptCanvasComponent and injected into the runtime ScriptCanvas component in BuildGameEntity
*/ */
class EditorScriptCanvasComponent class EditorScriptCanvasComponent
: public AzToolsFramework::Components::EditorComponentBase : public AzToolsFramework::Components::EditorComponentBase
, private EditorContextMenuRequestBus::Handler , private EditorContextMenuRequestBus::Handler
, private AzFramework::AssetCatalogEventBus::Handler , private AzFramework::AssetCatalogEventBus::Handler
, private EditorScriptCanvasComponentLoggingBus::Handler , private EditorScriptCanvasComponentLoggingBus::Handler
@ -54,7 +53,6 @@ namespace ScriptCanvasEditor
void Deactivate() override; void Deactivate() override;
//===================================================================== //=====================================================================
//===================================================================== //=====================================================================
// EditorComponentBase // EditorComponentBase
void BuildGameEntity(AZ::Entity* gameEntity) override; void BuildGameEntity(AZ::Entity* gameEntity) override;
@ -71,10 +69,10 @@ namespace ScriptCanvasEditor
void CloseGraph(); void CloseGraph();
void SetName(const AZStd::string& name) { m_name = name; } void SetName(const AZStd::string& name) { m_name = name; }
const AZStd::string& GetName() const { return m_name; }; const AZStd::string& GetName() const;
AZ::EntityId GetEditorEntityId() const { return GetEntity() ? GetEntityId() : AZ::EntityId(); } AZ::EntityId GetEditorEntityId() const { return GetEntity() ? GetEntityId() : AZ::EntityId(); }
AZ::NamedEntityId GetNamedEditorEntityId() const { return GetEntity() ? GetNamedEntityId() : AZ::NamedEntityId(); } AZ::NamedEntityId GetNamedEditorEntityId() const { return GetEntity() ? GetNamedEntityId() : AZ::NamedEntityId(); }
//===================================================================== //=====================================================================
// EditorScriptCanvasComponentRequestBus // EditorScriptCanvasComponentRequestBus
void SetAssetId(const AZ::Data::AssetId& assetId) override; void SetAssetId(const AZ::Data::AssetId& assetId) override;
@ -119,12 +117,8 @@ namespace ScriptCanvasEditor
(void)incompatible; (void)incompatible;
} }
//=====================================================================
// AssetCatalogEventBus
void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override; void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override;
void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override; void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override;
//=====================================================================
void OnScriptCanvasAssetChanged(AZ::Data::AssetId assetId); void OnScriptCanvasAssetChanged(AZ::Data::AssetId assetId);
void UpdateName(); void UpdateName();
@ -133,21 +127,15 @@ namespace ScriptCanvasEditor
void OnScriptCanvasAssetReady(const ScriptCanvasMemoryAsset::pointer asset); void OnScriptCanvasAssetReady(const ScriptCanvasMemoryAsset::pointer asset);
//===================================================================== //=====================================================================
void AddVariable(AZStd::string_view varName, const ScriptCanvas::GraphVariable& varDatum); void BuildGameEntityData();
void AddNewVariables(const ScriptCanvas::VariableData& graphVarData);
void RemoveVariable(const ScriptCanvas::VariableId& varId);
void RemoveOldVariables(const ScriptCanvas::VariableData& graphVarData);
bool UpdateVariable(const ScriptCanvas::GraphVariable& graphDatum, ScriptCanvas::GraphVariable& updateDatum, ScriptCanvas::GraphVariable& originalDatum);
void LoadVariables(const ScriptCanvasMemoryAsset::pointer memoryAsset);
void ClearVariables(); void ClearVariables();
private: private:
AZ::Data::AssetId m_removedCatalogId; AZ::Data::AssetId m_removedCatalogId;
AZ::Data::AssetId m_previousAssetId; AZ::Data::AssetId m_previousAssetId;
AZStd::string m_name; AZStd::string m_name;
ScriptCanvasAssetHolder m_scriptCanvasAssetHolder; ScriptCanvasAssetHolder m_scriptCanvasAssetHolder;
bool m_runtimeDataIsValid = false;
ScriptCanvas::EditableVariableData m_editableData; ScriptCanvasBuilder::BuildVariableOverrides m_variableOverrides;
}; };
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -289,7 +289,7 @@ namespace ScriptCanvasEditor
void LoggingDataAggregator::OnRegistrationDisabled(const AZ::NamedEntityId&, const ScriptCanvas::GraphIdentifier&) void LoggingDataAggregator::OnRegistrationDisabled(const AZ::NamedEntityId&, const ScriptCanvas::GraphIdentifier&)
{ {
} }
void LoggingDataAggregator::ResetLog() void LoggingDataAggregator::ResetLog()
@ -324,7 +324,7 @@ namespace ScriptCanvasEditor
m_hasAnchor = false; m_hasAnchor = false;
m_anchorTimeStamp = ScriptCanvas::Timestamp(0); m_anchorTimeStamp = ScriptCanvas::Timestamp(0);
} }
void LoggingDataAggregator::RegisterScriptCanvas(const AZ::NamedEntityId& entityId, const ScriptCanvas::GraphIdentifier& graphIdentifier) void LoggingDataAggregator::RegisterScriptCanvas(const AZ::NamedEntityId& entityId, const ScriptCanvas::GraphIdentifier& graphIdentifier)
{ {
bool foundMatch = false; bool foundMatch = false;
@ -335,7 +335,7 @@ namespace ScriptCanvasEditor
if (mapIter->second == graphIdentifier) if (mapIter->second == graphIdentifier)
{ {
foundMatch = true; foundMatch = true;
AZ_Error("ScriptCanvas", false, "Received a duplicated registration callback."); AZ_Warning("ScriptCanvas", false, "Received a duplicated registration callback.");
} }
} }

@ -523,7 +523,7 @@ namespace ScriptCanvasEditor
// Creation Actions // Creation Actions
{ {
m_createScriptCanvas = new QToolButton(); m_createScriptCanvas = new QToolButton();
m_createScriptCanvas->setIcon(QIcon(ScriptCanvas::AssetDescription::GetIconPath<ScriptCanvasAsset>())); m_createScriptCanvas->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/create_graph.png"));
m_createScriptCanvas->setToolTip("Creates a new Script Canvas Graph"); m_createScriptCanvas->setToolTip("Creates a new Script Canvas Graph");
QObject::connect(m_createScriptCanvas, &QToolButton::clicked, this, &MainWindow::OnFileNew); QObject::connect(m_createScriptCanvas, &QToolButton::clicked, this, &MainWindow::OnFileNew);

@ -12,6 +12,7 @@
<file>Resources/capture_offline.png</file> <file>Resources/capture_offline.png</file>
<file>Resources/create_function_input.png</file> <file>Resources/create_function_input.png</file>
<file>Resources/create_function_output.png</file> <file>Resources/create_function_output.png</file>
<file>Resources/create_graph.png</file>
<file>Resources/CollapseAll_Icon.png</file> <file>Resources/CollapseAll_Icon.png</file>
<file>Resources/edit_icon.png</file> <file>Resources/edit_icon.png</file>
<file>Resources/error_icon.png</file> <file>Resources/error_icon.png</file>

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -15,17 +15,28 @@ namespace ScriptCanvasRuntimeAssetCpp
{ {
AddDependencies = 3, AddDependencies = 3,
ChangeScriptRequirementToAsset, ChangeScriptRequirementToAsset,
// add your entry above
// add description above
Current Current
}; };
enum class RuntimeDataOverridesVersion : unsigned int
{
Initial = 0,
AddRuntimeAsset,
// add description above
Current,
};
enum class FunctionRuntimeDataVersion enum class FunctionRuntimeDataVersion
{ {
MergeBackEnd2dotZero, MergeBackEnd2dotZero,
AddSubgraphInterface, AddSubgraphInterface,
RemoveLegacyData, RemoveLegacyData,
RemoveConnectionToRuntimeData, RemoveConnectionToRuntimeData,
// add your entry above
// add description above
Current Current
}; };
} }
@ -87,9 +98,9 @@ namespace ScriptCanvas
{ {
return data.m_input.GetConstructorParameterCount() != 0 return data.m_input.GetConstructorParameterCount() != 0
|| AZStd::any_of(data.m_requiredAssets.begin(), data.m_requiredAssets.end(), [](const AZ::Data::Asset<RuntimeAsset>& asset) || AZStd::any_of(data.m_requiredAssets.begin(), data.m_requiredAssets.end(), [](const AZ::Data::Asset<RuntimeAsset>& asset)
{ {
return RequiresDependencyConstructionParametersRecurse(asset.Get()->m_runtimeData); return RequiresDependencyConstructionParametersRecurse(asset.Get()->m_runtimeData);
}); });
} }
bool RuntimeData::RequiresStaticInitialization() const bool RuntimeData::RequiresStaticInitialization() const
@ -97,6 +108,80 @@ namespace ScriptCanvas
return !m_cloneSources.empty(); return !m_cloneSources.empty();
} }
bool RuntimeDataOverrides::IsPreloadBehaviorEnforced(const RuntimeDataOverrides& overrides)
{
if (overrides.m_runtimeAsset.GetAutoLoadBehavior() != AZ::Data::AssetLoadBehavior::PreLoad)
{
return false;
}
for (auto& dependency : overrides.m_dependencies)
{
if (!IsPreloadBehaviorEnforced(dependency))
{
return false;
}
}
return true;
}
void RuntimeDataOverrides::EnforcePreloadBehavior()
{
m_runtimeAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
for (auto& dependency : m_dependencies)
{
dependency.EnforcePreloadBehavior();
}
}
void RuntimeDataOverrides::Reflect(AZ::ReflectContext* context)
{
RuntimeVariable::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<RuntimeDataOverrides>()
->Version(static_cast<unsigned int>(ScriptCanvasRuntimeAssetCpp::RuntimeDataOverridesVersion::Current))
->Field("runtimeAsset", &RuntimeDataOverrides::m_runtimeAsset)
->Field("variables", &RuntimeDataOverrides::m_variables)
->Field("variableIndices", &RuntimeDataOverrides::m_variableIndices)
->Field("entityIds", &RuntimeDataOverrides::m_entityIds)
->Field("dependencies", &RuntimeDataOverrides::m_dependencies)
;
}
}
RuntimeVariable::RuntimeVariable(const AZStd::any& source)
: value(source)
{
}
RuntimeVariable::RuntimeVariable(AZStd::any&& source)
: value(AZStd::move(source))
{
}
void RuntimeVariable::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<RuntimeVariable>()
->Field("value", &RuntimeVariable::value)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<RuntimeVariable>("RuntimeVariable", "RuntimeVariable")
->DataElement(AZ::Edit::UIHandlers::Default, &RuntimeVariable::value, "value", "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, true)
;
}
}
}
//////////////////////// ////////////////////////
// SubgraphInterfaceData // SubgraphInterfaceData
@ -118,7 +203,7 @@ namespace ScriptCanvas
{ {
*this = AZStd::move(other); *this = AZStd::move(other);
} }
SubgraphInterfaceData& SubgraphInterfaceData::operator=(SubgraphInterfaceData&& other) SubgraphInterfaceData& SubgraphInterfaceData::operator=(SubgraphInterfaceData&& other)
{ {
if (this != &other) if (this != &other)

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -10,6 +10,7 @@
#include <AzCore/Script/ScriptAsset.h> #include <AzCore/Script/ScriptAsset.h>
#include <ScriptCanvas/Asset/AssetDescription.h> #include <ScriptCanvas/Asset/AssetDescription.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Core/SubgraphInterface.h> #include <ScriptCanvas/Core/SubgraphInterface.h>
#include <ScriptCanvas/Core/GraphData.h> #include <ScriptCanvas/Core/GraphData.h>
#include <ScriptCanvas/Grammar/DebugMap.h> #include <ScriptCanvas/Grammar/DebugMap.h>
@ -21,6 +22,7 @@
namespace ScriptCanvas namespace ScriptCanvas
{ {
class RuntimeAsset; class RuntimeAsset;
struct RuntimeVariable;
class RuntimeAssetDescription : public AssetDescription class RuntimeAssetDescription : public AssetDescription
{ {
@ -41,7 +43,7 @@ namespace ScriptCanvas
"Script Canvas Runtime", "Script Canvas Runtime",
"Script Canvas Runtime", "Script Canvas Runtime",
"Icons/ScriptCanvas/Viewport/ScriptCanvas.png", "Icons/ScriptCanvas/Viewport/ScriptCanvas.png",
AZ::Color(1.0f,0.0f,0.0f,1.0f), AZ::Color(1.0f, 0.0f, 0.0f, 1.0f),
false false
) )
{} {}
@ -82,6 +84,24 @@ namespace ScriptCanvas
bool static RequiresDependencyConstructionParametersRecurse(const RuntimeData& data); bool static RequiresDependencyConstructionParametersRecurse(const RuntimeData& data);
}; };
struct RuntimeDataOverrides
{
AZ_TYPE_INFO(RuntimeDataOverrides, "{CE3C0AE6-4EBA-43B2-B2D5-7AC24A194E63}");
AZ_CLASS_ALLOCATOR(RuntimeDataOverrides, AZ::SystemAllocator, 0);
static bool IsPreloadBehaviorEnforced(const RuntimeDataOverrides& overrides);
static void Reflect(AZ::ReflectContext* reflectContext);
AZ::Data::Asset<RuntimeAsset> m_runtimeAsset;
AZStd::vector<RuntimeVariable> m_variables;
AZStd::vector<bool> m_variableIndices;
AZStd::vector<AZ::EntityId> m_entityIds;
AZStd::vector<RuntimeDataOverrides> m_dependencies;
void EnforcePreloadBehavior();
};
class RuntimeAssetBase class RuntimeAssetBase
: public AZ::Data::AssetData : public AZ::Data::AssetData
{ {
@ -94,7 +114,6 @@ namespace ScriptCanvas
{ {
} }
}; };
template <typename DataType> template <typename DataType>
class RuntimeAssetTyped class RuntimeAssetTyped
@ -165,7 +184,7 @@ namespace ScriptCanvas
"Script Canvas Function Interface", "Script Canvas Function Interface",
"Script Canvas Function Interface", "Script Canvas Function Interface",
"Icons/ScriptCanvas/Viewport/ScriptCanvas_Function.png", "Icons/ScriptCanvas/Viewport/ScriptCanvas_Function.png",
AZ::Color(1.0f,0.0f,0.0f,1.0f), AZ::Color(1.0f, 0.0f, 0.0f, 1.0f),
false false
) )
{} {}
@ -207,6 +226,6 @@ namespace ScriptCanvas
static const char* GetFileExtension() { return "scriptcanvas_fn_compiled"; } static const char* GetFileExtension() { return "scriptcanvas_fn_compiled"; }
static const char* GetFileFilter() { return "*.scriptcanvas_fn_compiled"; } static const char* GetFileFilter() { return "*.scriptcanvas_fn_compiled"; }
friend class SubgraphInterfaceAssetHandler; friend class SubgraphInterfaceAssetHandler;
}; };
} }

@ -1,12 +1,12 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#include <AzCore/Component/ComponentApplicationBus.h> #include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/RTTI/AttributeReader.h> #include <AzCore/RTTI/AttributeReader.h>
#include <AzCore/RTTI/ReflectContext.h> #include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
@ -17,6 +17,33 @@
namespace ScriptCanvas namespace ScriptCanvas
{ {
ScopedAuxiliaryEntityHandler::ScopedAuxiliaryEntityHandler(AZ::Entity* buildEntity)
: m_buildEntity(buildEntity)
, m_wasAdded(false)
{
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RemoveEntity(buildEntity);
}
if (buildEntity->GetState() == AZ::Entity::State::Constructed)
{
buildEntity->Init();
m_wasAdded = true;
}
}
ScopedAuxiliaryEntityHandler::~ScopedAuxiliaryEntityHandler()
{
if (!m_wasAdded)
{
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->AddEntity(m_buildEntity);
}
}
}
bool IsNamespacePathEqual(const NamespacePath& lhs, const NamespacePath& rhs) bool IsNamespacePathEqual(const NamespacePath& lhs, const NamespacePath& rhs)
{ {
if (lhs.size() != rhs.size()) if (lhs.size() != rhs.size())
@ -128,4 +155,3 @@ namespace ScriptCanvas
runtimeVersion = RuntimeVersion::Current; runtimeVersion = RuntimeVersion::Current;
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -15,6 +15,7 @@
#include <AzCore/RTTI/BehaviorContext.h> #include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/RTTI/ReflectContext.h> #include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/any.h>
#include <AzCore/std/hash.h> #include <AzCore/std/hash.h>
#include <AzCore/Component/EntityUtils.h> #include <AzCore/Component/EntityUtils.h>
#include <AzCore/Component/NamedEntityId.h> #include <AzCore/Component/NamedEntityId.h>
@ -26,7 +27,7 @@ namespace AZ
{ {
class Entity; class Entity;
class ReflectContext; class ReflectContext;
template<typename t_Attribute, typename t_Container> template<typename t_Attribute, typename t_Container>
bool ReadAttribute(t_Attribute& resultOut, AttributeId id, const t_Container& attributes) bool ReadAttribute(t_Attribute& resultOut, AttributeId id, const t_Container& attributes)
{ {
@ -41,7 +42,7 @@ namespace ScriptCanvas
// The actual value in each location initialized to GraphOwnerId is populated with the owning entity at editor-time, Asset Processor-time, or runtime, as soon as the owning entity is known. // The actual value in each location initialized to GraphOwnerId is populated with the owning entity at editor-time, Asset Processor-time, or runtime, as soon as the owning entity is known.
using GraphOwnerIdType = AZ::EntityId; using GraphOwnerIdType = AZ::EntityId;
static const GraphOwnerIdType GraphOwnerId = AZ::EntityId(0xacedc0de); static const GraphOwnerIdType GraphOwnerId = AZ::EntityId(0xacedc0de);
// A place holder identifier for unique runtime graph on Entity that is running more than one instance of the same graph. // A place holder identifier for unique runtime graph on Entity that is running more than one instance of the same graph.
// This allows multiple instances of the same graph to be addressed individually on the same entity. // This allows multiple instances of the same graph to be addressed individually on the same entity.
// The actual value in each location initialized to UniqueId is populated at run-time. // The actual value in each location initialized to UniqueId is populated at run-time.
@ -52,7 +53,7 @@ namespace ScriptCanvas
constexpr const char* k_OnVariableWriteEventName = "OnVariableValueChanged"; constexpr const char* k_OnVariableWriteEventName = "OnVariableValueChanged";
constexpr const char* k_OnVariableWriteEbusName = "VariableNotification"; constexpr const char* k_OnVariableWriteEbusName = "VariableNotification";
class Node; class Node;
class Edge; class Edge;
@ -195,7 +196,7 @@ namespace ScriptCanvas
using PropertyFields = AZStd::vector<AZStd::pair<AZStd::string_view, SlotId>>; using PropertyFields = AZStd::vector<AZStd::pair<AZStd::string_view, SlotId>>;
using NamedActiveEntityId = AZ::NamedEntityId; using NamedActiveEntityId = AZ::NamedEntityId;
using NamedNodeId = NamedId<AZ::EntityId>; using NamedNodeId = NamedId<AZ::EntityId>;
using NamedSlotId = NamedId<SlotId>; using NamedSlotId = NamedId<SlotId>;
@ -204,7 +205,26 @@ namespace ScriptCanvas
using EBusBusId = AZ::Crc32; using EBusBusId = AZ::Crc32;
using ScriptCanvasId = AZ::EntityId; using ScriptCanvasId = AZ::EntityId;
enum class AzEventIdentifier : size_t {}; enum class AzEventIdentifier : size_t {};
struct RuntimeVariable
{
AZ_TYPE_INFO(RuntimeVariable, "{6E969359-5AF5-4ECA-BE89-A96AB30A624E}");
AZ_CLASS_ALLOCATOR(RuntimeVariable, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* reflectContext);
AZStd::any value;
RuntimeVariable() = default;
RuntimeVariable(const RuntimeVariable&) = default;
RuntimeVariable(RuntimeVariable&&) = default;
explicit RuntimeVariable(const AZStd::any& source);
explicit RuntimeVariable(AZStd::any&& source);
RuntimeVariable& operator=(const RuntimeVariable&) = default;
RuntimeVariable& operator=(RuntimeVariable&&) = default;
};
struct NamespacePathHasher struct NamespacePathHasher
{ {
AZ_FORCE_INLINE size_t operator()(const NamespacePath& path) const AZ_FORCE_INLINE size_t operator()(const NamespacePath& path) const
@ -245,6 +265,17 @@ namespace ScriptCanvas
}; };
using ScriptCanvasSettingsRequestBus = AZ::EBus<ScriptCanvasSettingsRequests>; using ScriptCanvasSettingsRequestBus = AZ::EBus<ScriptCanvasSettingsRequests>;
class ScopedAuxiliaryEntityHandler
{
public:
ScopedAuxiliaryEntityHandler(AZ::Entity* buildEntity);
~ScopedAuxiliaryEntityHandler();
private:
bool m_wasAdded = false;
AZ::Entity* m_buildEntity = nullptr;
};
} }
namespace AZStd namespace AZStd

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -9,8 +9,8 @@
#include <AzCore/RTTI/BehaviorContext.h> #include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h> #include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/any.h>
#include <AzCore/std/string/string_view.h> #include <AzCore/std/string/string_view.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Data/Data.h> #include <ScriptCanvas/Data/Data.h>
#include <ScriptCanvas/Data/DataTrait.h> #include <ScriptCanvas/Data/DataTrait.h>
#include <ScriptCanvas/Data/BehaviorContextObject.h> #include <ScriptCanvas/Data/BehaviorContextObject.h>
@ -59,7 +59,7 @@ namespace ScriptCanvas
Datum(BehaviorContextResultTag, const AZ::BehaviorParameter& resultType); Datum(BehaviorContextResultTag, const AZ::BehaviorParameter& resultType);
Datum(const AZStd::string& behaviorClassName, eOriginality originality); Datum(const AZStd::string& behaviorClassName, eOriginality originality);
Datum(const AZ::BehaviorValueParameter& value); Datum(const AZ::BehaviorValueParameter& value);
void ReconfigureDatumTo(Datum&& object); void ReconfigureDatumTo(Datum&& object);
void ReconfigureDatumTo(const Datum& object); void ReconfigureDatumTo(const Datum& object);
@ -204,18 +204,18 @@ namespace ScriptCanvas
{ {
static_assert(!AZStd::is_pointer<t_Value>::value, "no pointer types in the Datum::GetAsHelper<t_Value, false>"); static_assert(!AZStd::is_pointer<t_Value>::value, "no pointer types in the Datum::GetAsHelper<t_Value, false>");
if (datum.m_storage.empty()) if (datum.m_storage.value.empty())
{ {
// rare, but can be caused by removals or problems with reflection to BehaviorContext, so must be checked // rare, but can be caused by removals or problems with reflection to BehaviorContext, so must be checked
return nullptr; return nullptr;
} }
else if (datum.m_type.GetType() == Data::eType::BehaviorContextObject) else if (datum.m_type.GetType() == Data::eType::BehaviorContextObject)
{ {
return (*AZStd::any_cast<BehaviorContextObjectPtr>(&datum.m_storage))->CastConst<t_Value>(); return (*AZStd::any_cast<BehaviorContextObjectPtr>(&datum.m_storage.value))->CastConst<t_Value>();
} }
else else
{ {
return AZStd::any_cast<const t_Value>(&datum.m_storage); return AZStd::any_cast<const t_Value>(&datum.m_storage.value);
} }
} }
}; };
@ -253,12 +253,12 @@ namespace ScriptCanvas
// eOriginality records the graph source of the object // eOriginality records the graph source of the object
eOriginality m_originality = eOriginality::Copy; eOriginality m_originality = eOriginality::Copy;
// storage for the datum, regardless of ScriptCanvas::Data::Type // storage for the datum, regardless of ScriptCanvas::Data::Type
AZStd::any m_storage; RuntimeVariable m_storage;
// This contains the editor label for m_storage. // This contains the editor label for m_storage.value.
AZStd::string m_datumLabel; AZStd::string m_datumLabel;
// This contains the editor visibility for m_storage. // This contains the editor visibility for m_storage.value.
AZ::Crc32 m_visibility{ AZ::Edit::PropertyVisibility::ShowChildrenOnly }; AZ::Crc32 m_visibility{ AZ::Edit::PropertyVisibility::ShowChildrenOnly };
// storage for implicit conversions, when needed // storage for implicit conversions, when needed
AZStd::any m_conversionStorage; AZStd::any m_conversionStorage;
@ -304,7 +304,7 @@ namespace ScriptCanvas
bool InitializeCRC(const void* source); bool InitializeCRC(const void* source);
bool InitializeEntityID(const void* source); bool InitializeEntityID(const void* source);
bool InitializeNamedEntityID(const void* source); bool InitializeNamedEntityID(const void* source);
bool InitializeMatrix3x3(const void* source); bool InitializeMatrix3x3(const void* source);
@ -384,7 +384,7 @@ namespace ScriptCanvas
bool Datum::Empty() const bool Datum::Empty() const
{ {
return m_storage.empty() || GetValueAddress() == nullptr; return m_storage.value.empty() || GetValueAddress() == nullptr;
} }
template<typename t_Value> template<typename t_Value>
@ -492,7 +492,7 @@ namespace ScriptCanvas
{ {
if (Data::IsValueType(m_type)) if (Data::IsValueType(m_type))
{ {
m_storage = value; m_storage.value = value;
return true; return true;
} }
else else

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -136,10 +136,7 @@ namespace ScriptCanvas
{ {
if (nodeEntity) if (nodeEntity)
{ {
if (nodeEntity->GetState() == AZ::Entity::State::Constructed) ScriptCanvas::ScopedAuxiliaryEntityHandler entityHandler(nodeEntity);
{
nodeEntity->Init();
}
if (auto* node = AZ::EntityUtils::FindFirstDerivedComponent<Node>(nodeEntity)) if (auto* node = AZ::EntityUtils::FindFirstDerivedComponent<Node>(nodeEntity))
{ {
@ -155,10 +152,7 @@ namespace ScriptCanvas
{ {
if (connectionEntity) if (connectionEntity)
{ {
if (connectionEntity->GetState() == AZ::Entity::State::Constructed) ScriptCanvas::ScopedAuxiliaryEntityHandler entityHandler(connectionEntity);
{
connectionEntity->Init();
}
} }
} }
@ -169,7 +163,7 @@ namespace ScriptCanvas
{ {
if (m_isFunctionGraph) if (m_isFunctionGraph)
{ {
return true; return true;
} }
return false; return false;
@ -418,7 +412,7 @@ namespace ScriptCanvas
void Graph::ValidateVariables(ValidationResults& validationResults) void Graph::ValidateVariables(ValidationResults& validationResults)
{ {
const VariableData* variableData = GetVariableData(); const VariableData* variableData = GetVariableData();
if (!variableData) if (!variableData)
{ {
return; return;
@ -440,7 +434,7 @@ namespace ScriptCanvas
{ {
errorDescription = AZStd::string::format("Variable %s has an invalid type %s.", GetVariableName(variableId).data(), variableType.GetAZType().ToString<AZStd::string>().c_str()); errorDescription = AZStd::string::format("Variable %s has an invalid type %s.", GetVariableName(variableId).data(), variableType.GetAZType().ToString<AZStd::string>().c_str());
} }
} }
else if (variableType == Data::Type::Invalid()) else if (variableType == Data::Type::Invalid())
{ {
errorDescription = AZStd::string::format("Variable %s has an invalid type.", GetVariableName(variableId).data()); errorDescription = AZStd::string::format("Variable %s has an invalid type.", GetVariableName(variableId).data());
@ -502,7 +496,7 @@ namespace ScriptCanvas
{ {
m_graphData.m_nodes.emplace(nodeEntity); m_graphData.m_nodes.emplace(nodeEntity);
m_nodeMapping[nodeId] = node; m_nodeMapping[nodeId] = node;
node->SetOwningScriptCanvasId(m_scriptCanvasId); node->SetOwningScriptCanvasId(m_scriptCanvasId);
node->Configure(); node->Configure();
GraphNotificationBus::Event(m_scriptCanvasId, &GraphNotifications::OnNodeAdded, nodeId); GraphNotificationBus::Event(m_scriptCanvasId, &GraphNotifications::OnNodeAdded, nodeId);
@ -523,17 +517,17 @@ namespace ScriptCanvas
if (node) if (node)
{ {
auto entry = m_graphData.m_nodes.find(node->GetEntity()); auto entry = m_graphData.m_nodes.find(node->GetEntity());
if (entry != m_graphData.m_nodes.end()) if (entry != m_graphData.m_nodes.end())
{ {
m_nodeMapping.erase(nodeId); m_nodeMapping.erase(nodeId);
m_graphData.m_nodes.erase(entry); m_graphData.m_nodes.erase(entry);
GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnNodeRemoved, nodeId); GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnNodeRemoved, nodeId);
RemoveDependentAsset(nodeId); RemoveDependentAsset(nodeId);
return true; return true;
}
} }
} }
}
return false; return false;
} }
@ -1036,17 +1030,17 @@ namespace ScriptCanvas
} }
} }
// for (auto connectionId : removableConnections) // for (auto connectionId : removableConnections)
// { // {
// DisconnectById(connectionId); // DisconnectById(connectionId);
// } // }
if (!removableConnections.empty()) if (!removableConnections.empty())
{ {
// RefreshConnectionValidity(warnOnRemoval); // RefreshConnectionValidity(warnOnRemoval);
} }
} }
void Graph::OnEntityActivated(const AZ::EntityId&) void Graph::OnEntityActivated(const AZ::EntityId&)
{ {
} }
@ -1075,7 +1069,7 @@ namespace ScriptCanvas
AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(scriptEventNode->GetAssetId(), AZ::Data::AssetLoadBehavior::Default); AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(scriptEventNode->GetAssetId(), AZ::Data::AssetLoadBehavior::Default);
} }
} }
m_batchAddingData = false; m_batchAddingData = false;
GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnBatchAddComplete); GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnBatchAddComplete);

@ -79,6 +79,7 @@ namespace ScriptCanvas
behaviorContext->Class<Nodeable>() behaviorContext->Class<Nodeable>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List) ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AZ::AttributeIsValid::IfPresent) ->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::Script::Attributes::UseClassIndexAllowNil, AZ::AttributeIsValid::IfPresent)
->Constructor<ExecutionStateWeakPtr>() ->Constructor<ExecutionStateWeakPtr>()
->Method("Deactivate", &Nodeable::Deactivate) ->Method("Deactivate", &Nodeable::Deactivate)
->Method("InitializeExecutionState", &Nodeable::InitializeExecutionState) ->Method("InitializeExecutionState", &Nodeable::InitializeExecutionState)

@ -756,10 +756,9 @@ namespace ScriptCanvas
{ {
auto runtimeComponent = (*graphIter); auto runtimeComponent = (*graphIter);
if (graphIdentifier.m_assetId.m_guid == runtimeComponent->GetAsset().GetId().m_guid) if (graphIdentifier.m_assetId.m_guid == runtimeComponent->GetRuntimeDataOverrides().m_runtimeAsset.GetId().m_guid)
{ {
// TODO: Gate on ComponentId // TODO: Gate on ComponentId
// \todo chcurran restore this functionality
// runtimeComponent->SetIsGraphObserved(observedState); // runtimeComponent->SetIsGraphObserved(observedState);
runtimeComponents.erase(graphIter); runtimeComponents.erase(graphIter);
break; break;

@ -1,12 +1,13 @@
/* /*
* 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. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#include <AzCore/Component/EntityUtils.h> #include <AzCore/Component/EntityUtils.h>
#include <AzCore/Script/ScriptSystemBus.h> #include <AzCore/Script/ScriptSystemBus.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzFramework/Entity/EntityContextBus.h> #include <AzFramework/Entity/EntityContextBus.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h> #include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Core/Nodeable.h> #include <ScriptCanvas/Core/Nodeable.h>
@ -19,13 +20,13 @@
namespace ExecutionContextCpp namespace ExecutionContextCpp
{ {
void TypeCopy(AZ::BehaviorValueParameter& lhs, const AZ::BehaviorValueParameter& rhs) void CopyTypeInformationOnly(AZ::BehaviorValueParameter& lhs, const AZ::BehaviorValueParameter& rhs)
{ {
lhs.m_typeId = rhs.m_typeId; lhs.m_typeId = rhs.m_typeId;
lhs.m_azRtti = rhs.m_azRtti; lhs.m_azRtti = rhs.m_azRtti;
} }
void ValueCopy(AZ::BehaviorValueParameter& lhs, const AZ::BehaviorValueParameter& rhs) void CopyTypeAndValueSource(AZ::BehaviorValueParameter& lhs, const AZ::BehaviorValueParameter& rhs)
{ {
lhs.m_typeId = rhs.m_typeId; lhs.m_typeId = rhs.m_typeId;
lhs.m_azRtti = rhs.m_azRtti; lhs.m_azRtti = rhs.m_azRtti;
@ -37,97 +38,72 @@ namespace ScriptCanvas
{ {
namespace Execution namespace Execution
{ {
ActivationData::ActivationData(const RuntimeComponent& component, ActivationInputArray& storage) ActivationData::ActivationData(const RuntimeDataOverrides& variableOverrides, ActivationInputArray& storage)
: entityId(component.GetEntityId()) : variableOverrides(variableOverrides)
, variableOverrides(component.GetVariableOverrides()) , runtimeData(variableOverrides.m_runtimeAsset->GetData())
, runtimeData(component.GetAsset()->GetData())
, storage(storage) , storage(storage)
{} {}
ActivationData::ActivationData(const AZ::EntityId entityId, const VariableData& variableOverrides, const RuntimeData& runtimeData, ActivationInputArray& storage) const void* ActivationData::GetVariableSource(size_t index, size_t& overrideIndexTracker) const
: entityId(entityId) {
, variableOverrides(variableOverrides) if (variableOverrides.m_variableIndices[index])
, runtimeData(runtimeData) {
, storage(storage) return AZStd::any_cast<void>(&variableOverrides.m_variables[overrideIndexTracker++].value);
{} }
else
{
return runtimeData.m_input.m_variables[index].second.GetAsDanger();
}
}
ActivationInputRange Context::CreateActivateInputRange(ActivationData& activationData) ActivationInputRange Context::CreateActivateInputRange(ActivationData& activationData, [[maybe_unused]] const AZ::EntityId& forSliceSupportOnly)
{ {
const RuntimeData& runtimeData = activationData.runtimeData; const RuntimeData& runtimeData = activationData.runtimeData;
ActivationInputRange rangeOut = runtimeData.m_activationInputRange; ActivationInputRange rangeOut = runtimeData.m_activationInputRange;
rangeOut.inputs = activationData.storage.begin(); rangeOut.inputs = activationData.storage.begin();
AZ_Assert(rangeOut.totalCount <= activationData.storage.size(), "Too many initial arguments for activation. " AZ_Assert(rangeOut.totalCount <= activationData.storage.size(), "Too many initial arguments for activation. "
"Consider increasing size, source of ActivationInputArray, or breaking up the source graph"); "Consider increasing size, source of ActivationInputArray, or breaking up the source graph");
// nodeables // nodeables - until the optimization is required, every instance gets their own copy
{ {
auto sourceVariableIter = runtimeData.m_activationInputRange.inputs; auto sourceVariableIter = runtimeData.m_activationInputRange.inputs;
const auto sourceVariableSentinel = runtimeData.m_activationInputRange.inputs + runtimeData.m_activationInputRange.nodeableCount; const auto sourceVariableSentinel = runtimeData.m_activationInputRange.inputs + runtimeData.m_activationInputRange.nodeableCount;
auto destVariableIter = rangeOut.inputs; auto destVariableIter = rangeOut.inputs;
for (; sourceVariableIter != sourceVariableSentinel; ++sourceVariableIter, ++destVariableIter) for (; sourceVariableIter != sourceVariableSentinel; ++sourceVariableIter, ++destVariableIter)
{ {
ExecutionContextCpp::ValueCopy(*destVariableIter, *sourceVariableIter); ExecutionContextCpp::CopyTypeAndValueSource(*destVariableIter, *sourceVariableIter);
} }
} }
// (possibly overridden) variables // (possibly overridden) variables, only the overrides are saved in on the component, otherwise they are taken from the runtime asset
{ {
auto sourceVariableIter = runtimeData.m_activationInputRange.inputs + runtimeData.m_activationInputRange.nodeableCount; auto sourceVariableIter = runtimeData.m_activationInputRange.inputs + runtimeData.m_activationInputRange.nodeableCount;
auto destVariableIter = rangeOut.inputs + runtimeData.m_activationInputRange.nodeableCount; auto destVariableIter = rangeOut.inputs + runtimeData.m_activationInputRange.nodeableCount;
for (auto& idDatumPair : runtimeData.m_input.m_variables) size_t overrideIndexTracker = 0;
const size_t sentinel = runtimeData.m_input.m_variables.size();
for (size_t index = 0; index != sentinel; ++index, ++destVariableIter, ++sourceVariableIter)
{ {
ExecutionContextCpp::TypeCopy(*destVariableIter, *sourceVariableIter); ExecutionContextCpp::CopyTypeInformationOnly(*destVariableIter, *sourceVariableIter);
destVariableIter->m_value = const_cast<void*>(activationData.GetVariableSource(index, overrideIndexTracker));
auto variableOverride = activationData.variableOverrides.FindVariable(idDatumPair.first);
const Datum* datum = variableOverride ? variableOverride->GetDatum() : &idDatumPair.second;
destVariableIter->m_value = const_cast<void*>(datum->GetAsDanger());
++destVariableIter;
++sourceVariableIter;
} }
} }
// (must always be re-mapped) EntityId // (always overridden) EntityIds
if (!runtimeData.m_input.m_entityIds.empty())
{ {
AZ::SliceComponent::EntityIdToEntityIdMap loadedEntityIdMap;
AzFramework::EntityContextId owningContextId = AzFramework::EntityContextId::CreateNull();
AzFramework::EntityIdContextQueryBus::EventResult(owningContextId, activationData.entityId, &AzFramework::EntityIdContextQueries::GetOwningContextId);
if (!owningContextId.IsNull())
{
AzFramework::SliceEntityOwnershipServiceRequestBus::EventResult(loadedEntityIdMap, owningContextId, &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::GetLoadedEntityIdMap);
}
AZ::BehaviorValueParameter* destVariableIter = rangeOut.inputs AZ::BehaviorValueParameter* destVariableIter = rangeOut.inputs
+ runtimeData.m_activationInputRange.nodeableCount + runtimeData.m_activationInputRange.nodeableCount
+ runtimeData.m_activationInputRange.variableCount; + runtimeData.m_activationInputRange.variableCount;
const auto entityIdTypeId = azrtti_typeid<Data::EntityIDType>(); const auto entityIdTypeId = azrtti_typeid<Data::EntityIDType>();
for (auto& idEntityPair : runtimeData.m_input.m_entityIds)
for (auto& entityId : activationData.variableOverrides.m_entityIds)
{ {
destVariableIter->m_typeId = entityIdTypeId; destVariableIter->m_typeId = entityIdTypeId;
destVariableIter->m_value = destVariableIter->m_tempData.allocate(sizeof(Data::EntityIDType), AZStd::alignment_of<Data::EntityIDType>::value, 0); destVariableIter->m_value = destVariableIter->m_tempData.allocate(sizeof(Data::EntityIDType), AZStd::alignment_of<Data::EntityIDType>::value, 0);
auto entityIdValuePtr = reinterpret_cast<AZStd::decay_t<Data::EntityIDType>*>(destVariableIter->m_value); auto entityIdValuePtr = reinterpret_cast<AZStd::decay_t<Data::EntityIDType>*>(destVariableIter->m_value);
*entityIdValuePtr = entityId;
if (auto variableOverride = activationData.variableOverrides.FindVariable(idEntityPair.first))
{
*entityIdValuePtr = *variableOverride->GetDatum()->GetAs<Data::EntityIDType>();
}
else
{
auto iter = loadedEntityIdMap.find(idEntityPair.second);
if (iter != loadedEntityIdMap.end())
{
*entityIdValuePtr = iter->second;
}
else
{
*entityIdValuePtr = Data::EntityIDType();
}
}
++destVariableIter; ++destVariableIter;
} }
} }
@ -156,7 +132,7 @@ namespace ScriptCanvas
for (auto& idDatumPair : runtimeData.m_input.m_variables) for (auto& idDatumPair : runtimeData.m_input.m_variables)
{ {
const Datum* datum = &idDatumPair.second; const Datum* datum = &idDatumPair.second;
AZ::BehaviorValueParameter bvp; AZ::BehaviorValueParameter bvp;
bvp.m_typeId = datum->GetType().GetAZType(); bvp.m_typeId = datum->GetType().GetAZType();
const auto classIter(behaviorContext.m_typeToClassMap.find(bvp.m_typeId)); const auto classIter(behaviorContext.m_typeToClassMap.find(bvp.m_typeId));
@ -214,6 +190,6 @@ namespace ScriptCanvas
Execution::InterpretedUnloadData(runtimeData); Execution::InterpretedUnloadData(runtimeData);
} }
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -12,9 +12,9 @@
namespace ScriptCanvas namespace ScriptCanvas
{ {
class RuntimeComponent; class RuntimeComponent;
class VariableData;
struct RuntimeData; struct RuntimeData;
struct RuntimeDataOverrides;
namespace Execution namespace Execution
{ {
@ -22,15 +22,15 @@ namespace ScriptCanvas
struct ActivationData struct ActivationData
{ {
ActivationData(const RuntimeComponent& component, ActivationInputArray& storage); const RuntimeDataOverrides& variableOverrides;
ActivationData(const AZ::EntityId entityId, const VariableData& variableOverrides, const RuntimeData& runtimeData, ActivationInputArray& storage);
const AZ::EntityId entityId;
const VariableData& variableOverrides;
const RuntimeData& runtimeData; const RuntimeData& runtimeData;
ActivationInputArray& storage; ActivationInputArray& storage;
ActivationData(const RuntimeDataOverrides& variableOverrides, ActivationInputArray& storage);
const void* GetVariableSource(size_t index, size_t& overrideIndexTracker) const;
}; };
struct ActivationInputRange struct ActivationInputRange
{ {
AZ::BehaviorValueParameter* inputs = nullptr; AZ::BehaviorValueParameter* inputs = nullptr;
@ -47,7 +47,7 @@ namespace ScriptCanvas
AZ_TYPE_INFO(Context, "{2C137581-19F4-42EB-8BF3-14DBFBC02D8D}"); AZ_TYPE_INFO(Context, "{2C137581-19F4-42EB-8BF3-14DBFBC02D8D}");
AZ_CLASS_ALLOCATOR(Context, AZ::SystemAllocator, 0); AZ_CLASS_ALLOCATOR(Context, AZ::SystemAllocator, 0);
static ActivationInputRange CreateActivateInputRange(ActivationData& activationData); static ActivationInputRange CreateActivateInputRange(ActivationData& activationData, const AZ::EntityId& forSliceSupportOnly);
static void InitializeActivationData(RuntimeData& runtimeData); static void InitializeActivationData(RuntimeData& runtimeData);
static void UnloadData(RuntimeData& runtimeData); static void UnloadData(RuntimeData& runtimeData);
@ -56,5 +56,5 @@ namespace ScriptCanvas
static void IntializeStaticCloners(RuntimeData& runtimeData, AZ::BehaviorContext& behaviorContext); static void IntializeStaticCloners(RuntimeData& runtimeData, AZ::BehaviorContext& behaviorContext);
}; };
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -27,34 +27,34 @@ namespace ScriptCanvas
ExecutionState::ExecutionState(const ExecutionStateConfig& config) ExecutionState::ExecutionState(const ExecutionStateConfig& config)
: m_component(&config.component) : m_component(&config.component)
{} {}
ExecutionStatePtr ExecutionState::Create(const ExecutionStateConfig& config) ExecutionStatePtr ExecutionState::Create(const ExecutionStateConfig& config)
{ {
Grammar::ExecutionStateSelection selection = config.runtimeData.m_input.m_executionSelection; Grammar::ExecutionStateSelection selection = config.runtimeData.m_input.m_executionSelection;
switch (selection) switch (selection)
{ {
case Grammar::InterpretedPure: case Grammar::ExecutionStateSelection::InterpretedPure:
return AZStd::make_shared<ExecutionStateInterpretedPure>(config); return AZStd::make_shared<ExecutionStateInterpretedPure>(config);
case Grammar::InterpretedPureOnGraphStart: case Grammar::ExecutionStateSelection::InterpretedPureOnGraphStart:
return AZStd::make_shared<ExecutionStateInterpretedPureOnGraphStart>(config); return AZStd::make_shared<ExecutionStateInterpretedPureOnGraphStart>(config);
case Grammar::InterpretedObject: case Grammar::ExecutionStateSelection::InterpretedObject:
return AZStd::make_shared<ExecutionStateInterpretedPerActivation>(config); return AZStd::make_shared<ExecutionStateInterpretedPerActivation>(config);
case Grammar::InterpretedObjectOnGraphStart: case Grammar::ExecutionStateSelection::InterpretedObjectOnGraphStart:
return AZStd::make_shared<ExecutionStateInterpretedPerActivationOnGraphStart>(config); return AZStd::make_shared<ExecutionStateInterpretedPerActivationOnGraphStart>(config);
default: default:
AZ_Assert(false, "Unsupported ScriptCanvas execution selection"); AZ_Assert(false, "Unsupported ScriptCanvas execution selection");
return nullptr; return nullptr;
} }
} }
AZ::Data::AssetId ExecutionState::GetAssetId() const AZ::Data::AssetId ExecutionState::GetAssetId() const
{ {
return m_component->GetAsset().GetId(); return m_component->GetRuntimeDataOverrides().m_runtimeAsset.GetId();
} }
AZ::EntityId ExecutionState::GetEntityId() const AZ::EntityId ExecutionState::GetEntityId() const
@ -82,9 +82,9 @@ namespace ScriptCanvas
return m_component->GetScriptCanvasId(); return m_component->GetScriptCanvasId();
} }
const VariableData& ExecutionState::GetVariableOverrides() const const RuntimeDataOverrides& ExecutionState::GetRuntimeDataOverrides() const
{ {
return m_component->GetVariableOverrides(); return m_component->GetRuntimeDataOverrides();
} }
void ExecutionState::Reflect(AZ::ReflectContext* reflectContext) void ExecutionState::Reflect(AZ::ReflectContext* reflectContext)
@ -92,10 +92,12 @@ namespace ScriptCanvas
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext)) if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext))
{ {
behaviorContext->Class<ExecutionState>() behaviorContext->Class<ExecutionState>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AZ::AttributeIsValid::IfPresent)
->Method("GetEntityId", &ExecutionState::GetEntityId) ->Method("GetEntityId", &ExecutionState::GetEntityId)
->Method("GetScriptCanvasId", &ExecutionState::GetScriptCanvasId) ->Method("GetScriptCanvasId", &ExecutionState::GetScriptCanvasId)
->Method("ToString", &ExecutionState::ToString) ->Method("ToString", &ExecutionState::ToString)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString) ->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
; ;
} }
@ -116,7 +118,7 @@ namespace ScriptCanvas
{ {
return shared_from_this(); return shared_from_this();
} }
AZStd::string ExecutionState::ToString() const AZStd::string ExecutionState::ToString() const
{ {
return AZStd::string::format("ExecutionState[%p]", this); return AZStd::string::format("ExecutionState[%p]", this);
@ -132,4 +134,4 @@ namespace ScriptCanvas
return ExecutionStateWeakConstPtr(this); return ExecutionStateWeakConstPtr(this);
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -37,7 +37,7 @@ namespace ScriptCanvas
ExecutionStateConfig(AZ::Data::Asset<RuntimeAsset> asset, RuntimeComponent& component); ExecutionStateConfig(AZ::Data::Asset<RuntimeAsset> asset, RuntimeComponent& component);
}; };
class ExecutionState class ExecutionState
: public AZStd::enable_shared_from_this<ExecutionState> : public AZStd::enable_shared_from_this<ExecutionState>
{ {
@ -50,7 +50,7 @@ namespace ScriptCanvas
static void Reflect(AZ::ReflectContext* reflectContext); static void Reflect(AZ::ReflectContext* reflectContext);
const RuntimeComponent* m_component = nullptr; const RuntimeComponent* m_component = nullptr;
ExecutionState(const ExecutionStateConfig& config); ExecutionState(const ExecutionStateConfig& config);
virtual ~ExecutionState() = default; virtual ~ExecutionState() = default;
@ -71,7 +71,7 @@ namespace ScriptCanvas
AZ::EntityId GetScriptCanvasId() const; AZ::EntityId GetScriptCanvasId() const;
const VariableData& GetVariableOverrides() const; const RuntimeDataOverrides& GetRuntimeDataOverrides() const;
virtual void Initialize() = 0; virtual void Initialize() = 0;
@ -88,4 +88,4 @@ namespace ScriptCanvas
ExecutionStateWeakConstPtr WeakFromThisConst() const; ExecutionStateWeakConstPtr WeakFromThisConst() const;
}; };
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -176,7 +176,7 @@ namespace ExecutionInterpretedAPICpp
// Lua: // Lua:
AZStd::pair<void*, AZ::BehaviorContext*> multipleResults = ScriptCanvas::BehaviorContextUtils::ConstructTupleGetContext(typeId); AZStd::pair<void*, AZ::BehaviorContext*> multipleResults = ScriptCanvas::BehaviorContextUtils::ConstructTupleGetContext(typeId);
AZ_Assert(multipleResults.first, "failure to construct a tuple by typeid from behavior context"); AZ_Assert(multipleResults.first, "failure to construct a tuple by typeid from behavior context");
AZ::BehaviorValueParameter parameter; AZ::BehaviorValueParameter parameter;
parameter.m_value = multipleResults.first; parameter.m_value = multipleResults.first;
parameter.m_typeId = typeId; parameter.m_typeId = typeId;
AZ::StackPush(lua, multipleResults.second, parameter); AZ::StackPush(lua, multipleResults.second, parameter);
@ -253,7 +253,7 @@ namespace ScriptCanvas
break; break;
} }
} }
void SetInterpretedExecutionModeDebug() void SetInterpretedExecutionModeDebug()
{ {
AZ::ScriptContext* scriptContext{}; AZ::ScriptContext* scriptContext{};
@ -314,7 +314,7 @@ namespace ScriptCanvas
{ {
using namespace ExecutionInterpretedAPICpp; using namespace ExecutionInterpretedAPICpp;
static_assert(sizeof(AZ::Uuid) == k_UuidSize, "size of uuid has changed"); static_assert(sizeof(AZ::Uuid) == k_UuidSize, "size of uuid has changed");
AZStd::string fastString; AZStd::string fastString;
fastString.resize(k_StringFastSize); fastString.resize(k_StringFastSize);
char* fastDigit = fastString.begin(); char* fastDigit = fastString.begin();
@ -338,7 +338,7 @@ namespace ScriptCanvas
AZ_Assert(string, "string argument must not be null"); AZ_Assert(string, "string argument must not be null");
AZ_Assert(strlen(string) == k_StringFastSize, "invalid length of string, fast format must be: 0123456789ABCDEF0123456789ABCDEF"); AZ_Assert(strlen(string) == k_StringFastSize, "invalid length of string, fast format must be: 0123456789ABCDEF0123456789ABCDEF");
const char* current = string; const char* current = string;
AZ::Uuid id; AZ::Uuid id;
auto data = id.begin(); auto data = id.begin();
auto sentinel = id.end(); auto sentinel = id.end();
@ -358,8 +358,7 @@ namespace ScriptCanvas
++current; ++current;
*data = (value0 << 4) | value1; *data = (value0 << 4) | value1;
} } while ((++data) != sentinel);
while ((++data) != sentinel);
return id; return id;
} }
@ -370,7 +369,6 @@ namespace ScriptCanvas
/** /**
Here is the function in Lua for easier reading Here is the function in Lua for easier reading
function OverrideNodeableMetatable(userdata, class_mt) function OverrideNodeableMetatable(userdata, class_mt)
local proxy = setmetatable({}, class_mt) -- class_mt from the user graph definition local proxy = setmetatable({}, class_mt) -- class_mt from the user graph definition
local instance_mt = { local instance_mt = {
@ -388,18 +386,16 @@ namespace ScriptCanvas
--]] --]]
return setmetatable(userdata instance_mt) -- can't be done from Lua return setmetatable(userdata instance_mt) -- can't be done from Lua
end end
--[[ --[[
userdata to Nodeable before: userdata to Nodeable before:
getmetatable(userdata).__index == Nodeable getmetatable(userdata).__index == Nodeable
userdata to Nodeable after: userdata to Nodeable after:
local override_mt = getmetatable(userdata) local override_mt = getmetatable(userdata)
local proxy = override_mt.__index local proxy = override_mt.__index
local SubGraph = getmetatable(proxy).__index local SubGraph = getmetatable(proxy).__index
getmetatable(SubGraph.__index) == Nodeable) getmetatable(SubGraph.__index) == Nodeable)
--]] --]]
*/ */
// \note: all other metamethods ignored for now // \note: all other metamethods ignored for now
@ -504,7 +500,7 @@ namespace ScriptCanvas
AZ_Assert(argsCount >= 2, "CallExecutionOut: Error in compiled Lua file, not enough arguments"); AZ_Assert(argsCount >= 2, "CallExecutionOut: Error in compiled Lua file, not enough arguments");
AZ_Assert(lua_isuserdata(lua, 1), "CallExecutionOut: Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); AZ_Assert(lua_isuserdata(lua, 1), "CallExecutionOut: Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
AZ_Assert(lua_isnumber(lua, 2), "CallExecutionOut: Error in compiled lua file, 2nd argument to SetExecutionOut is not a number"); AZ_Assert(lua_isnumber(lua, 2), "CallExecutionOut: Error in compiled lua file, 2nd argument to SetExecutionOut is not a number");
Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, 1); Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, 1);
size_t index = aznumeric_caster(lua_tointeger(lua, 2)); size_t index = aznumeric_caster(lua_tointeger(lua, 2));
nodeable->CallOut(index, nullptr, nullptr, argsCount - 2); nodeable->CallOut(index, nullptr, nullptr, argsCount - 2);
// Lua: results... // Lua: results...
@ -568,7 +564,7 @@ namespace ScriptCanvas
{ {
const int handlerIndex = lua_gettop(lua) - argCount; const int handlerIndex = lua_gettop(lua) - argCount;
lua_pushcfunction(lua, &ExecutionInterpretedAPICpp::ErrorHandler); lua_pushcfunction(lua, &ExecutionInterpretedAPICpp::ErrorHandler);
lua_insert(lua, handlerIndex); lua_insert(lua, handlerIndex);
int result = lua_pcall(lua, argCount, returnValueCount, handlerIndex); int result = lua_pcall(lua, argCount, returnValueCount, handlerIndex);
lua_remove(lua, handlerIndex); lua_remove(lua, handlerIndex);
return result; return result;
@ -581,7 +577,7 @@ namespace ScriptCanvas
AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)");
AZ_Assert(lua_isnumber(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a number"); AZ_Assert(lua_isnumber(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a number");
AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)"); AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)");
Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, -3); Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, -3);
AZ_Assert(nodeable, "Failed to read nodeable"); AZ_Assert(nodeable, "Failed to read nodeable");
size_t index = aznumeric_caster(lua_tointeger(lua, -2)); size_t index = aznumeric_caster(lua_tointeger(lua, -2));
@ -680,9 +676,9 @@ namespace ScriptCanvas
struct DependencyConstructionPack struct DependencyConstructionPack
{ {
ExecutionStateInterpreted* executionState; ExecutionStateInterpreted* executionState;
AZStd::vector<AZ::Data::Asset<RuntimeAsset>>* dependentAssets; AZStd::vector<RuntimeDataOverrides>* dependencies;
const size_t dependentAssetsIndex; const size_t dependenciesIndex;
RuntimeData& runtimeData; RuntimeDataOverrides& runtimeOverrides;
}; };
DependencyConstructionPack UnpackDependencyConstructionArgsSanitize(lua_State* lua) DependencyConstructionPack UnpackDependencyConstructionArgsSanitize(lua_State* lua)
@ -690,27 +686,26 @@ namespace ScriptCanvas
auto executionState = AZ::ScriptValue<ExecutionStateInterpreted*>::StackRead(lua, 1); auto executionState = AZ::ScriptValue<ExecutionStateInterpreted*>::StackRead(lua, 1);
AZ_Assert(executionState, "Error in compiled lua file, 1st argument to UnpackDependencyArgs is not an ExecutionStateInterpreted"); AZ_Assert(executionState, "Error in compiled lua file, 1st argument to UnpackDependencyArgs is not an ExecutionStateInterpreted");
AZ_Assert(lua_islightuserdata(lua, 2), "Error in compiled lua file, 2nd argument to UnpackDependencyArgs is not userdata (AZStd::vector<AZ::Data::Asset<RuntimeAsset>>*), but a :%s", lua_typename(lua, 2)); AZ_Assert(lua_islightuserdata(lua, 2), "Error in compiled lua file, 2nd argument to UnpackDependencyArgs is not userdata (AZStd::vector<AZ::Data::Asset<RuntimeAsset>>*), but a :%s", lua_typename(lua, 2));
auto dependentAssets = reinterpret_cast<AZStd::vector<AZ::Data::Asset<RuntimeAsset>>*>(lua_touserdata(lua, 2)); auto dependentOverrides = reinterpret_cast<AZStd::vector<RuntimeDataOverrides>*>(lua_touserdata(lua, 2));
AZ_Assert(lua_isinteger(lua, 3), "Error in compiled Lua file, 3rd argument to UnpackDependencyArgs is not a number"); AZ_Assert(lua_isinteger(lua, 3), "Error in compiled Lua file, 3rd argument to UnpackDependencyArgs is not a number");
const size_t dependentAssetsIndex = aznumeric_caster(lua_tointeger(lua, 3)); const size_t dependencyIndex = aznumeric_caster(lua_tointeger(lua, 3));
return DependencyConstructionPack{ executionState, dependentOverrides, dependencyIndex, (*dependentOverrides)[dependencyIndex] };
return DependencyConstructionPack{ executionState, dependentAssets, dependentAssetsIndex, (*dependentAssets)[dependentAssetsIndex].Get()->m_runtimeData };
} }
int Unpack(lua_State* lua, DependencyConstructionPack& args) int Unpack(lua_State* lua, DependencyConstructionPack& args)
{ {
ActivationInputArray storage; ActivationInputArray storage;
ActivationData data(args.executionState->GetEntityId(), args.executionState->GetVariableOverrides(), args.runtimeData, storage); ActivationData data(args.runtimeOverrides, storage);
ActivationInputRange range = Execution::Context::CreateActivateInputRange(data); ActivationInputRange range = Execution::Context::CreateActivateInputRange(data, args.executionState->GetEntityId());
PushActivationArgs(lua, range.inputs, range.totalCount); PushActivationArgs(lua, range.inputs, range.totalCount);
return range.totalCount; return range.totalCount;
} }
int UnpackDependencyConstructionArgs(lua_State* lua) int UnpackDependencyConstructionArgs(lua_State* lua)
{ {
// Lua: executionState, dependentAssets, dependentAssetsIndex // Lua: executionState, dependent overrides, index into dependent overrides
DependencyConstructionPack pack = UnpackDependencyConstructionArgsSanitize(lua); DependencyConstructionPack pack = UnpackDependencyConstructionArgsSanitize(lua);
lua_pushlightuserdata(lua, const_cast<void*>(reinterpret_cast<const void*>(&pack.runtimeData.m_requiredAssets))); lua_pushlightuserdata(lua, const_cast<void*>(reinterpret_cast<const void*>(&pack.runtimeOverrides.m_dependencies)));
return 1 + Unpack(lua, pack); return 1 + Unpack(lua, pack);
} }
@ -720,6 +715,5 @@ namespace ScriptCanvas
DependencyConstructionPack constructionArgs = UnpackDependencyConstructionArgsSanitize(lua); DependencyConstructionPack constructionArgs = UnpackDependencyConstructionArgsSanitize(lua);
return Unpack(lua, constructionArgs); return Unpack(lua, constructionArgs);
} }
} }
}
}

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -20,6 +20,7 @@ namespace ExecutionStateInterpretedCpp
AZ::Data::Asset<RuntimeAsset> GetSubgraphAssetForDebug(const AZ::Data::AssetId& id) AZ::Data::Asset<RuntimeAsset> GetSubgraphAssetForDebug(const AZ::Data::AssetId& id)
{ {
// #functions2 this may have to be made recursive
auto asset = AZ::Data::AssetManager::Instance().GetAsset<SubgraphInterfaceAsset>(id, AZ::Data::AssetLoadBehavior::PreLoad); auto asset = AZ::Data::AssetManager::Instance().GetAsset<SubgraphInterfaceAsset>(id, AZ::Data::AssetLoadBehavior::PreLoad);
asset.BlockUntilLoadComplete(); asset.BlockUntilLoadComplete();
return asset; return asset;
@ -32,7 +33,7 @@ namespace ScriptCanvas
: ExecutionState(config) : ExecutionState(config)
, m_interpretedAsset(config.runtimeData.m_script) , m_interpretedAsset(config.runtimeData.m_script)
{} {}
void ExecutionStateInterpreted::ClearLuaRegistryIndex() void ExecutionStateInterpreted::ClearLuaRegistryIndex()
{ {
m_luaRegistryIndex = LUA_NOREF; m_luaRegistryIndex = LUA_NOREF;
@ -40,8 +41,8 @@ namespace ScriptCanvas
const Grammar::DebugExecution* ExecutionStateInterpreted::GetDebugSymbolIn(size_t index) const const Grammar::DebugExecution* ExecutionStateInterpreted::GetDebugSymbolIn(size_t index) const
{ {
return index < m_component->GetAssetData().m_debugMap.m_ins.size() return index < m_component->GetRuntimeAssetData().m_debugMap.m_ins.size()
? &(m_component->GetAssetData().m_debugMap.m_ins[index]) ? &(m_component->GetRuntimeAssetData().m_debugMap.m_ins[index])
: nullptr; : nullptr;
} }
@ -55,8 +56,8 @@ namespace ScriptCanvas
const Grammar::DebugExecution* ExecutionStateInterpreted::GetDebugSymbolOut(size_t index) const const Grammar::DebugExecution* ExecutionStateInterpreted::GetDebugSymbolOut(size_t index) const
{ {
return index < m_component->GetAssetData().m_debugMap.m_outs.size() return index < m_component->GetRuntimeAssetData().m_debugMap.m_outs.size()
? &(m_component->GetAssetData().m_debugMap.m_outs[index]) ? &(m_component->GetRuntimeAssetData().m_debugMap.m_outs[index])
: nullptr; : nullptr;
} }
@ -70,8 +71,8 @@ namespace ScriptCanvas
const Grammar::DebugExecution* ExecutionStateInterpreted::GetDebugSymbolReturn(size_t index) const const Grammar::DebugExecution* ExecutionStateInterpreted::GetDebugSymbolReturn(size_t index) const
{ {
return index < m_component->GetAssetData().m_debugMap.m_returns.size() return index < m_component->GetRuntimeAssetData().m_debugMap.m_returns.size()
? &(m_component->GetAssetData().m_debugMap.m_returns[index]) ? &(m_component->GetRuntimeAssetData().m_debugMap.m_returns[index])
: nullptr; : nullptr;
} }
@ -85,8 +86,8 @@ namespace ScriptCanvas
const Grammar::DebugDataSource* ExecutionStateInterpreted::GetDebugSymbolVariableChange(size_t index) const const Grammar::DebugDataSource* ExecutionStateInterpreted::GetDebugSymbolVariableChange(size_t index) const
{ {
return index < m_component->GetAssetData().m_debugMap.m_variables.size() return index < m_component->GetRuntimeAssetData().m_debugMap.m_variables.size()
? &(m_component->GetAssetData().m_debugMap.m_variables[index]) ? &(m_component->GetRuntimeAssetData().m_debugMap.m_variables[index])
: nullptr; : nullptr;
} }
@ -131,6 +132,8 @@ namespace ScriptCanvas
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext)) if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext))
{ {
behaviorContext->Class<ExecutionStateInterpreted>() behaviorContext->Class<ExecutionStateInterpreted>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AZ::AttributeIsValid::IfPresent)
; ;
} }
} }
@ -148,5 +151,4 @@ namespace ScriptCanvas
luaL_unref(m_luaState, LUA_REGISTRYINDEX, m_luaRegistryIndex); luaL_unref(m_luaState, LUA_REGISTRYINDEX, m_luaRegistryIndex);
m_luaRegistryIndex = LUA_NOREF; m_luaRegistryIndex = LUA_NOREF;
} }
}
}

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -19,7 +19,7 @@ namespace ScriptCanvas
ExecutionStateInterpretedPerActivation::ExecutionStateInterpretedPerActivation(const ExecutionStateConfig& config) ExecutionStateInterpretedPerActivation::ExecutionStateInterpretedPerActivation(const ExecutionStateConfig& config)
: ExecutionStateInterpreted(config) : ExecutionStateInterpreted(config)
{} {}
ExecutionStateInterpretedPerActivation::~ExecutionStateInterpretedPerActivation() ExecutionStateInterpretedPerActivation::~ExecutionStateInterpretedPerActivation()
{ {
if (m_deactivationRequired) if (m_deactivationRequired)
@ -45,15 +45,15 @@ namespace ScriptCanvas
AZ::Internal::LuaClassToStack(lua, this, azrtti_typeid<ExecutionStateInterpretedPerActivation>(), AZ::ObjectToLua::ByReference, AZ::AcquisitionOnPush::None); AZ::Internal::LuaClassToStack(lua, this, azrtti_typeid<ExecutionStateInterpretedPerActivation>(), AZ::ObjectToLua::ByReference, AZ::AcquisitionOnPush::None);
// Lua: graph_VM, graph_VM['new'], userdata<ExecutionState> // Lua: graph_VM, graph_VM['new'], userdata<ExecutionState>
Execution::ActivationInputArray storage; Execution::ActivationInputArray storage;
Execution::ActivationData data(*m_component, storage); Execution::ActivationData data(m_component->GetRuntimeDataOverrides(), storage);
Execution::ActivationInputRange range = Execution::Context::CreateActivateInputRange(data); Execution::ActivationInputRange range = Execution::Context::CreateActivateInputRange(data, m_component->GetEntityId());
if (range.requiresDependencyConstructionParameters) if (range.requiresDependencyConstructionParameters)
{ {
lua_pushlightuserdata(lua, const_cast<void*>(reinterpret_cast<const void*>(&data.runtimeData.m_requiredAssets))); lua_pushlightuserdata(lua, const_cast<void*>(reinterpret_cast<const void*>(&data.variableOverrides.m_dependencies)));
// Lua: graph_VM, graph_VM['new'], userdata<ExecutionState>, dependencies // Lua: graph_VM, graph_VM['new'], userdata<ExecutionState>, runtimeDataOverrides
Execution::PushActivationArgs(lua, range.inputs, range.totalCount); Execution::PushActivationArgs(lua, range.inputs, range.totalCount);
// Lua: graph_VM, graph_VM['new'], userdata<ExecutionState>, dependencies, args... // Lua: graph_VM, graph_VM['new'], userdata<ExecutionState>, runtimeDataOverrides, args...
AZ::Internal::LuaSafeCall(lua, aznumeric_caster(2 + range.totalCount), 1); AZ::Internal::LuaSafeCall(lua, aznumeric_caster(2 + range.totalCount), 1);
} }
else else
@ -139,5 +139,4 @@ namespace ScriptCanvas
; ;
} }
} }
}
}

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -21,7 +21,7 @@ namespace ScriptCanvas
void ExecutionStateInterpretedPure::Execute() void ExecutionStateInterpretedPure::Execute()
{} {}
void ExecutionStateInterpretedPure::Initialize() void ExecutionStateInterpretedPure::Initialize()
{} {}
@ -52,8 +52,8 @@ namespace ScriptCanvas
AZ::Internal::LuaClassToStack(lua, this, azrtti_typeid<ExecutionStateInterpretedPureOnGraphStart>(), AZ::ObjectToLua::ByReference, AZ::AcquisitionOnPush::None); AZ::Internal::LuaClassToStack(lua, this, azrtti_typeid<ExecutionStateInterpretedPureOnGraphStart>(), AZ::ObjectToLua::ByReference, AZ::AcquisitionOnPush::None);
// Lua: graph_VM, graph_VM['k_OnGraphStartFunctionName'], userdata<ExecutionState> // Lua: graph_VM, graph_VM['k_OnGraphStartFunctionName'], userdata<ExecutionState>
Execution::ActivationInputArray storage; Execution::ActivationInputArray storage;
Execution::ActivationData data(*m_component, storage); Execution::ActivationData data(m_component->GetRuntimeDataOverrides(), storage);
Execution::ActivationInputRange range = Execution::Context::CreateActivateInputRange(data); Execution::ActivationInputRange range = Execution::Context::CreateActivateInputRange(data, m_component->GetEntityId());
Execution::PushActivationArgs(lua, range.inputs, range.totalCount); Execution::PushActivationArgs(lua, range.inputs, range.totalCount);
// Lua: graph_VM, graph_VM['k_OnGraphStartFunctionName'], userdata<ExecutionState>, args... // Lua: graph_VM, graph_VM['k_OnGraphStartFunctionName'], userdata<ExecutionState>, args...
const int result = Execution::InterpretedSafeCall(lua, aznumeric_caster(1 + range.totalCount), 0); const int result = Execution::InterpretedSafeCall(lua, aznumeric_caster(1 + range.totalCount), 0);
@ -78,4 +78,4 @@ namespace ScriptCanvas
; ;
} }
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -24,9 +24,12 @@
namespace RuntimeComponentCpp namespace RuntimeComponentCpp
{ {
enum Version enum class RuntimeComponentVersion : unsigned int
{ {
ForceAssetPreloads = 5, ForceAssetPreloads = 5,
AddRuntimeDataOverrides,
PrefabSupport,
RemoveRuntimeAsset,
// add description above // add description above
Current, Current,
@ -40,17 +43,11 @@ namespace ScriptCanvas
return GraphInfo(scriptCanvasId, graphIdentifier); return GraphInfo(scriptCanvasId, graphIdentifier);
} }
DatumValue CreateDatumValue(ScriptCanvasId /*scriptCanvasId*/, const GraphVariable& variable) DatumValue CreateDatumValue([[maybe_unused]] ScriptCanvasId scriptCanvasId, const GraphVariable& variable)
{ {
return DatumValue::Create(GraphVariable((*variable.GetDatum()), variable.GetVariableId())); return DatumValue::Create(GraphVariable((*variable.GetDatum()), variable.GetVariableId()));
} }
RuntimeComponent::RuntimeComponent(AZ::Data::Asset<RuntimeAsset> runtimeAsset)
: m_runtimeAsset(runtimeAsset)
{
m_runtimeAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
}
void RuntimeComponent::Activate() void RuntimeComponent::Activate()
{ {
InitializeExecution(); InitializeExecution();
@ -66,18 +63,13 @@ namespace ScriptCanvas
AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::ScriptCanvas, "RuntimeComponent::Execute (%s)", m_runtimeAsset.GetId().ToString<AZStd::string>().c_str()); AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::ScriptCanvas, "RuntimeComponent::Execute (%s)", m_runtimeAsset.GetId().ToString<AZStd::string>().c_str());
AZ_Assert(m_executionState, "RuntimeComponent::Execute called without an execution state"); AZ_Assert(m_executionState, "RuntimeComponent::Execute called without an execution state");
SC_EXECUTION_TRACE_GRAPH_ACTIVATED(CreateActivationInfo()); SC_EXECUTION_TRACE_GRAPH_ACTIVATED(CreateActivationInfo());
SCRIPT_CANVAS_PERFORMANCE_SCOPE_EXECUTION(m_executionState->GetScriptCanvasId(), m_runtimeAsset.GetId()); SCRIPT_CANVAS_PERFORMANCE_SCOPE_EXECUTION(m_executionState->GetScriptCanvasId(), m_runtimeOverrides.m_runtimeAsset.GetId());
m_executionState->Execute(); m_executionState->Execute();
} }
const AZ::Data::Asset<RuntimeAsset>& RuntimeComponent::GetAsset() const const RuntimeData& RuntimeComponent::GetRuntimeAssetData() const
{
return m_runtimeAsset;
}
const RuntimeData& RuntimeComponent::GetAssetData() const
{ {
return m_runtimeAsset->GetData(); return m_runtimeOverrides.m_runtimeAsset->GetData();
} }
ExecutionMode RuntimeComponent::GetExecutionMode() const ExecutionMode RuntimeComponent::GetExecutionMode() const
@ -87,7 +79,7 @@ namespace ScriptCanvas
GraphIdentifier RuntimeComponent::GetGraphIdentifier() const GraphIdentifier RuntimeComponent::GetGraphIdentifier() const
{ {
return GraphIdentifier(AZ::Data::AssetId(m_runtimeAsset.GetId().m_guid, 0), 0); return GraphIdentifier(AZ::Data::AssetId(m_runtimeOverrides.m_runtimeAsset.GetId().m_guid, 0), 0);
} }
AZ::EntityId RuntimeComponent::GetScriptCanvasId() const AZ::EntityId RuntimeComponent::GetScriptCanvasId() const
@ -95,37 +87,43 @@ namespace ScriptCanvas
return m_scriptCanvasId; return m_scriptCanvasId;
} }
const VariableData& RuntimeComponent::GetVariableOverrides() const const RuntimeDataOverrides& RuntimeComponent::GetRuntimeDataOverrides() const
{ {
return m_variableOverrides; return m_runtimeOverrides;
}
void RuntimeComponent::SetRuntimeDataOverrides(const RuntimeDataOverrides& overrideData)
{
m_runtimeOverrides = overrideData;
m_runtimeOverrides.EnforcePreloadBehavior();
} }
void RuntimeComponent::Init() void RuntimeComponent::Init()
{ {
m_scriptCanvasId = AZ::Entity::MakeId(); m_scriptCanvasId = AZ::Entity::MakeId();
AZ_Assert(m_runtimeAsset.GetAutoLoadBehavior() == AZ::Data::AssetLoadBehavior::PreLoad, "RuntimeComponent::m_runtimeAsset Auto load behavior MUST be set to AZ::Data::AssetLoadBehavior::PreLoad"); AZ_Assert(RuntimeDataOverrides::IsPreloadBehaviorEnforced(m_runtimeOverrides), "RuntimeComponent::m_runtimeAsset Auto load behavior MUST be set to AZ::Data::AssetLoadBehavior::PreLoad");
} }
void RuntimeComponent::InitializeExecution() void RuntimeComponent::InitializeExecution()
{ {
#if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK) #if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK)
if (!m_runtimeAsset.Get()) if (!m_runtimeOverrides.m_runtimeAsset.Get())
{ {
AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeAsset.GetId().ToString<AZStd::string>().data()); AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString<AZStd::string>().data());
return; return;
} }
#else #else
AZ_Assert(m_runtimeAsset.Get(), "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeAsset.GetId().ToString<AZStd::string>().data()); AZ_Assert(m_runtimeAsset.Get(), "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString<AZStd::string>().data());
#endif #endif
AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::ScriptCanvas, "RuntimeComponent::InitializeExecution (%s)", m_runtimeAsset.GetId().ToString<AZStd::string>().c_str()); AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::ScriptCanvas, "RuntimeComponent::InitializeExecution (%s)", m_runtimeAsset.GetId().ToString<AZStd::string>().c_str());
SCRIPT_CANVAS_PERFORMANCE_SCOPE_INITIALIZATION(m_scriptCanvasId, m_runtimeAsset.GetId()); SCRIPT_CANVAS_PERFORMANCE_SCOPE_INITIALIZATION(m_scriptCanvasId, m_runtimeOverrides.m_runtimeAsset.GetId());
m_executionState = ExecutionState::Create(ExecutionStateConfig(m_runtimeAsset, *this)); m_executionState = ExecutionState::Create(ExecutionStateConfig(m_runtimeOverrides.m_runtimeAsset, *this));
#if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK) #if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK)
if (!m_executionState) if (!m_executionState)
{ {
AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run", m_runtimeAsset.GetId().ToString<AZStd::string>().data()); AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString<AZStd::string>().data());
return; return;
} }
#else #else
@ -135,7 +133,7 @@ namespace ScriptCanvas
AZ::EntityBus::Handler::BusConnect(GetEntityId()); AZ::EntityBus::Handler::BusConnect(GetEntityId());
m_executionState->Initialize(); m_executionState->Initialize();
} }
void RuntimeComponent::OnEntityActivated(const AZ::EntityId&) void RuntimeComponent::OnEntityActivated(const AZ::EntityId&)
{ {
Execute(); Execute();
@ -151,24 +149,18 @@ namespace ScriptCanvas
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{ {
serializeContext->Class<RuntimeComponent, AZ::Component>() serializeContext->Class<RuntimeComponent, AZ::Component>()
->Version(RuntimeComponentCpp::Version::Current, &RuntimeComponent::VersionConverter) ->Version(static_cast<unsigned int>(RuntimeComponentCpp::RuntimeComponentVersion::Current), &RuntimeComponent::VersionConverter)
->Field("m_runtimeAsset", &RuntimeComponent::m_runtimeAsset) ->Field("runtimeOverrides", &RuntimeComponent::m_runtimeOverrides)
->Field("m_variableOverrides", &RuntimeComponent::m_variableOverrides)
; ;
} }
} }
void RuntimeComponent::SetVariableOverrides(const VariableData& overrideData)
{
m_variableOverrides = overrideData;
}
void RuntimeComponent::StopExecution() void RuntimeComponent::StopExecution()
{ {
if (m_executionState) if (m_executionState)
{ {
m_executionState->StopExecution(); m_executionState->StopExecution();
SCRIPT_CANVAS_PERFORMANCE_FINALIZE_TIMER(GetScriptCanvasId(), m_runtimeAsset.GetId()); SCRIPT_CANVAS_PERFORMANCE_FINALIZE_TIMER(GetScriptCanvasId(), m_runtimeOverrides.m_runtimeAsset.GetId());
SC_EXECUTION_TRACE_GRAPH_DEACTIVATED(CreateActivationInfo()); SC_EXECUTION_TRACE_GRAPH_DEACTIVATED(CreateActivationInfo());
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -17,9 +17,6 @@
#include <ScriptCanvas/Execution/ExecutionStateDeclarations.h> #include <ScriptCanvas/Execution/ExecutionStateDeclarations.h>
#include <ScriptCanvas/Grammar/PrimitivesDeclarations.h> #include <ScriptCanvas/Grammar/PrimitivesDeclarations.h>
#include "RuntimeComponent.h"
namespace ScriptCanvas namespace ScriptCanvas
{ {
using VariableIdMap = AZStd::unordered_map<VariableId, VariableId>; using VariableIdMap = AZStd::unordered_map<VariableId, VariableId>;
@ -45,11 +42,8 @@ namespace ScriptCanvas
RuntimeComponent() = default; RuntimeComponent() = default;
RuntimeComponent(AZ::Data::Asset<RuntimeAsset> runtimeAsset); // used to provide debug symbols, usually coming in the form of Node/Slot/Variable IDs
const RuntimeData& GetRuntimeAssetData() const;
const AZ::Data::Asset<RuntimeAsset>& GetAsset() const;
const RuntimeData& GetAssetData() const;
GraphIdentifier GetGraphIdentifier() const; GraphIdentifier GetGraphIdentifier() const;
@ -57,9 +51,9 @@ namespace ScriptCanvas
AZ::EntityId GetScriptCanvasId() const; AZ::EntityId GetScriptCanvasId() const;
const VariableData& GetVariableOverrides() const; const RuntimeDataOverrides& GetRuntimeDataOverrides() const;
void SetVariableOverrides(const VariableData& overrideData); void SetRuntimeDataOverrides(const RuntimeDataOverrides& overrideData);
protected: protected:
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
@ -94,15 +88,8 @@ namespace ScriptCanvas
void StopExecution(); void StopExecution();
private: private:
AZ::Data::Asset<RuntimeAsset> m_runtimeAsset;
ExecutionStatePtr m_executionState; ExecutionStatePtr m_executionState;
AZ::EntityId m_scriptCanvasId; AZ::EntityId m_scriptCanvasId;
RuntimeDataOverrides m_runtimeOverrides;
//! Per instance variable data overrides for the runtime asset
//! This is serialized when building this component from the EditorScriptCanvasComponent
// \todo remove the names from this data, and make it more lightweight
// it only needs variable id and value
// move the other information to the runtime system component
VariableData m_variableOverrides;
}; };
} }

@ -1,12 +1,13 @@
/* /*
* 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. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#include <AzCore/std/containers/unordered_map.h> #include <AzCore/std/containers/unordered_map.h>
#include <AzFramework/StringFunc/StringFunc.h> #include <AzFramework/StringFunc/StringFunc.h>
#include <Builder/ScriptCanvasBuilder.h>
#include <ScriptCanvas/Core/Datum.h> #include <ScriptCanvas/Core/Datum.h>
#include <ScriptCanvas/Core/EBusHandler.h> #include <ScriptCanvas/Core/EBusHandler.h>
#include <ScriptCanvas/Core/Graph.h> #include <ScriptCanvas/Core/Graph.h>
@ -41,11 +42,11 @@ namespace AbstractCodeModelCpp
using namespace ScriptCanvas::Grammar; using namespace ScriptCanvas::Grammar;
AZStd::unordered_set< const Nodes::Core::FunctionDefinitionNode*> Intersection AZStd::unordered_set< const Nodes::Core::FunctionDefinitionNode*> Intersection
( const AZStd::unordered_multimap<const Nodes::Core::FunctionDefinitionNode*, ExecutionTreePtr>& lhs (const AZStd::unordered_multimap<const Nodes::Core::FunctionDefinitionNode*, ExecutionTreePtr>& lhs
, const AZStd::unordered_set< const Nodes::Core::FunctionDefinitionNode*>& rhs) , const AZStd::unordered_set< const Nodes::Core::FunctionDefinitionNode*>& rhs)
{ {
AZStd::unordered_set< const Nodes::Core::FunctionDefinitionNode*> intersection; AZStd::unordered_set< const Nodes::Core::FunctionDefinitionNode*> intersection;
for (auto candidate : lhs) for (auto candidate : lhs)
{ {
if (rhs.contains(candidate.first)) if (rhs.contains(candidate.first))
@ -147,7 +148,7 @@ namespace ScriptCanvas
} }
} }
m_functions.clear(); m_functions.clear();
m_userInsThatRequireTopology.clear(); m_userInsThatRequireTopology.clear();
m_userOutsThatRequireTopology.clear(); m_userOutsThatRequireTopology.clear();
@ -239,7 +240,7 @@ namespace ScriptCanvas
// #functions2 slot<->variable consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering // #functions2 slot<->variable consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering
m_sourceVariableByDatum.insert(AZStd::make_pair(datum, &variablePair.second)); m_sourceVariableByDatum.insert(AZStd::make_pair(datum, &variablePair.second));
} }
} }
for (auto& sourceVariable : sortedVariables) for (auto& sourceVariable : sortedVariables)
@ -424,7 +425,7 @@ namespace ScriptCanvas
} }
void AbstractCodeModel::AddExecutionMapIn void AbstractCodeModel::AddExecutionMapIn
( UserInParseTopologyResult /*result*/ (UserInParseTopologyResult /*result*/
, ExecutionTreeConstPtr root , ExecutionTreeConstPtr root
, const AZStd::vector<ExecutionTreeConstPtr>& outCalls , const AZStd::vector<ExecutionTreeConstPtr>& outCalls
, AZStd::string_view defaultOutName , AZStd::string_view defaultOutName
@ -441,10 +442,10 @@ namespace ScriptCanvas
for (auto& input : functionInput) for (auto& input : functionInput)
{ {
in.inputs.push_back in.inputs.push_back
({ GetOriginalVariableName(input.second->m_source, nodelingIn) ({ GetOriginalVariableName(input.second->m_source, nodelingIn)
, input.second->m_source->m_name , input.second->m_source->m_name
, input.second->m_source->m_datum , input.second->m_source->m_datum
, input.second->m_source->m_sourceVariableId }); , input.second->m_source->m_sourceVariableId });
} }
if (!root->HasExplicitUserOutCalls()) if (!root->HasExplicitUserOutCalls())
@ -473,10 +474,10 @@ namespace ScriptCanvas
{ {
const auto& returnValueVariable = root->GetReturnValue(returnValueIndex).second->m_source; const auto& returnValueVariable = root->GetReturnValue(returnValueIndex).second->m_source;
out.outputs.push_back out.outputs.push_back
({ GetOriginalVariableName(returnValueVariable, *uniqueNodelingsOut.begin()) ({ GetOriginalVariableName(returnValueVariable, *uniqueNodelingsOut.begin())
, returnValueVariable->m_name , returnValueVariable->m_name
, returnValueVariable->m_datum.GetType() , returnValueVariable->m_datum.GetType()
, returnValueVariable->m_sourceVariableId }); , returnValueVariable->m_sourceVariableId });
} }
in.outs.push_back(AZStd::move(out)); in.outs.push_back(AZStd::move(out));
@ -505,15 +506,15 @@ namespace ScriptCanvas
SetDisplayAndParsedName(out, defaultOutName); SetDisplayAndParsedName(out, defaultOutName);
out.sourceID = defaultOutId; out.sourceID = defaultOutId;
} }
for (size_t inputIndex = 0; inputIndex < outCall->GetInputCount(); ++inputIndex) for (size_t inputIndex = 0; inputIndex < outCall->GetInputCount(); ++inputIndex)
{ {
const auto& returnValueVariable = outCall->GetInput(inputIndex).m_value; const auto& returnValueVariable = outCall->GetInput(inputIndex).m_value;
out.outputs.push_back out.outputs.push_back
({ GetOriginalVariableName(returnValueVariable, outCallID.m_node) ({ GetOriginalVariableName(returnValueVariable, outCallID.m_node)
, returnValueVariable->m_name , returnValueVariable->m_name
, returnValueVariable->m_datum.GetType() , returnValueVariable->m_datum.GetType()
, returnValueVariable->m_sourceVariableId }); , returnValueVariable->m_sourceVariableId });
} }
AZStd::const_pointer_cast<ExecutionTree>(outCall)->SetOutCallIndex(m_outIndexCount); AZStd::const_pointer_cast<ExecutionTree>(outCall)->SetOutCallIndex(m_outIndexCount);
@ -543,20 +544,20 @@ namespace ScriptCanvas
{ {
const auto& inputVariable = outCall->GetInput(inputIndex).m_value; const auto& inputVariable = outCall->GetInput(inputIndex).m_value;
out.outputs.push_back out.outputs.push_back
({ GetOriginalVariableName(inputVariable, &nodeling) ({ GetOriginalVariableName(inputVariable, &nodeling)
, inputVariable->m_name , inputVariable->m_name
, inputVariable->m_datum.GetType() , inputVariable->m_datum.GetType()
, inputVariable->m_sourceVariableId }); , inputVariable->m_sourceVariableId });
} }
for (size_t returnValueIndex = 0; returnValueIndex < outCall->GetReturnValueCount(); ++returnValueIndex) for (size_t returnValueIndex = 0; returnValueIndex < outCall->GetReturnValueCount(); ++returnValueIndex)
{ {
const auto& returnValueVariable = outCall->GetReturnValue(returnValueIndex).second->m_source; const auto& returnValueVariable = outCall->GetReturnValue(returnValueIndex).second->m_source;
out.outputs.push_back out.outputs.push_back
({ GetOriginalVariableName(returnValueVariable, &nodeling) ({ GetOriginalVariableName(returnValueVariable, &nodeling)
, returnValueVariable->m_name , returnValueVariable->m_name
, returnValueVariable->m_datum.GetType() , returnValueVariable->m_datum.GetType()
, returnValueVariable->m_sourceVariableId }); , returnValueVariable->m_sourceVariableId });
} }
AZStd::const_pointer_cast<ExecutionTree>(outCall)->SetOutCallIndex(m_outIndexCount); AZStd::const_pointer_cast<ExecutionTree>(outCall)->SetOutCallIndex(m_outIndexCount);
@ -697,7 +698,7 @@ namespace ScriptCanvas
} }
AZStd::string AbstractCodeModel::CheckUniqueInterfaceNames AZStd::string AbstractCodeModel::CheckUniqueInterfaceNames
( AZStd::string_view candidate (AZStd::string_view candidate
, AZStd::string_view defaultName , AZStd::string_view defaultName
, AZStd::unordered_set<AZStd::string>& uniqueNames , AZStd::unordered_set<AZStd::string>& uniqueNames
, const AZStd::unordered_set<const ScriptCanvas::Nodes::Core::FunctionDefinitionNode*>& nodelingsOut) , const AZStd::unordered_set<const ScriptCanvas::Nodes::Core::FunctionDefinitionNode*>& nodelingsOut)
@ -755,7 +756,7 @@ namespace ScriptCanvas
} }
AZStd::vector<Grammar::VariableConstPtr> AbstractCodeModel::CombineVariableLists AZStd::vector<Grammar::VariableConstPtr> AbstractCodeModel::CombineVariableLists
( const AZStd::vector<Nodeable*>& constructionNodeables (const AZStd::vector<Nodeable*>& constructionNodeables
, const AZStd::vector<AZStd::pair<VariableId, Datum>>& constructionInputVariables , const AZStd::vector<AZStd::pair<VariableId, Datum>>& constructionInputVariables
, const AZStd::vector<AZStd::pair<VariableId, Data::EntityIDType>>& entityIds) const , const AZStd::vector<AZStd::pair<VariableId, Data::EntityIDType>>& entityIds) const
{ {
@ -766,12 +767,12 @@ namespace ScriptCanvas
const void* nodeableAsVoidPtr = nodeable; const void* nodeableAsVoidPtr = nodeable;
auto iter = AZStd::find_if auto iter = AZStd::find_if
( m_nodeablesByNode.begin() (m_nodeablesByNode.begin()
, m_nodeablesByNode.end() , m_nodeablesByNode.end()
, [&](const auto& candidate) , [&](const auto& candidate)
{ {
return candidate.second->m_nodeable->m_datum.GetAsDanger() == nodeableAsVoidPtr; return candidate.second->m_nodeable->m_datum.GetAsDanger() == nodeableAsVoidPtr;
}); });
if (iter != m_nodeablesByNode.end()) if (iter != m_nodeablesByNode.end())
{ {
@ -784,7 +785,7 @@ namespace ScriptCanvas
for (const auto& variable : entityIds) for (const auto& variable : entityIds)
{ {
auto iter = AZStd::find_if( m_variables.begin(), m_variables.end(), [&](const auto& candidate) { auto iter = AZStd::find_if(m_variables.begin(), m_variables.end(), [&](const auto& candidate) {
if (candidate->m_datum.GetType() == Data::Type::EntityID()) if (candidate->m_datum.GetType() == Data::Type::EntityID())
{ {
bool isVariableIdMatch = candidate->m_sourceVariableId == variable.first; bool isVariableIdMatch = candidate->m_sourceVariableId == variable.first;
@ -836,7 +837,7 @@ namespace ScriptCanvas
{ {
ExecutionTreePtr child = AZStd::make_shared<ExecutionTree>(); ExecutionTreePtr child = AZStd::make_shared<ExecutionTree>();
child->SetParent(parent); child->SetParent(parent);
child->SetId({node, slot}); child->SetId({ node, slot });
child->SetScope(parent ? parent->ModScope() : m_graphScope); child->SetScope(parent ? parent->ModScope() : m_graphScope);
return child; return child;
} }
@ -944,7 +945,7 @@ namespace ScriptCanvas
AddError(node.GetEntityId(), nullptr, ParseErrors::EventNodeConnectCallMalformed); AddError(node.GetEntityId(), nullptr, ParseErrors::EventNodeConnectCallMalformed);
return false; return false;
} }
auto azEventNode = azrtti_cast<const ScriptCanvas::Nodes::Core::AzEventHandler*>(&node); auto azEventNode = azrtti_cast<const ScriptCanvas::Nodes::Core::AzEventHandler*>(&node);
if (!azEventNode) if (!azEventNode)
{ {
@ -1081,7 +1082,7 @@ namespace ScriptCanvas
{ {
// Node output is input data to a function definition // Node output is input data to a function definition
OutputAssignmentPtr output = CreateOutput(execution, outputSlot, {}, "input"); OutputAssignmentPtr output = CreateOutput(execution, outputSlot, {}, "input");
if (auto variable = FindReferencedVariableChecked(execution, outputSlot)) if (auto variable = FindReferencedVariableChecked(execution, outputSlot))
{ {
output->m_assignments.push_back(variable); output->m_assignments.push_back(variable);
@ -1222,11 +1223,11 @@ namespace ScriptCanvas
if (m_uniqueInNames.contains(displayName)) if (m_uniqueInNames.contains(displayName))
{ {
AddError AddError
( nodeling->GetEntityId() (nodeling->GetEntityId()
, nullptr , nullptr
, AZStd::string::format , AZStd::string::format
( "%s is the name of multiple In Nodelings in a subgraph,\n" ( "%s is the name of multiple In Nodelings in a subgraph,\n"
"this will result in a difficult or impossible to use Function Node when used in another graph", displayName.data())); "this will result in a difficult or impossible to use Function Node when used in another graph", displayName.c_str()));
return; return;
} }
else else
@ -1258,8 +1259,8 @@ namespace ScriptCanvas
AddError(nodeling->GetEntityId() AddError(nodeling->GetEntityId()
, nullptr , nullptr
, AZStd::string::format , AZStd::string::format
( "%s is the name of multiple In Nodelings in a subgraph,\n" ("%s is the name of multiple In Nodelings in a subgraph,\n"
"this will result in a difficult or impossible to use Function Node when used in another graph", displayName.data())); "this will result in a difficult or impossible to use Function Node when used in another graph", displayName.data()));
} }
else else
{ {
@ -1355,7 +1356,7 @@ namespace ScriptCanvas
{ {
AddError(nullptr, aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format AddError(nullptr, aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format
( "Execution cycle detected (see connections to %s-%s. Use a looping node like While or For" ( "Execution cycle detected (see connections to %s-%s. Use a looping node like While or For"
, node.GetDebugName().data(), outSlot.GetName().data()).data())); , node.GetDebugName().c_str(), outSlot.GetName().c_str()).c_str()));
return true; return true;
} }
@ -1368,12 +1369,12 @@ namespace ScriptCanvas
AbstractCodeModel::ReturnValueConnections AbstractCodeModel::FindAssignments(ExecutionTreeConstPtr execution, const Slot& output) AbstractCodeModel::ReturnValueConnections AbstractCodeModel::FindAssignments(ExecutionTreeConstPtr execution, const Slot& output)
{ {
ReturnValueConnections connections; ReturnValueConnections connections;
if (auto variable = FindReferencedVariableChecked(execution, output)) if (auto variable = FindReferencedVariableChecked(execution, output))
{ {
connections.m_returnValuesOrReferences.push_back(variable); connections.m_returnValuesOrReferences.push_back(variable);
} }
auto connectedNodes = execution->GetId().m_node->GetConnectedNodes(output); auto connectedNodes = execution->GetId().m_node->GetConnectedNodes(output);
bool isAtLeastOneReturnValueFound = false; bool isAtLeastOneReturnValueFound = false;
@ -1477,7 +1478,7 @@ namespace ScriptCanvas
return slot && candidate.second == slot; return slot && candidate.second == slot;
}); });
return iter != scriptCanvasNodesConnectedToInput.end() ? *iter : EndpointResolved{nullptr, nullptr}; return iter != scriptCanvasNodesConnectedToInput.end() ? *iter : EndpointResolved{ nullptr, nullptr };
}; };
for (size_t childIndex = 0; childIndex < outputSource->GetChildrenCount(); ++childIndex) for (size_t childIndex = 0; childIndex < outputSource->GetChildrenCount(); ++childIndex)
@ -1543,8 +1544,8 @@ namespace ScriptCanvas
for (const auto& otherConnections : scriptCanvasNodesConnectedToInput) for (const auto& otherConnections : scriptCanvasNodesConnectedToInput)
{ {
if (otherConnections.first == outputSCNode if (otherConnections.first == outputSCNode
&& otherConnections.second != outputSlot && otherConnections.second != outputSlot
&& InSimultaneousDataPath(*outputSCNode, *otherConnections.second, *outputSlot)) && InSimultaneousDataPath(*outputSCNode, *otherConnections.second, *outputSlot))
{ {
AddError(executionWithInput->GetId().m_node->GetEntityId(), executionWithInput, ParseErrors::MultipleSimulaneousInputValues); AddError(executionWithInput->GetId().m_node->GetEntityId(), executionWithInput, ParseErrors::MultipleSimulaneousInputValues);
} }
@ -1570,7 +1571,7 @@ namespace ScriptCanvas
VariableConstPtr AbstractCodeModel::FindVariable(const AZ::EntityId& sourceNodeId) const VariableConstPtr AbstractCodeModel::FindVariable(const AZ::EntityId& sourceNodeId) const
{ {
auto resultIter = AZStd::find_if auto resultIter = AZStd::find_if
( m_variables.begin() (m_variables.begin()
, m_variables.end() , m_variables.end()
, [&sourceNodeId](const VariableConstPtr& candidate) { return candidate->m_nodeableNodeId == sourceNodeId; }); , [&sourceNodeId](const VariableConstPtr& candidate) { return candidate->m_nodeableNodeId == sourceNodeId; });
@ -1580,7 +1581,7 @@ namespace ScriptCanvas
VariableConstPtr AbstractCodeModel::FindVariable(const VariableId& sourceVariableId) const VariableConstPtr AbstractCodeModel::FindVariable(const VariableId& sourceVariableId) const
{ {
auto resultIter = AZStd::find_if auto resultIter = AZStd::find_if
( m_variables.begin() (m_variables.begin()
, m_variables.end() , m_variables.end()
, [&sourceVariableId](const VariableConstPtr& candidate) { return candidate->m_sourceVariableId == sourceVariableId; }); , [&sourceVariableId](const VariableConstPtr& candidate) { return candidate->m_sourceVariableId == sourceVariableId; });
@ -1591,7 +1592,7 @@ namespace ScriptCanvas
{ {
if (IsUserNodeable(variable)) if (IsUserNodeable(variable))
{ {
auto iter = AZStd::find_if(m_nodeablesByNode.begin(), m_nodeablesByNode.end(), [&variable](auto& candidate){ return candidate.second->m_nodeable == variable; }); auto iter = AZStd::find_if(m_nodeablesByNode.begin(), m_nodeablesByNode.end(), [&variable](auto& candidate) { return candidate.second->m_nodeable == variable; });
if (iter != m_nodeablesByNode.end()) if (iter != m_nodeablesByNode.end())
{ {
return iter->second->m_simpleName; return iter->second->m_simpleName;
@ -1604,7 +1605,7 @@ namespace ScriptCanvas
const AZStd::pair<VariableConstPtr, AZStd::string>* AbstractCodeModel::FindStaticVariable(VariableConstPtr variable) const const AZStd::pair<VariableConstPtr, AZStd::string>* AbstractCodeModel::FindStaticVariable(VariableConstPtr variable) const
{ {
auto iter = AZStd::find_if auto iter = AZStd::find_if
( m_staticVariableNames.begin() (m_staticVariableNames.begin()
, m_staticVariableNames.end() , m_staticVariableNames.end()
, [&](const auto& candidate) { return candidate.first == variable; }); , [&](const auto& candidate) { return candidate.first == variable; });
@ -1622,7 +1623,7 @@ namespace ScriptCanvas
else else
{ {
const_cast<AbstractCodeModel*>(this)->AddError(execution, aznew ParseError(slot.GetNodeId(), AZStd::string::format const_cast<AbstractCodeModel*>(this)->AddError(execution, aznew ParseError(slot.GetNodeId(), AZStd::string::format
( "Failed to find member variable for Variable Reference in slot: %s Id: %s" ("Failed to find member variable for Variable Reference in slot: %s Id: %s"
, slot.GetName().data() , slot.GetName().data()
, slot.GetVariableReference().ToString().data()))); , slot.GetVariableReference().ToString().data())));
} }
@ -1965,7 +1966,7 @@ namespace ScriptCanvas
return {}; return {};
} }
AZStd::sys_time_t AbstractCodeModel::GetParseDuration() const AZStd::sys_time_t AbstractCodeModel::GetParseDuration() const
{ {
return m_parseDuration; return m_parseDuration;
@ -2091,7 +2092,7 @@ namespace ScriptCanvas
{ {
const AZStd::vector<const Slot*>& slots = outcome.GetValue(); const AZStd::vector<const Slot*>& slots = outcome.GetValue();
if (AZStd::find(slots.begin(), slots.end(), &reference) != slots.end() if (AZStd::find(slots.begin(), slots.end(), &reference) != slots.end()
&& AZStd::find(slots.begin(), slots.end(), &candidate) != slots.end()) && AZStd::find(slots.begin(), slots.end(), &candidate) != slots.end())
{ {
return true; return true;
} }
@ -2165,7 +2166,7 @@ namespace ScriptCanvas
if (m_start) if (m_start)
{ {
roots.push_back(m_start); roots.push_back(m_start);
} }
for (auto& nodeableParse : m_nodeablesByNode) for (auto& nodeableParse : m_nodeablesByNode)
@ -2237,7 +2238,7 @@ namespace ScriptCanvas
{ {
ExecutionTreePtr child = CreateChild(parent, node, outSlot); ExecutionTreePtr child = CreateChild(parent, node, outSlot);
child->SetScope(AZStd::make_shared<Scope>()); child->SetScope(AZStd::make_shared<Scope>());
child->ModScope()->m_parent = parent ? parent->ModScope(): m_graphScope; child->ModScope()->m_parent = parent ? parent->ModScope() : m_graphScope;
return child; return child;
} }
@ -2258,12 +2259,16 @@ namespace ScriptCanvas
m_variableScopeMeaning = VariableScopeMeaning_LegacyFunctions::ValueInitialization; m_variableScopeMeaning = VariableScopeMeaning_LegacyFunctions::ValueInitialization;
} }
#endif #endif
// The Order Matters: begin
// add all data to the ACM for easy look up in input/output processing for ACM nodes
AddAllVariablesPreParse(); AddAllVariablesPreParse();
if (!IsErrorFree()) if (!IsErrorFree())
{ {
return; return;
} }
// parse basic editor nodes as they may add implicit variables
for (auto& nodeEntity : m_source.m_graphData->m_nodes) for (auto& nodeEntity : m_source.m_graphData->m_nodes)
{ {
if (nodeEntity) if (nodeEntity)
@ -2296,18 +2301,27 @@ namespace ScriptCanvas
return; return;
} }
// parse the implicit variables added by ebus handling syntax sugar
ParseAutoConnectedEBusHandlerVariables(); ParseAutoConnectedEBusHandlerVariables();
// all possible data is available, now parse execution, starting with "main", currently keyed to RuntimeComponent::Activate
Parse(m_startNodes); Parse(m_startNodes);
// parse any function introduced by nodes other than On Graph Start/"main"
for (auto node : m_possibleExecutionRoots) for (auto node : m_possibleExecutionRoots)
{ {
ParseExecutionTreeRoots(*node); ParseExecutionTreeRoots(*node);
} }
// parse functions introduced by variable change events
ParseVariableHandling(); ParseVariableHandling();
// parse all user function and function object signatures
ParseUserFunctionTopology(); ParseUserFunctionTopology();
ParseConstructionInputVariables(); // culls unused variables, and determine whether the the graph defines an object or static functionality
ParseExecutionCharacteristics(); ParseExecutionCharacteristics();
// now that variables have been culled, determined what data needs to be initialized by an external source
ParseConstructionInputVariables();
// now that externally initialized data has been identified, associate local, static initializers with individual functions
ParseFunctionLocalStaticUseage();
// The Order Matters: end
// from here on, nothing more needs to happen during simple parsing // from here on, nothing more needs to happen during simple parsing
// for example, in the editor, to get validation on syntax based effects for the view // for example, in the editor, to get validation on syntax based effects for the view
@ -2315,7 +2329,10 @@ namespace ScriptCanvas
if (IsErrorFree()) if (IsErrorFree())
{ {
// the graph could have used several user graphs which required construction, and maybe multiple instances of the same user asset
// this will create indices for those nodes to be able to pass in the proper entry in the construction argument tree at translation and runtime
ParseDependenciesAssetIndicies(); ParseDependenciesAssetIndicies();
// protect all names against keyword collision and language naming violations
ConvertNamesToIdentifiers(); ConvertNamesToIdentifiers();
if (m_source.m_addDebugInfo) if (m_source.m_addDebugInfo)
@ -2334,7 +2351,7 @@ namespace ScriptCanvas
AddError(nullptr, ValidationConstPtr(aznew InactiveGraph())); AddError(nullptr, ValidationConstPtr(aznew InactiveGraph()));
} }
} }
else else
{ {
MarkParseStop(); MarkParseStop();
@ -2629,9 +2646,9 @@ namespace ScriptCanvas
// create a variable declaration // create a variable declaration
ExecutionTreePtr variableConstruction = CreateChild(inPreviouslyExecutedScopeResult.m_mostParent->ModParent(), nullptr, nullptr); ExecutionTreePtr variableConstruction = CreateChild(inPreviouslyExecutedScopeResult.m_mostParent->ModParent(), nullptr, nullptr);
variableConstruction->AddInput({ nullptr , newInputResultOfAssignment, DebugDataSource::FromInternal()}); variableConstruction->AddInput({ nullptr , newInputResultOfAssignment, DebugDataSource::FromInternal() });
variableConstruction->SetSymbol(Symbol::VariableDeclaration); variableConstruction->SetSymbol(Symbol::VariableDeclaration);
// splice the variable declaration right before the most parent for loop is executed // splice the variable declaration right before the most parent for loop is executed
auto positionOutcome = mostForLoopParent->RemoveChild(inPreviouslyExecutedScopeResult.m_mostParent); auto positionOutcome = mostForLoopParent->RemoveChild(inPreviouslyExecutedScopeResult.m_mostParent);
if (!positionOutcome.IsSuccess()) if (!positionOutcome.IsSuccess())
@ -2701,7 +2718,7 @@ namespace ScriptCanvas
case VariableConstructionRequirement::InputVariable: case VariableConstructionRequirement::InputVariable:
{ {
auto variableID = variable->m_sourceVariableId.IsValid() ? variable->m_sourceVariableId : VariableId::MakeVariableId(); auto variableID = variable->m_sourceVariableId.IsValid() ? variable->m_sourceVariableId : MakeParserGeneratedId(m_generatedIdCount++);
inputVariableIds.push_back(variableID); inputVariableIds.push_back(variableID);
inputVariablesById.insert({ variableID, variable }); inputVariablesById.insert({ variableID, variable });
// sort revealed a datum copy issue: type is not preserved, workaround below // sort revealed a datum copy issue: type is not preserved, workaround below
@ -2755,7 +2772,7 @@ namespace ScriptCanvas
{ {
auto& localStatics = ModStaticVariablesNames(staticVariable->m_source); auto& localStatics = ModStaticVariablesNames(staticVariable->m_source);
auto iter = AZStd::find_if auto iter = AZStd::find_if
( localStatics.begin() (localStatics.begin()
, localStatics.end() , localStatics.end()
, [&](const auto& candidate) { return candidate.first == staticVariable; }); , [&](const auto& candidate) { return candidate.first == staticVariable; });
@ -2834,16 +2851,16 @@ namespace ScriptCanvas
{ {
switch (execution->GetSymbol()) switch (execution->GetSymbol())
{ {
// nothing required // nothing required
case Symbol::PlaceHolderDuringParsing: case Symbol::PlaceHolderDuringParsing:
break; break;
// out and return value information // out and return value information
case Symbol::FunctionDefinition: case Symbol::FunctionDefinition:
AddDebugInformationFunctionDefinition(execution); AddDebugInformationFunctionDefinition(execution);
break; break;
// add in out everything // add in out everything
case Symbol::ForEach: case Symbol::ForEach:
case Symbol::FunctionCall: case Symbol::FunctionCall:
case Symbol::OperatorAddition: case Symbol::OperatorAddition:
@ -2857,7 +2874,7 @@ namespace ScriptCanvas
AddDebugInformationOut(execution); AddDebugInformationOut(execution);
break; break;
// add in but not out // add in but not out
case Symbol::Break: case Symbol::Break:
case Symbol::LogicalAND: case Symbol::LogicalAND:
case Symbol::LogicalNOT: case Symbol::LogicalNOT:
@ -2871,8 +2888,8 @@ namespace ScriptCanvas
AddDebugInformationIn(execution); AddDebugInformationIn(execution);
break; break;
// add in-debug-info if the if condition is NOT prefixed with logic or comparison expression (which will have the in-debug-info) // add in-debug-info if the if condition is NOT prefixed with logic or comparison expression (which will have the in-debug-info)
// add out-debug-info in all cases including including empty cases // add out-debug-info in all cases including including empty cases
case Symbol::IfCondition: case Symbol::IfCondition:
if (!(execution->GetId().m_node->IsIfBranchPrefacedWithBooleanExpression())) if (!(execution->GetId().m_node->IsIfBranchPrefacedWithBooleanExpression()))
{ {
@ -2900,7 +2917,7 @@ namespace ScriptCanvas
if (dependencies.userSubgraphs.find(m_source.m_namespacePath) != dependencies.userSubgraphs.end()) if (dependencies.userSubgraphs.find(m_source.m_namespacePath) != dependencies.userSubgraphs.end())
{ {
AZStd::string circularDependency = AZStd::string::format AZStd::string circularDependency = AZStd::string::format
( ParseErrors::CircularDependencyFormat (ParseErrors::CircularDependencyFormat
, m_source.m_name.data() , m_source.m_name.data()
, node.GetDebugName().data() , node.GetDebugName().data()
, m_source.m_name.data()); , m_source.m_name.data());
@ -2908,6 +2925,7 @@ namespace ScriptCanvas
AddError(nullptr, aznew Internal::ParseError(node.GetEntityId(), circularDependency)); AddError(nullptr, aznew Internal::ParseError(node.GetEntityId(), circularDependency));
} }
// #functions2 make this use an identifier for the node, for property window display and easier find/replace updates
// this part must NOT recurse, the dependency tree should remain a tree and not be flattened // this part must NOT recurse, the dependency tree should remain a tree and not be flattened
m_orderedDependencies.source.MergeWith(dependencies); m_orderedDependencies.source.MergeWith(dependencies);
} }
@ -2950,11 +2968,32 @@ namespace ScriptCanvas
{ {
if (!input->m_sourceVariableId.IsValid() && IsEntityIdThatRequiresRuntimeRemap(input)) if (!input->m_sourceVariableId.IsValid() && IsEntityIdThatRequiresRuntimeRemap(input))
{ {
input->m_sourceVariableId = VariableId::MakeVariableId(); input->m_sourceVariableId = MakeParserGeneratedId(m_generatedIdCount++);
input->m_source = nullptr; input->m_source = nullptr;
// promote to member variable for at this stage, optimizations on data flow will occur later // promote to member variable for at this stage, optimizations on data flow will occur later
input->m_isMember = true; input->m_isMember = true;
input->m_name = m_graphScope->AddVariableName(input->m_name);
AZStd::string entityVariableName;
if (slotAndVariable.m_slot)
{
if (execution->GetId().m_node)
{
entityVariableName.append(execution->GetId().m_node->GetNodeName());
entityVariableName.append(".");
entityVariableName.append(slotAndVariable.m_slot->GetName());
}
else
{
entityVariableName.append(slotAndVariable.m_slot->GetName());
}
}
else
{
entityVariableName = input->m_name;
}
input->m_name = m_graphScope->AddVariableName(entityVariableName);
AddVariable(input); AddVariable(input);
} }
} }
@ -3020,11 +3059,11 @@ namespace ScriptCanvas
CullUnusedVariables(); CullUnusedVariables();
if (allRootsArePure if (allRootsArePure
&& m_ebusHandlingByNode.empty() && m_ebusHandlingByNode.empty()
&& m_eventHandlingByNode.empty() && m_eventHandlingByNode.empty()
&& m_nodeablesByNode.empty() && m_nodeablesByNode.empty()
&& m_variableWriteHandlingByVariable.empty() && m_variableWriteHandlingByVariable.empty()
&& m_subgraphInterface.IsParsedPure()) && m_subgraphInterface.IsParsedPure())
{ {
if (m_start) if (m_start)
{ {
@ -3077,7 +3116,7 @@ namespace ScriptCanvas
void AbstractCodeModel::ParseExecutionLoop(ExecutionTreePtr executionLoop) void AbstractCodeModel::ParseExecutionLoop(ExecutionTreePtr executionLoop)
{ {
AddDebugInfiniteLoopDetectionInLoop(executionLoop); AddDebugInfiniteLoopDetectionInLoop(executionLoop);
auto loopSlot = executionLoop->GetId().m_node->GetSlot(executionLoop->GetId().m_node->GetLoopSlotId()); auto loopSlot = executionLoop->GetId().m_node->GetSlot(executionLoop->GetId().m_node->GetLoopSlotId());
AZ_Assert(loopSlot, "Node did not return a valid loop slot"); AZ_Assert(loopSlot, "Node did not return a valid loop slot");
ExecutionTreePtr executionLoopBody = OpenScope(executionLoop, executionLoop->GetId().m_node, loopSlot); ExecutionTreePtr executionLoopBody = OpenScope(executionLoop, executionLoop->GetId().m_node, loopSlot);
@ -3255,7 +3294,7 @@ namespace ScriptCanvas
} }
else if (numConnections == 1) else if (numConnections == 1)
{ {
ParseExecutionFunctionRecurse(execution, execution->ModChild(0), outSlot, executionOutNodes[0]); ParseExecutionFunctionRecurse(execution, execution->ModChild(0), outSlot, executionOutNodes[0]);
} }
else else
{ {
@ -3762,7 +3801,7 @@ namespace ScriptCanvas
trueValue->m_source = once; trueValue->m_source = once;
trueValue->m_datum = Datum(Data::BooleanType(true)); trueValue->m_datum = Datum(Data::BooleanType(true));
once->AddInput({ nullptr, trueValue, DebugDataSource::FromInternal() }); once->AddInput({ nullptr, trueValue, DebugDataSource::FromInternal() });
ExecutionTreePtr onReset = CreateChild(once, once->GetId().m_node, onceResetSlot); ExecutionTreePtr onReset = CreateChild(once, once->GetId().m_node, onceResetSlot);
onReset->SetSymbol(Symbol::PlaceHolderDuringParsing); onReset->SetSymbol(Symbol::PlaceHolderDuringParsing);
onReset->MarkInputOutputPreprocessed(); onReset->MarkInputOutputPreprocessed();
@ -3849,7 +3888,7 @@ namespace ScriptCanvas
executionSwitch->SetSymbol(Symbol::Switch); executionSwitch->SetSymbol(Symbol::Switch);
ParseExecutionSequentialChildren(executionSwitch); ParseExecutionSequentialChildren(executionSwitch);
} }
// the execution will already have its function definition defined, this will create the body of that function // the execution will already have its function definition defined, this will create the body of that function
void AbstractCodeModel::ParseExecutionTreeBody(ExecutionTreePtr execution, const Slot& outSlot) void AbstractCodeModel::ParseExecutionTreeBody(ExecutionTreePtr execution, const Slot& outSlot)
{ {
@ -4112,7 +4151,7 @@ namespace ScriptCanvas
{ {
auto& userFunctionNode = *userFunctionIter->first; auto& userFunctionNode = *userFunctionIter->first;
auto outSlots = userFunctionNode.GetSlotsByType(CombinedSlotType::ExecutionOut); auto outSlots = userFunctionNode.GetSlotsByType(CombinedSlotType::ExecutionOut);
if (outSlots.empty() || !outSlots.front()) if (outSlots.empty() || !outSlots.front())
{ {
AddError(userFunctionNode.GetEntityId(), nullptr, ScriptCanvas::ParseErrors::NoOutSlotInFunctionDefinitionStart); AddError(userFunctionNode.GetEntityId(), nullptr, ScriptCanvas::ParseErrors::NoOutSlotInFunctionDefinitionStart);
@ -4167,6 +4206,32 @@ namespace ScriptCanvas
ParseExecutionLoop(execution); ParseExecutionLoop(execution);
} }
void AbstractCodeModel::ParseFunctionLocalStaticUseage()
{
for (auto execution : ModAllExecutionRoots())
{
if (auto localVariables = GetLocalVariables(execution))
{
for (auto variable : *localVariables)
{
if (const AZStd::pair<VariableConstPtr, AZStd::string>* pair = FindStaticVariable(variable))
{
auto& localStatics = ModStaticVariablesNames(execution);
auto iter = AZStd::find_if
( localStatics.begin()
, localStatics.end()
, [&](const auto& candidate) { return candidate.first == variable; });
if (iter == localStatics.end())
{
localStatics.push_back(*pair);
}
}
}
}
}
}
void AbstractCodeModel::ParseImplicitVariables(const Node& node) void AbstractCodeModel::ParseImplicitVariables(const Node& node)
{ {
if (IsCycle(node)) if (IsCycle(node))
@ -4179,7 +4244,7 @@ namespace ScriptCanvas
auto onceControl = AddMemberVariable(Datum(Data::BooleanType(true)), "onceControl"); auto onceControl = AddMemberVariable(Datum(Data::BooleanType(true)), "onceControl");
m_controlVariablesBySourceNode.insert({ &node, onceControl }); m_controlVariablesBySourceNode.insert({ &node, onceControl });
} }
else else
{ {
const auto nodelingType = CheckNodelingType(node); const auto nodelingType = CheckNodelingType(node);
if (nodelingType != NodelingType::None) if (nodelingType != NodelingType::None)
@ -4208,7 +4273,7 @@ namespace ScriptCanvas
{ {
const VariableId assignedFromId = execution->GetId().m_node->GetVariableIdRead(execution->GetId().m_slot); const VariableId assignedFromId = execution->GetId().m_node->GetVariableIdRead(execution->GetId().m_slot);
auto variableRead = assignedFromId.IsValid() ? FindVariable(assignedFromId) : nullptr; auto variableRead = assignedFromId.IsValid() ? FindVariable(assignedFromId) : nullptr;
if (variableRead) if (variableRead)
{ {
// nullptr is acceptable here // nullptr is acceptable here
@ -4314,7 +4379,7 @@ namespace ScriptCanvas
for (auto sourceNodeAndSlot : nodes) for (auto sourceNodeAndSlot : nodes)
{ {
AddError(nullptr, aznew ScopedDataConnectionEvent AddError(nullptr, aznew ScopedDataConnectionEvent
( execution->GetNodeId() (execution->GetNodeId()
, targetNode , targetNode
, targetSlot , targetSlot
, *sourceNodeAndSlot.first , *sourceNodeAndSlot.first
@ -4324,7 +4389,7 @@ namespace ScriptCanvas
} }
} }
} }
bool AbstractCodeModel::ParseInputThisPointer(ExecutionTreePtr execution) bool AbstractCodeModel::ParseInputThisPointer(ExecutionTreePtr execution)
{ {
auto node = execution->GetId().m_node; auto node = execution->GetId().m_node;
@ -4364,7 +4429,7 @@ namespace ScriptCanvas
{ {
auto node2 = execution->GetId().m_node; auto node2 = execution->GetId().m_node;
AddError(execution, aznew ParseError(node2->GetEntityId(), AZStd::string::format AddError(execution, aznew ParseError(node2->GetEntityId(), AZStd::string::format
( "Failed to find member variable for Node: %s Id: %s" ("Failed to find member variable for Node: %s Id: %s"
, node2->GetNodeName().data() , node2->GetNodeName().data()
, node2->GetEntityId().ToString().data()).data())); , node2->GetEntityId().ToString().data()).data()));
} }
@ -4394,7 +4459,7 @@ namespace ScriptCanvas
{ {
auto node2 = execution->GetId().m_node; auto node2 = execution->GetId().m_node;
AddError(execution, aznew ParseError(node2->GetEntityId(), AZStd::string::format AddError(execution, aznew ParseError(node2->GetEntityId(), AZStd::string::format
( "Failed to find member variable for Node: %s Id: %s" ("Failed to find member variable for Node: %s Id: %s"
, node2->GetNodeName().data() , node2->GetNodeName().data()
, node2->GetEntityId().ToString().data()).data())); , node2->GetEntityId().ToString().data()).data()));
} }
@ -4451,10 +4516,10 @@ namespace ScriptCanvas
} }
ExecutionChild* executionChildInParent = &parent->ModChild(indexInParentCall); ExecutionChild* executionChildInParent = &parent->ModChild(indexInParentCall);
const size_t executionInputCount = execution->GetInputCount(); const size_t executionInputCount = execution->GetInputCount();
const size_t thisInputOffset = execution->InputHasThisPointer() ? 1 : 0; const size_t thisInputOffset = execution->InputHasThisPointer() ? 1 : 0;
// the original index has ALL the input from the slots on the node // the original index has ALL the input from the slots on the node
// create multiple calls with separate function call nodes, but ONLY take the inputs required // create multiple calls with separate function call nodes, but ONLY take the inputs required
// as indicated by the function call info // as indicated by the function call info
@ -4811,7 +4876,7 @@ namespace ScriptCanvas
} }
} }
} }
void AbstractCodeModel::ParseReturnValue(ExecutionTreePtr execution, const Slot& returnValueSlot) void AbstractCodeModel::ParseReturnValue(ExecutionTreePtr execution, const Slot& returnValueSlot)
{ {
if (auto variable = FindReferencedVariableChecked(execution, returnValueSlot)) if (auto variable = FindReferencedVariableChecked(execution, returnValueSlot))
@ -4862,9 +4927,9 @@ namespace ScriptCanvas
{ {
ParseUserIn(iter.second, iter.first); ParseUserIn(iter.second, iter.first);
} }
m_userInsThatRequireTopology.clear(); m_userInsThatRequireTopology.clear();
ParseUserOuts(); ParseUserOuts();
auto parseOutcome = m_subgraphInterface.Parse(); auto parseOutcome = m_subgraphInterface.Parse();
@ -4920,7 +4985,7 @@ namespace ScriptCanvas
AddError(root, aznew Internal::ParseError(AZ::EntityId(), "In Nodeling didn't parse properly, there were still leaves without nodelings in the execution tree.")); AddError(root, aznew Internal::ParseError(AZ::EntityId(), "In Nodeling didn't parse properly, there were still leaves without nodelings in the execution tree."));
return; return;
} }
} }
auto& outCallsChecked = listenerCheck.GetOutCalls(); auto& outCallsChecked = listenerCheck.GetOutCalls();
if (!result.addSingleOutToMap && outCallsChecked.empty()) if (!result.addSingleOutToMap && outCallsChecked.empty())
@ -4968,8 +5033,8 @@ namespace ScriptCanvas
} }
if ((!root->HasExplicitUserOutCalls()) if ((!root->HasExplicitUserOutCalls())
&& root->GetReturnValueCount() > 0 && root->GetReturnValueCount() > 0
&& branches > 1) && branches > 1)
{ {
AddError(root->GetNodeId(), root, ScriptCanvas::ParseErrors::TooManyBranchesForReturn); AddError(root->GetNodeId(), root, ScriptCanvas::ParseErrors::TooManyBranchesForReturn);
return; return;
@ -5005,7 +5070,7 @@ namespace ScriptCanvas
AZStd::pair<const Slot*, ReturnValueConstPtr> returnValue = execution->GetReturnValue(execution->GetReturnValueCount() - 1); AZStd::pair<const Slot*, ReturnValueConstPtr> returnValue = execution->GetReturnValue(execution->GetReturnValueCount() - 1);
AZStd::const_pointer_cast<ReturnValue>(returnValue.second)->m_isNewValue = true; AZStd::const_pointer_cast<ReturnValue>(returnValue.second)->m_isNewValue = true;
} }
} }
} }
} }
@ -5029,7 +5094,7 @@ namespace ScriptCanvas
result.addExplicitOutCalls = nodelingsOutCount > 1; result.addExplicitOutCalls = nodelingsOutCount > 1;
result.isSimpleFunction = !result.addExplicitOutCalls; result.isSimpleFunction = !result.addExplicitOutCalls;
} }
else else
{ {
// user explicitly defined at least 1 Out and there are execution leaves without Outs, so we provide an Out to any missing ones // user explicitly defined at least 1 Out and there are execution leaves without Outs, so we provide an Out to any missing ones
result.addSingleOutToMap = true; result.addSingleOutToMap = true;
@ -5037,7 +5102,7 @@ namespace ScriptCanvas
result.addExplicitOutCalls = true; result.addExplicitOutCalls = true;
result.isSimpleFunction = false; result.isSimpleFunction = false;
} }
return result; return result;
} }
@ -5058,41 +5123,41 @@ namespace ScriptCanvas
void AbstractCodeModel::ParseUserLatentData(ExecutionTreePtr execution) void AbstractCodeModel::ParseUserLatentData(ExecutionTreePtr execution)
{ {
if (execution->IsOnLatentPath()) if (execution->IsOnLatentPath())
{ {
if (execution->GetChildrenCount() == 0) if (execution->GetChildrenCount() == 0)
{ {
execution->AddChild({ nullptr, {}, nullptr }); execution->AddChild({ nullptr, {}, nullptr });
} }
auto& executionChild = execution->ModChild(0); auto& executionChild = execution->ModChild(0);
// inputs are return values expected from the latent out call // inputs are return values expected from the latent out call
for (auto& returnValue : FindUserLatentReturnValues(execution)) for (auto& returnValue : FindUserLatentReturnValues(execution))
{ {
// if there are return values, we can continue execution after // if there are return values, we can continue execution after
// the nodeling out that is in the path (disable the contract) // the nodeling out that is in the path (disable the contract)
// and we must make sure there's ONLY ONE // and we must make sure there's ONLY ONE
// and no immediate ins // and no immediate ins
auto outputAssignment = CreateOutputAssignment(returnValue); auto outputAssignment = CreateOutputAssignment(returnValue);
executionChild.m_output.push_back({ nullptr, outputAssignment }); executionChild.m_output.push_back({ nullptr, outputAssignment });
} }
auto methodRoot = execution->ModRoot(); auto methodRoot = execution->ModRoot();
// outputs are inputs to the latent out call // outputs are inputs to the latent out call
for (auto& inputValue : FindUserLatentOutput(execution)) for (auto& inputValue : FindUserLatentOutput(execution))
{ {
inputValue->m_source = methodRoot; inputValue->m_source = methodRoot;
execution->AddInput({ nullptr, inputValue, DebugDataSource::FromVariable(SlotId{}, inputValue->m_datum.GetType(), inputValue->m_sourceVariableId) }); execution->AddInput({ nullptr, inputValue, DebugDataSource::FromVariable(SlotId{}, inputValue->m_datum.GetType(), inputValue->m_sourceVariableId) });
} }
methodRoot->CopyInput(execution, ExecutionTree::RemapVariableSource::No); methodRoot->CopyInput(execution, ExecutionTree::RemapVariableSource::No);
} }
else else
{ {
AddError(execution, aznew Internal::ParseError(execution->GetNodeId(), "immediate execution parsed data in latent thread")); AddError(execution, aznew Internal::ParseError(execution->GetNodeId(), "immediate execution parsed data in latent thread"));
} }
} }
void AbstractCodeModel::ParseUserOutCall(ExecutionTreePtr execution) void AbstractCodeModel::ParseUserOutCall(ExecutionTreePtr execution)
@ -5164,7 +5229,7 @@ namespace ScriptCanvas
if (!IsConnectedToUserIn(nodeling)) if (!IsConnectedToUserIn(nodeling))
{ {
const auto report = AZStd::string::format const auto report = AZStd::string::format
( "Nodeling Out (%s) not connected to Nodeling In, functionality cannot be executed", nodeling->GetDisplayName().data()); ("Nodeling Out (%s) not connected to Nodeling In, functionality cannot be executed", nodeling->GetDisplayName().data());
AddError(nullptr, aznew Internal::ParseError(nodeling->GetEntityId(), report)); AddError(nullptr, aznew Internal::ParseError(nodeling->GetEntityId(), report));
} }
@ -5172,7 +5237,7 @@ namespace ScriptCanvas
else else
{ {
const auto report = AZStd::string::format const auto report = AZStd::string::format
("null nodeling in immediate out list"); ("null nodeling in immediate out list");
AddError(nullptr, aznew Internal::ParseError(nodeling->GetEntityId(), report)); AddError(nullptr, aznew Internal::ParseError(nodeling->GetEntityId(), report));
} }
@ -5210,27 +5275,8 @@ namespace ScriptCanvas
TraverseTree(execution, listener); TraverseTree(execution, listener);
const auto& usage = listener.GetUsedVariables(); const auto& usage = listener.GetUsedVariables();
const bool usesOnlyLocalVariables = usage.memberVariables.empty() && usage.implicitMemberVariables.empty(); const bool usesOnlyLocalVariables = usage.memberVariables.empty() && usage.implicitMemberVariables.empty();
m_variableUse.localVariables.insert(usage.localVariables.begin(), usage.localVariables.end()); m_variableUse.localVariables.insert(usage.localVariables.begin(), usage.localVariables.end());
m_variableUse.memberVariables.insert(usage.memberVariables.begin(), usage.memberVariables.end()); m_variableUse.memberVariables.insert(usage.memberVariables.begin(), usage.memberVariables.end());
for (auto variable : m_variableUse.localVariables)
{
if (const AZStd::pair<VariableConstPtr, AZStd::string>* pair = FindStaticVariable(variable))
{
auto& localStatics = ModStaticVariablesNames(execution);
auto iter = AZStd::find_if
(localStatics.begin()
, localStatics.end()
, [&](const auto& candidate) { return candidate.first == variable; });
if (iter == localStatics.end())
{
localStatics.push_back(*pair);
}
}
}
m_variableUseByExecution.emplace(execution, listener.MoveUsedVariables()); m_variableUseByExecution.emplace(execution, listener.MoveUsedVariables());
return (!usage.usesExternallyInitializedVariables) && usesOnlyLocalVariables && listener.IsPure(); return (!usage.usesExternallyInitializedVariables) && usesOnlyLocalVariables && listener.IsPure();
} }
@ -5285,7 +5331,7 @@ namespace ScriptCanvas
RemoveFromTree(noOpChild); RemoveFromTree(noOpChild);
} }
} }
void AbstractCodeModel::RemoveFromTree(ExecutionTreePtr execution) void AbstractCodeModel::RemoveFromTree(ExecutionTreePtr execution)
{ {
if (!execution->GetParent()) if (!execution->GetParent())
@ -5304,7 +5350,7 @@ namespace ScriptCanvas
{ {
AddError(execution->GetNodeId(), execution, ScriptCanvas::ParseErrors::RequiredOutputRemoved); AddError(execution->GetNodeId(), execution, ScriptCanvas::ParseErrors::RequiredOutputRemoved);
} }
if (childCount != 0) if (childCount != 0)
{ {
if (childCount > 1) if (childCount > 1)
@ -5332,7 +5378,7 @@ namespace ScriptCanvas
execution->Clear(); execution->Clear();
} }
AZ::Outcome<AZStd::pair<size_t, ExecutionChild>> AbstractCodeModel::RemoveChild(const ExecutionTreePtr& execution, const ExecutionTreeConstPtr& child) AZ::Outcome<AZStd::pair<size_t, ExecutionChild>> AbstractCodeModel::RemoveChild(const ExecutionTreePtr& execution, const ExecutionTreeConstPtr& child)
{ {
return execution->RemoveChild(child); return execution->RemoveChild(child);
@ -5342,7 +5388,5 @@ namespace ScriptCanvas
{ {
return type == Data::eType::BehaviorContextObject; return type == Data::eType::BehaviorContextObject;
} }
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -71,7 +71,7 @@ namespace ScriptCanvas
AZStd::optional<AZStd::pair<size_t, Grammar::DependencyInfo>> CheckUserNodeableDependencyConstructionIndex(VariableConstPtr nodeable) const; AZStd::optional<AZStd::pair<size_t, Grammar::DependencyInfo>> CheckUserNodeableDependencyConstructionIndex(VariableConstPtr nodeable) const;
AZStd::vector<VariableConstPtr> CombineVariableLists AZStd::vector<VariableConstPtr> CombineVariableLists
( const AZStd::vector<Nodeable*>& constructionNodeables (const AZStd::vector<Nodeable*>& constructionNodeables
, const AZStd::vector<AZStd::pair<VariableId, Datum>>& constructionInputVariableIds , const AZStd::vector<AZStd::pair<VariableId, Datum>>& constructionInputVariableIds
, const AZStd::vector<AZStd::pair<VariableId, Data::EntityIDType>>& entityIds) const; , const AZStd::vector<AZStd::pair<VariableId, Data::EntityIDType>>& entityIds) const;
@ -120,7 +120,7 @@ namespace ScriptCanvas
const ParsedRuntimeInputs& GetRuntimeInputs() const; const ParsedRuntimeInputs& GetRuntimeInputs() const;
const Source& GetSource() const; const Source& GetSource() const;
const AZStd::string& GetSourceString() const; const AZStd::string& GetSourceString() const;
ExecutionTreeConstPtr GetStart() const; ExecutionTreeConstPtr GetStart() const;
@ -150,21 +150,19 @@ namespace ScriptCanvas
bool IsUserNodeable(VariableConstPtr variable) const; bool IsUserNodeable(VariableConstPtr variable) const;
bool HasUserNodeableDependenciesInVariables() const;
template<typename T> template<typename T>
AZStd::vector<Grammar::VariableConstPtr> ToVariableList(const AZStd::vector<AZStd::pair<VariableId, T>>& source) const; AZStd::vector<Grammar::VariableConstPtr> ToVariableList(const AZStd::vector<AZStd::pair<VariableId, T>>& source) const;
private: private:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Internal parsing // Internal parsing
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct ReturnValueConnections struct ReturnValueConnections
{ {
bool m_hasOtherConnections = false; bool m_hasOtherConnections = false;
AZStd::vector<VariableConstPtr> m_returnValuesOrReferences; AZStd::vector<VariableConstPtr> m_returnValuesOrReferences;
}; };
void AddAllVariablesPreParse(); void AddAllVariablesPreParse();
void AddAllVariablesPreParse_LegacyFunctions(); void AddAllVariablesPreParse_LegacyFunctions();
@ -210,7 +208,7 @@ namespace ScriptCanvas
bool CheckCreateRoot(const Node& node); bool CheckCreateRoot(const Node& node);
AZStd::string CheckUniqueInterfaceNames AZStd::string CheckUniqueInterfaceNames
( AZStd::string_view candidate (AZStd::string_view candidate
, AZStd::string_view defaultName , AZStd::string_view defaultName
, AZStd::unordered_set<AZStd::string>& uniqueNames , AZStd::unordered_set<AZStd::string>& uniqueNames
, const AZStd::unordered_set<const ScriptCanvas::Nodes::Core::FunctionDefinitionNode*>& nodelingsOut); , const AZStd::unordered_set<const ScriptCanvas::Nodes::Core::FunctionDefinitionNode*>& nodelingsOut);
@ -340,7 +338,7 @@ namespace ScriptCanvas
void ParseExecutionLogicalExpression(ExecutionTreePtr execution, Symbol symbol); void ParseExecutionLogicalExpression(ExecutionTreePtr execution, Symbol symbol);
void ParseExecutionLoop(ExecutionTreePtr execution); void ParseExecutionLoop(ExecutionTreePtr execution);
void ParseExecutionMultipleOutSyntaxSugar(ExecutionTreePtr execution, const EndpointsResolved& executionOutNodes, const AZStd::vector<const Slot*>& outSlots); void ParseExecutionMultipleOutSyntaxSugar(ExecutionTreePtr execution, const EndpointsResolved& executionOutNodes, const AZStd::vector<const Slot*>& outSlots);
void ParseExecutionMultipleOutSyntaxSugarOfSequencNode(ExecutionTreePtr sequence); void ParseExecutionMultipleOutSyntaxSugarOfSequencNode(ExecutionTreePtr sequence);
@ -368,6 +366,8 @@ namespace ScriptCanvas
void ParseExecutionWhileLoop(ExecutionTreePtr execution); void ParseExecutionWhileLoop(ExecutionTreePtr execution);
void ParseFunctionLocalStaticUseage();
void ParseImplicitVariables(const Node& node); void ParseImplicitVariables(const Node& node);
void ParseInputData(ExecutionTreePtr execution); void ParseInputData(ExecutionTreePtr execution);
@ -428,7 +428,7 @@ namespace ScriptCanvas
void PruneNoOpChildren(const ExecutionTreePtr& execution); void PruneNoOpChildren(const ExecutionTreePtr& execution);
AZ::Outcome<AZStd::pair<size_t, ExecutionChild>> RemoveChild(const ExecutionTreePtr& execution, const ExecutionTreeConstPtr& child); AZ::Outcome<AZStd::pair<size_t, ExecutionChild>> RemoveChild(const ExecutionTreePtr& execution, const ExecutionTreeConstPtr& child);
void RemoveFromTree(ExecutionTreePtr execution); void RemoveFromTree(ExecutionTreePtr execution);
struct ConnectionInPreviouslyExecutedScope struct ConnectionInPreviouslyExecutedScope
@ -473,7 +473,7 @@ namespace ScriptCanvas
} }
void AddExecutionMapIn void AddExecutionMapIn
( UserInParseTopologyResult result (UserInParseTopologyResult result
, ExecutionTreeConstPtr root , ExecutionTreeConstPtr root
, const AZStd::vector<ExecutionTreeConstPtr>& outCalls , const AZStd::vector<ExecutionTreeConstPtr>& outCalls
, AZStd::string_view defaultOutName , AZStd::string_view defaultOutName
@ -505,6 +505,7 @@ namespace ScriptCanvas
static UserInParseTopologyResult ParseUserInTolopology(size_t nodelingsOutCount, size_t leavesWithoutNodelingsCount); static UserInParseTopologyResult ParseUserInTolopology(size_t nodelingsOutCount, size_t leavesWithoutNodelingsCount);
size_t m_outIndexCount = 0; size_t m_outIndexCount = 0;
size_t m_generatedIdCount = 0;
ExecutionTreePtr m_start; ExecutionTreePtr m_start;
AZStd::vector<const Nodes::Core::Start*> m_startNodes; AZStd::vector<const Nodes::Core::Start*> m_startNodes;
ScopePtr m_graphScope; ScopePtr m_graphScope;
@ -513,7 +514,7 @@ namespace ScriptCanvas
AZStd::unordered_set<VariableConstPtr> m_userNodeables; AZStd::unordered_set<VariableConstPtr> m_userNodeables;
AZStd::unordered_map<VariableConstPtr, DependencyInfo> m_dependencyByVariable; AZStd::unordered_map<VariableConstPtr, DependencyInfo> m_dependencyByVariable;
AZStd::vector<VariableConstPtr> m_variables; AZStd::vector<VariableConstPtr> m_variables;
AZStd::vector<const Node*> m_possibleExecutionRoots; AZStd::vector<const Node*> m_possibleExecutionRoots;
@ -621,7 +622,7 @@ namespace ScriptCanvas
for (const auto& variable : source) for (const auto& variable : source)
{ {
auto iter = AZStd::find_if auto iter = AZStd::find_if
( m_variables.begin() (m_variables.begin()
, m_variables.end() , m_variables.end()
, [&](const auto& candidate) { return candidate->m_sourceVariableId == variable.first; }); , [&](const auto& candidate) { return candidate->m_sourceVariableId == variable.first; });
@ -633,7 +634,5 @@ namespace ScriptCanvas
return variables; return variables;
} }
}
} }
}

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -47,6 +47,10 @@ namespace ParsingUtilitiesCpp
using namespace ScriptCanvas; using namespace ScriptCanvas;
using namespace ScriptCanvas::Grammar; using namespace ScriptCanvas::Grammar;
const AZ::u64 k_parserGeneratedMask = 0x7FC0616C94E7465F;
const size_t k_maskIndex = 0;
const size_t k_countIndex = 1;
class PrettyPrinter class PrettyPrinter
: public ExecutionTreeTraversalListener : public ExecutionTreeTraversalListener
{ {
@ -85,7 +89,7 @@ namespace ParsingUtilitiesCpp
{ {
m_result += AZStd::string::format(" # children: %zu", childCount); m_result += AZStd::string::format(" # children: %zu", childCount);
} }
if (m_marker == execution) if (m_marker == execution)
{ {
m_result += " <<<< MARKER <<<< "; m_result += " <<<< MARKER <<<< ";
@ -97,7 +101,7 @@ namespace ParsingUtilitiesCpp
m_result += "\n"; m_result += "\n";
} }
void EvaluateRoot(ExecutionTreeConstPtr node, const Slot* ) void EvaluateRoot(ExecutionTreeConstPtr node, const Slot*)
{ {
m_result += "\nRoot:\n"; m_result += "\nRoot:\n";
} }
@ -356,7 +360,7 @@ namespace ScriptCanvas
else if (nodeling->IsExecutionExit()) else if (nodeling->IsExecutionExit())
{ {
return NodelingType::Out; return NodelingType::Out;
} }
} }
return NodelingType::None; return NodelingType::None;
@ -785,7 +789,7 @@ namespace ScriptCanvas
{ {
return execution->GetInputCount() > index return execution->GetInputCount() > index
&& ((execution->GetInput(index).m_value->m_datum.GetAs<Data::NamedEntityIDType>() && *execution->GetInput(index).m_value->m_datum.GetAs<Data::NamedEntityIDType>() == GraphOwnerId && !execution->GetInput(index).m_value->m_isExposedToConstruction) && ((execution->GetInput(index).m_value->m_datum.GetAs<Data::NamedEntityIDType>() && *execution->GetInput(index).m_value->m_datum.GetAs<Data::NamedEntityIDType>() == GraphOwnerId && !execution->GetInput(index).m_value->m_isExposedToConstruction)
|| (execution->GetInput(index).m_value->m_datum.GetAs<Data::EntityIDType>() && *execution->GetInput(index).m_value->m_datum.GetAs<Data::EntityIDType>() == GraphOwnerId && !execution->GetInput(index).m_value->m_isExposedToConstruction)); || (execution->GetInput(index).m_value->m_datum.GetAs<Data::EntityIDType>() && *execution->GetInput(index).m_value->m_datum.GetAs<Data::EntityIDType>() == GraphOwnerId && !execution->GetInput(index).m_value->m_isExposedToConstruction));
} }
bool IsIsNull(const ExecutionTreeConstPtr& execution) bool IsIsNull(const ExecutionTreeConstPtr& execution)
@ -855,7 +859,7 @@ namespace ScriptCanvas
return true; return true;
} }
} }
return IsMidSequence(parent); return IsMidSequence(parent);
} }
@ -1001,10 +1005,16 @@ namespace ScriptCanvas
return true; return true;
} }
bool IsParserGeneratedId(const ScriptCanvas::VariableId& id)
{
using namespace ParsingUtilitiesCpp;
return reinterpret_cast<const AZ::u64*>(id.m_id.data)[k_maskIndex] == k_parserGeneratedMask;
}
bool IsPropertyExtractionSlot(const ExecutionTreeConstPtr& execution, const Slot* outputSlot) bool IsPropertyExtractionSlot(const ExecutionTreeConstPtr& execution, const Slot* outputSlot)
{ {
auto iter = AZStd::find_if auto iter = AZStd::find_if
( execution->GetPropertyExtractionSources().begin() (execution->GetPropertyExtractionSources().begin()
, execution->GetPropertyExtractionSources().end() , execution->GetPropertyExtractionSources().end()
, [&](const auto& iter) { return iter.first == outputSlot; }); , [&](const auto& iter) { return iter.first == outputSlot; });
@ -1052,9 +1062,9 @@ namespace ScriptCanvas
bool IsSequenceNode(const ExecutionTreeConstPtr& execution) bool IsSequenceNode(const ExecutionTreeConstPtr& execution)
{ {
return (IsSequenceNode(execution->GetId().m_node) return (IsSequenceNode(execution->GetId().m_node)
&& execution->GetId().m_slot->GetType() == CombinedSlotType::ExecutionIn); && execution->GetId().m_slot->GetType() == CombinedSlotType::ExecutionIn);
} }
bool IsSwitchStatement(const ExecutionTreeConstPtr& execution) bool IsSwitchStatement(const ExecutionTreeConstPtr& execution)
{ {
return execution->GetId().m_node->IsSwitchStatement() return execution->GetId().m_node->IsSwitchStatement()
@ -1120,6 +1130,16 @@ namespace ScriptCanvas
return AZStd::string::format("%s%s", k_memberNamePrefix, name.data()); return AZStd::string::format("%s%s", k_memberNamePrefix, name.data());
} }
VariableId MakeParserGeneratedId(size_t count)
{
using namespace ParsingUtilitiesCpp;
AZ::Uuid parserGenerated;
reinterpret_cast<AZ::u64*>(parserGenerated.data)[k_maskIndex] = k_parserGeneratedMask;
reinterpret_cast<AZ::u64*>(parserGenerated.data)[k_countIndex] = count;
return ScriptCanvas::VariableId(parserGenerated);
}
VariableConstructionRequirement ParseConstructionRequirement(VariableConstPtr variable) VariableConstructionRequirement ParseConstructionRequirement(VariableConstPtr variable)
{ {
if (IsEntityIdThatRequiresRuntimeRemap(variable)) if (IsEntityIdThatRequiresRuntimeRemap(variable))
@ -1216,7 +1236,7 @@ namespace ScriptCanvas
result += AZStd::string::format("Variable: %s, Type: %s, Scope: %s, \n" result += AZStd::string::format("Variable: %s, Type: %s, Scope: %s, \n"
, variable->m_name.data() , variable->m_name.data()
, Data::GetName(variable->m_datum.GetType()).data() , Data::GetName(variable->m_datum.GetType()).data()
, variable->m_isMember ? "Member" : "Local" ); , variable->m_isMember ? "Member" : "Local");
} }
auto roots = model.GetAllExecutionRoots(); auto roots = model.GetAllExecutionRoots();
@ -1261,11 +1281,11 @@ namespace ScriptCanvas
bool RequiresRuntimeRemap(const AZ::EntityId& entityId) bool RequiresRuntimeRemap(const AZ::EntityId& entityId)
{ {
return entityId.IsValid() return entityId.IsValid()
&& entityId != UniqueId && entityId != UniqueId
&& entityId != GraphOwnerId; && entityId != GraphOwnerId;
} }
AZStd::string SlotNameToIndexString(const Slot& slot) AZStd::string SlotNameToIndexString(const Slot& slot)
{ {
auto indexString = slot.GetName(); auto indexString = slot.GetName();
@ -1445,5 +1465,5 @@ namespace ScriptCanvas
} }
} }
} }
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -113,7 +113,7 @@ namespace ScriptCanvas
bool IsInfiniteSelfEntityActivationLoop(const AbstractCodeModel& model, ExecutionTreeConstPtr execution); bool IsInfiniteSelfEntityActivationLoop(const AbstractCodeModel& model, ExecutionTreeConstPtr execution);
bool IsInfiniteSelfEntityActivationLoopRecurse(const AbstractCodeModel& model, ExecutionTreeConstPtr execution); bool IsInfiniteSelfEntityActivationLoopRecurse(const AbstractCodeModel& model, ExecutionTreeConstPtr execution);
bool IsInfiniteVariableWriteHandlingLoop(const AbstractCodeModel& model, VariableWriteHandlingPtr variableHandling, ExecutionTreeConstPtr execution, bool isConnected); bool IsInfiniteVariableWriteHandlingLoop(const AbstractCodeModel& model, VariableWriteHandlingPtr variableHandling, ExecutionTreeConstPtr execution, bool isConnected);
bool IsInLoop(const ExecutionTreeConstPtr& execution); bool IsInLoop(const ExecutionTreeConstPtr& execution);
@ -144,6 +144,8 @@ namespace ScriptCanvas
bool IsOnSelfEntityActivated(const AbstractCodeModel& model, ExecutionTreeConstPtr execution); bool IsOnSelfEntityActivated(const AbstractCodeModel& model, ExecutionTreeConstPtr execution);
bool IsParserGeneratedId(const VariableId& id);
bool IsPropertyExtractionSlot(const ExecutionTreeConstPtr& execution, const Slot* outputSlot); bool IsPropertyExtractionSlot(const ExecutionTreeConstPtr& execution, const Slot* outputSlot);
bool IsPropertyExtractionNode(const ExecutionTreeConstPtr& execution); bool IsPropertyExtractionNode(const ExecutionTreeConstPtr& execution);
@ -178,6 +180,8 @@ namespace ScriptCanvas
bool IsWrittenMathExpression(const ExecutionTreeConstPtr& execution); bool IsWrittenMathExpression(const ExecutionTreeConstPtr& execution);
VariableId MakeParserGeneratedId(size_t count);
AZStd::string MakeMemberVariableName(AZStd::string_view name); AZStd::string MakeMemberVariableName(AZStd::string_view name);
VariableConstructionRequirement ParseConstructionRequirement(Grammar::VariableConstPtr value); VariableConstructionRequirement ParseConstructionRequirement(Grammar::VariableConstPtr value);
@ -203,6 +207,5 @@ namespace ScriptCanvas
void TraverseTree(const AbstractCodeModel& execution, ExecutionTreeTraversalListener& listener); void TraverseTree(const AbstractCodeModel& execution, ExecutionTreeTraversalListener& listener);
void TraverseTree(const ExecutionTreeConstPtr& execution, ExecutionTreeTraversalListener& listener); void TraverseTree(const ExecutionTreeConstPtr& execution, ExecutionTreeTraversalListener& listener);
} }
}
}

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -99,9 +99,9 @@ namespace ScriptCanvas
m_inputs.clear(); m_inputs.clear();
m_outputs.clear(); m_outputs.clear();
} }
bool FunctionPrototype::IsVoid() const bool FunctionPrototype::IsVoid() const
{ {
return m_outputs.empty(); return m_outputs.empty();
} }
@ -200,24 +200,23 @@ namespace ScriptCanvas
baseName.append(suffix); baseName.append(suffix);
return AddVariableName(baseName); return AddVariableName(baseName);
} }
AZ::s32 Scope::AddNameCount(AZStd::string_view name) AZ::s32 Scope::AddNameCount(AZStd::string_view name)
{ {
AZ::s32 count = -1; AZ::s32 count = -1;
ScopePtr ns = shared_from_this(); ScopePtr ns = shared_from_this();
do do
{ {
auto iter = ns->m_baseNameToCount.find(name); auto iter = ns->m_baseNameToCount.find(name);
if (iter != ns->m_baseNameToCount.end()) if (iter != ns->m_baseNameToCount.end())
{ {
// a basename has been found in current or parent scope, get the latest count // a basename has been found in current or parent scope, get the latest count
count = iter->second; count = iter->second;
break; break;
} }
} } while ((ns = AZStd::const_pointer_cast<Scope>(ns->m_parent)));
while ((ns = AZStd::const_pointer_cast<Scope>(ns->m_parent)));
auto iter = m_baseNameToCount.find(name); auto iter = m_baseNameToCount.find(name);
if (iter == m_baseNameToCount.end()) if (iter == m_baseNameToCount.end())
@ -235,7 +234,7 @@ namespace ScriptCanvas
const VariableData Source::k_emptyVardata{}; const VariableData Source::k_emptyVardata{};
Source::Source Source::Source
( const Graph& graph (const Graph& graph
, const AZ::Data::AssetId& id , const AZ::Data::AssetId& id
, const GraphData& graphData , const GraphData& graphData
, const VariableData& variableData , const VariableData& variableData
@ -277,8 +276,8 @@ namespace ScriptCanvas
AzFramework::StringFunc::Path::StripExtension(namespacePath); AzFramework::StringFunc::Path::StripExtension(namespacePath);
return AZ::Success(Source return AZ::Success(Source
( *request.graph (*request.graph
, request.assetId , request.scriptAssetId
, *graphData , *graphData
, *sourceVariableData , *sourceVariableData
, name , name
@ -294,23 +293,23 @@ namespace ScriptCanvas
} }
Variable::Variable(Datum&& datum) Variable::Variable(Datum&& datum)
: m_datum(datum) : m_datum(datum)
{} {}
Variable::Variable(const Datum& datum, const AZStd::string& name, TraitsFlags traitsFlags) Variable::Variable(const Datum& datum, const AZStd::string& name, TraitsFlags traitsFlags)
: m_datum(datum) : m_datum(datum)
, m_name(name) , m_name(name)
, m_isConst(traitsFlags & TraitsFlags::Const) , m_isConst(traitsFlags& TraitsFlags::Const)
, m_isMember(traitsFlags & TraitsFlags::Member) , m_isMember(traitsFlags& TraitsFlags::Member)
{} {}
Variable::Variable(Datum&& datum, AZStd::string&& name, TraitsFlags&& traitsFlags) Variable::Variable(Datum&& datum, AZStd::string&& name, TraitsFlags&& traitsFlags)
: m_datum(datum) : m_datum(datum)
, m_name(name) , m_name(name)
, m_isConst(traitsFlags & TraitsFlags::Const) , m_isConst(traitsFlags& TraitsFlags::Const)
, m_isMember(traitsFlags & TraitsFlags::Member) , m_isMember(traitsFlags& TraitsFlags::Member)
{} {}
void Variable::Reflect(AZ::ReflectContext* reflectContext) void Variable::Reflect(AZ::ReflectContext* reflectContext)
{ {
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext)) if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext))
@ -339,5 +338,5 @@ namespace ScriptCanvas
m_variable = nullptr; m_variable = nullptr;
m_connectionVariable = nullptr; m_connectionVariable = nullptr;
} }
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -12,7 +12,9 @@ namespace ScriptCanvas
namespace Grammar namespace Grammar
{ {
AZ_CVAR(bool, g_disableParseOnGraphValidation, false, {}, AZ::ConsoleFunctorFlags::Null, "In case parsing the graph is interfering with opening a graph, disable parsing on validation"); AZ_CVAR(bool, g_disableParseOnGraphValidation, false, {}, AZ::ConsoleFunctorFlags::Null, "In case parsing the graph is interfering with opening a graph, disable parsing on validation");
AZ_CVAR(bool, g_printAbstractCodeModel, false, {}, AZ::ConsoleFunctorFlags::Null, "Print out the Abstract Code Model at the end of parsing for debug purposes."); AZ_CVAR(bool, g_printAbstractCodeModel, true, {}, AZ::ConsoleFunctorFlags::Null, "Print out the Abstract Code Model at the end of parsing for debug purposes.");
AZ_CVAR(bool, g_saveRawTranslationOuputToFile, false, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation for debug purposes."); AZ_CVAR(bool, g_printAbstractCodeModelAtPrefabTime, false, {}, AZ::ConsoleFunctorFlags::Null, "Print out the Abstract Code Model at the end of parsing (at prefab time) for debug purposes.");
AZ_CVAR(bool, g_saveRawTranslationOuputToFile, true, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation for debug purposes.");
AZ_CVAR(bool, g_saveRawTranslationOuputToFileAtPrefabTime, false, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation (at prefab time) for debug purposes.");
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -108,7 +108,7 @@ namespace ScriptCanvas
constexpr const char* k_InitializeExecutionOutByRequiredCountName = "InitializeExecutionOutByRequiredCount"; constexpr const char* k_InitializeExecutionOutByRequiredCountName = "InitializeExecutionOutByRequiredCount";
constexpr const char* k_InterpretedConfigurationPerformance = "SCRIPT_CANVAS_GLOBAL_PERFORMANCE"; constexpr const char* k_InterpretedConfigurationPerformance = "SCRIPT_CANVAS_GLOBAL_PERFORMANCE";
constexpr const char* k_InterpretedConfigurationRelease = "SCRIPT_CANVAS_GLOBAL_RELEASE"; constexpr const char* k_InterpretedConfigurationRelease = "SCRIPT_CANVAS_GLOBAL_RELEASE";
constexpr const char* k_NodeableCallInterpretedOut = "ExecutionOut"; constexpr const char* k_NodeableCallInterpretedOut = "ExecutionOut";
constexpr const char* k_NodeableUserBaseClassName = "Nodeable"; constexpr const char* k_NodeableUserBaseClassName = "Nodeable";
constexpr const char* k_NodeableSetExecutionOutName = "SetExecutionOut"; constexpr const char* k_NodeableSetExecutionOutName = "SetExecutionOut";
@ -120,7 +120,7 @@ namespace ScriptCanvas
constexpr const char* k_OnGraphStartFunctionName = "OnGraphStart"; constexpr const char* k_OnGraphStartFunctionName = "OnGraphStart";
constexpr const char* k_OverrideNodeableMetatableName = "OverrideNodeableMetatable"; constexpr const char* k_OverrideNodeableMetatableName = "OverrideNodeableMetatable";
constexpr const char* k_stringFormatLexicalScopeName = "string"; constexpr const char* k_stringFormatLexicalScopeName = "string";
constexpr const char* k_stringFormatName = "format"; constexpr const char* k_stringFormatName = "format";
@ -139,7 +139,7 @@ namespace ScriptCanvas
constexpr const char* k_DependentAssetsIndexArgName = "dependentAssetsIndex"; constexpr const char* k_DependentAssetsIndexArgName = "dependentAssetsIndex";
constexpr const char* k_UnpackDependencyConstructionArgsFunctionName = "UnpackDependencyConstructionArgs"; constexpr const char* k_UnpackDependencyConstructionArgsFunctionName = "UnpackDependencyConstructionArgs";
constexpr const char* k_UnpackDependencyConstructionArgsLeafFunctionName = "UnpackDependencyConstructionArgsLeaf"; constexpr const char* k_UnpackDependencyConstructionArgsLeafFunctionName = "UnpackDependencyConstructionArgsLeaf";
enum class ExecutionCharacteristics : AZ::u32 enum class ExecutionCharacteristics : AZ::u32
{ {
Object, Object,
@ -147,7 +147,7 @@ namespace ScriptCanvas
}; };
// default to a pure, interpreted function // default to a pure, interpreted function
enum ExecutionStateSelection : AZ::u32 enum class ExecutionStateSelection : AZ::u32
{ {
InterpretedPure, InterpretedPure,
InterpretedPureOnGraphStart, InterpretedPureOnGraphStart,
@ -172,7 +172,7 @@ namespace ScriptCanvas
Count, Count,
}; };
#undef REGISTER_ENUM #undef REGISTER_ENUM
// create the Symbol strings // create the Symbol strings
#define REGISTER_ENUM(x) #x, #define REGISTER_ENUM(x) #x,
static const char* g_SymbolNames[] = static const char* g_SymbolNames[] =
@ -247,7 +247,9 @@ namespace ScriptCanvas
AZ_CVAR_EXTERNED(bool, g_disableParseOnGraphValidation); AZ_CVAR_EXTERNED(bool, g_disableParseOnGraphValidation);
AZ_CVAR_EXTERNED(bool, g_printAbstractCodeModel); AZ_CVAR_EXTERNED(bool, g_printAbstractCodeModel);
AZ_CVAR_EXTERNED(bool, g_printAbstractCodeModelAtPrefabTime);
AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFile); AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFile);
AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFileAtPrefabTime);
struct DependencyInfo struct DependencyInfo
{ {
@ -258,7 +260,7 @@ namespace ScriptCanvas
struct Request struct Request
{ {
AZ::Data::AssetId assetId; AZ::Data::AssetId scriptAssetId;
const Graph* graph = nullptr; const Graph* graph = nullptr;
AZStd::string_view name; AZStd::string_view name;
AZStd::string_view path; AZStd::string_view path;
@ -291,7 +293,7 @@ namespace ScriptCanvas
Source() = default; Source() = default;
Source Source
( const Graph& graph (const Graph& graph
, const AZ::Data::AssetId& id , const AZ::Data::AssetId& id
, const GraphData& graphData , const GraphData& graphData
, const VariableData& variableData , const VariableData& variableData
@ -305,8 +307,8 @@ namespace ScriptCanvas
AZStd::string ToTypeSafeEBusResultName(const Data::Type& type); AZStd::string ToTypeSafeEBusResultName(const Data::Type& type);
AZStd::string ToSafeName(const AZStd::string& name); AZStd::string ToSafeName(const AZStd::string& name);
NamespacePath ToNamespacePath(AZStd::string_view path, AZStd::string_view name); NamespacePath ToNamespacePath(AZStd::string_view path, AZStd::string_view name);
} }
} }
namespace AZStd namespace AZStd
{ {

@ -0,0 +1,101 @@
/*
* 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/Serialization/Json/JsonSerialization.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Serialization/ScriptUserDataSerializer.h>
using namespace ScriptCanvas;
namespace AZ
{
AZ_CLASS_ALLOCATOR_IMPL(ScriptUserDataSerializer, SystemAllocator, 0);
JsonSerializationResult::Result ScriptUserDataSerializer::Load
( void* outputValue
, [[maybe_unused]] const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(outputValueTypeId == azrtti_typeid<RuntimeVariable>(), "ScriptUserDataSerializer Load against output typeID that was not RuntimeVariable");
AZ_Assert(outputValue, "ScriptUserDataSerializer Load against null output");
auto outputVariable = reinterpret_cast<RuntimeVariable*>(outputValue);
JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField);
AZ::Uuid typeId = AZ::Uuid::CreateNull();
auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier);
if (typeIdMember == inputValue.MemberEnd())
{
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Missing, AZStd::string::format("ScriptUserDataSerializer::Load failed to load the %s member", JsonSerialization::TypeIdFieldIdentifier));
}
result.Combine(LoadTypeId(typeId, typeIdMember->value, context));
if (typeId.IsNull())
{
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "ScriptUserDataSerializer::Load failed to load the AZ TypeId of the value");
}
outputVariable->value = context.GetSerializeContext()->CreateAny(typeId);
if (outputVariable->value.empty() || outputVariable->value.type() != typeId)
{
return context.Report(result, "ScriptUserDataSerializer::Load failed to load a value matched the reported AZ TypeId. The C++ declaration may have been deleted or changed.");
}
result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&outputVariable->value), typeId, inputValue, "value", context));
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "ScriptUserDataSerializer Load finished loading RuntimeVariable"
: "ScriptUserDataSerializer Load failed to load RuntimeVariable");
}
JsonSerializationResult::Result ScriptUserDataSerializer::Store
( rapidjson::Value& outputValue
, const void* inputValue
, const void* defaultValue
, [[maybe_unused]] const Uuid& valueTypeId
, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(valueTypeId == azrtti_typeid<RuntimeVariable>(), "RuntimeVariable Store against value typeID that was not RuntimeVariable");
AZ_Assert(inputValue, "RuntimeVariable Store against null inputValue pointer ");
auto inputScriptDataPtr = reinterpret_cast<const RuntimeVariable*>(inputValue);
auto defaultScriptDataPtr = reinterpret_cast<const RuntimeVariable*>(defaultValue);
auto inputAnyPtr = &inputScriptDataPtr->value;
auto defaultAnyPtr = defaultScriptDataPtr ? &defaultScriptDataPtr->value : nullptr;
if (defaultAnyPtr)
{
ScriptCanvas::Datum inputDatum(ScriptCanvas::Data::FromAZType(inputAnyPtr->type()), ScriptCanvas::Datum::eOriginality::Copy, AZStd::any_cast<void>(inputAnyPtr), inputAnyPtr->type());
ScriptCanvas::Datum defaultDatum(ScriptCanvas::Data::FromAZType(defaultAnyPtr->type()), ScriptCanvas::Datum::eOriginality::Copy, AZStd::any_cast<void>(defaultAnyPtr), defaultAnyPtr->type());
if (inputDatum == defaultDatum)
{
return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "ScriptUserDataSerializer Store used defaults for RuntimeVariable");
}
}
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
{
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, inputAnyPtr->type(), context));
outputValue.AddMember(rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), AZStd::move(typeValue), context.GetJsonAllocator());
}
result.Combine(ContinueStoringToJsonObjectField(outputValue, "value", AZStd::any_cast<void>(inputAnyPtr), AZStd::any_cast<void>(defaultAnyPtr), inputAnyPtr->type(), context));
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "ScriptUserDataSerializer Store finished saving RuntimeVariable"
: "ScriptUserDataSerializer Store failed to save RuntimeVariable");
}
}

@ -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 <AzCore/Memory/Memory.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AZ
{
class ScriptUserDataSerializer
: public BaseJsonSerializer
{
public:
AZ_RTTI(ScriptUserDataSerializer, "{7E5FC193-8CDB-4251-A68B-F337027381DF}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
private:
JsonSerializationResult::Result Load
( void* outputValue
, const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store
( rapidjson::Value& outputValue
, const void* inputValue
, const void* defaultValue
, const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
}

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -75,7 +75,7 @@ namespace ScriptCanvas
{ {
return m_model.GetSource().m_name; return m_model.GetSource().m_name;
} }
AZStd::string_view GraphToX::GetFullPath() const AZStd::string_view GraphToX::GetFullPath() const
{ {
return m_model.GetSource().m_path; return m_model.GetSource().m_path;
@ -120,7 +120,7 @@ namespace ScriptCanvas
resolution += Grammar::ToIdentifier(namespaces[index]); resolution += Grammar::ToIdentifier(namespaces[index]);
} }
} }
return resolution; return resolution;
} }
@ -128,13 +128,13 @@ namespace ScriptCanvas
{ {
writer.Write(m_configuration.m_singleLineComment); writer.Write(m_configuration.m_singleLineComment);
} }
void GraphToX::OpenBlockComment(Writer& writer) void GraphToX::OpenBlockComment(Writer& writer)
{ {
writer.WriteIndent(); writer.WriteIndent();
writer.WriteLine(m_configuration.m_blockCommentOpen); writer.WriteLine(m_configuration.m_blockCommentOpen);
} }
void GraphToX::OpenFunctionBlock(Writer& writer) void GraphToX::OpenFunctionBlock(Writer& writer)
{ {
writer.WriteLineIndented(m_configuration.m_functionBlockOpen); writer.WriteLineIndented(m_configuration.m_functionBlockOpen);
@ -162,7 +162,7 @@ namespace ScriptCanvas
void GraphToX::WriteCopyright(Writer& writer) void GraphToX::WriteCopyright(Writer& writer)
{ {
OpenBlockComment(writer); OpenBlockComment(writer);
writer.WriteLine(GetAmazonCopyright()); writer.WriteLine(GetCopyright());
CloseBlockComment(writer); CloseBlockComment(writer);
} }
@ -206,5 +206,5 @@ namespace ScriptCanvas
writer.Write("Last written: "); writer.Write("Last written: ");
writer.WriteLine(buffer); writer.WriteLine(buffer);
} }
} }
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -30,7 +30,6 @@ namespace TranslationCPP
AZ::Outcome<AZStd::pair<AZStd::string, AZStd::string>, AZStd::pair<AZStd::string, AZStd::string>> ToCPlusPlus(const Grammar::AbstractCodeModel& model, bool rawSave = false) AZ::Outcome<AZStd::pair<AZStd::string, AZStd::string>, AZStd::pair<AZStd::string, AZStd::string>> ToCPlusPlus(const Grammar::AbstractCodeModel& model, bool rawSave = false)
{ {
AZStd::string dotH, dotCPP; AZStd::string dotH, dotCPP;
auto outcome = GraphToCPlusPlus::Translate(model, dotH, dotCPP); auto outcome = GraphToCPlusPlus::Translate(model, dotH, dotCPP);
if (outcome.IsSuccess()) if (outcome.IsSuccess())
{ {
@ -48,13 +47,11 @@ namespace TranslationCPP
{ {
saveOutcome = SaveDotCPP(model.GetSource(), dotCPP); saveOutcome = SaveDotCPP(model.GetSource(), dotCPP);
} }
if (!saveOutcome.IsSuccess()) if (!saveOutcome.IsSuccess())
{ {
AZ_TracePrintf("Save failed %s", saveOutcome.GetError().data()); AZ_TracePrintf("Save failed %s", saveOutcome.GetError().data());
} }
} }
return AZ::Success(AZStd::make_pair(AZStd::move(dotH), AZStd::move(dotCPP))); return AZ::Success(AZStd::make_pair(AZStd::move(dotH), AZStd::move(dotCPP)));
} }
else else
@ -96,16 +93,28 @@ namespace ScriptCanvas
{ {
namespace Translation namespace Translation
{ {
Result ParseGraph(const Grammar::Request& request) AZ::Outcome<Grammar::AbstractCodeModelConstPtr, AZStd::string> ParseGraph(const Grammar::Request& request)
{ {
AZ::Outcome<Grammar::Source, AZStd::string> sourceOutcome = Grammar::Source::Construct(request); AZ::Outcome<Grammar::Source, AZStd::string> sourceOutcome = Grammar::Source::Construct(request);
if (!sourceOutcome.IsSuccess()) if (!sourceOutcome.IsSuccess())
{ {
return Result(sourceOutcome.TakeError()); return AZ::Failure(sourceOutcome.TakeError());
} }
Grammar::AbstractCodeModelConstPtr model = Grammar::AbstractCodeModel::Parse(sourceOutcome.TakeValue()); Grammar::AbstractCodeModelConstPtr model = Grammar::AbstractCodeModel::Parse(sourceOutcome.TakeValue());
return AZ::Success(model);
}
Result ParseAndTranslateGraph(const Grammar::Request& request)
{
auto parseOutcome = ParseGraph(request);
if (!parseOutcome.IsSuccess())
{
return Result(parseOutcome.TakeError());
}
Grammar::AbstractCodeModelConstPtr model = parseOutcome.TakeValue();
Translations translations; Translations translations;
Errors errors; Errors errors;
@ -124,61 +133,56 @@ namespace ScriptCanvas
} }
} }
// if (targetFlags & (TargetFlags::Cpp | TargetFlags::Hpp)) // Translation to C++ (executed via BehaviorContext calls) has been demonstrated in the past and is partially in progress.
// { // These calls allow for users to execute multiple translations from the same abstract code model.
// auto outcomeCPP = TranslationCPP::ToCPlusPlus(*model.get(), rawSave); // More work is required to complete all the latest features of the ACM, and do integrate output files into the build.
// if (outcomeCPP.IsSuccess()) //
// { // if (targetFlags & (TargetFlags::Cpp | TargetFlags::Hpp))
// auto hppAndCpp = outcomeCPP.TakeValue(); // {
// // auto outcomeCPP = TranslationCPP::ToCPlusPlus(*model.get(), rawSave);
// TargetResult cppResult; // if (outcomeCPP.IsSuccess())
// cppResult.m_text = AZStd::move(hppAndCpp.first); // {
// translations.emplace(TargetFlags::Hpp, AZStd::move(cppResult)); // auto hppAndCpp = outcomeCPP.TakeValue();
// TargetResult hppResult; //
// hppResult.m_text = AZStd::move(hppAndCpp.second); // TargetResult cppResult;
// translations.emplace(TargetFlags::Cpp, AZStd::move(hppResult)); // cppResult.m_text = AZStd::move(hppAndCpp.first);
// } // translations.emplace(TargetFlags::Hpp, AZStd::move(cppResult));
// else // TargetResult hppResult;
// { // hppResult.m_text = AZStd::move(hppAndCpp.second);
// auto hppAndCpp = outcomeCPP.TakeError(); // translations.emplace(TargetFlags::Cpp, AZStd::move(hppResult));
// errors.emplace(TargetFlags::Hpp, AZStd::move(hppAndCpp.first)); // }
// errors.emplace(TargetFlags::Cpp, AZStd::move(hppAndCpp.second)); // else
// } // {
// } // auto hppAndCpp = outcomeCPP.TakeError();
// errors.emplace(TargetFlags::Hpp, AZStd::move(hppAndCpp.first));
// errors.emplace(TargetFlags::Cpp, AZStd::move(hppAndCpp.second));
// }
// }
} }
else
{
ValidationResults results;
for (auto& test : model->GetValidationEvents())
{
results.AddValidationEvent(test.get());
}
}
return Result(model, AZStd::move(translations), AZStd::move(errors)); return Result(model, AZStd::move(translations), AZStd::move(errors));
} }
Result ToCPlusPlusAndLua(const Grammar::Request& request) Result ToCPlusPlusAndLua(const Grammar::Request& request)
{ {
Grammar::Request toBoth = request; Grammar::Request toBoth = request;
toBoth.translationTargetFlags = TargetFlags::Lua | TargetFlags::Cpp; toBoth.translationTargetFlags = TargetFlags::Lua | TargetFlags::Cpp;
return ParseGraph(toBoth); return ParseAndTranslateGraph(toBoth);
} }
Result ToCPlusPlus(const Grammar::Request& request) Result ToCPlusPlus(const Grammar::Request& request)
{ {
Grammar::Request toCpp = request; Grammar::Request toCpp = request;
toCpp.translationTargetFlags = TargetFlags::Cpp; toCpp.translationTargetFlags = TargetFlags::Cpp;
return ParseGraph(toCpp); return ParseAndTranslateGraph(toCpp);
} }
Result ToLua(const Grammar::Request& request) Result ToLua(const Grammar::Request& request)
{ {
Grammar::Request toLua = request; Grammar::Request toLua = request;
toLua.translationTargetFlags = TargetFlags::Lua; toLua.translationTargetFlags = TargetFlags::Lua;
return ParseGraph(toLua); return ParseAndTranslateGraph(toLua);
} }
}
} }
}

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -18,14 +18,15 @@ namespace ScriptCanvas
namespace Translation namespace Translation
{ {
Result ParseGraph(const Grammar::Request& request); AZ::Outcome<Grammar::AbstractCodeModelConstPtr, AZStd::string> ParseGraph(const Grammar::Request& request);
Result ParseAndTranslateGraph(const Grammar::Request& request);
Result ToCPlusPlus(const Grammar::Request& request); Result ToCPlusPlus(const Grammar::Request& request);
Result ToCPlusPlusAndLua(const Grammar::Request& request); Result ToCPlusPlusAndLua(const Grammar::Request& request);
Result ToLua(const Grammar::Request& request); Result ToLua(const Grammar::Request& request);
}
} }
}

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -41,7 +41,7 @@ namespace ScriptCanvas
Cpp = 1 << 1, Cpp = 1 << 1,
Hpp = 1 << 2, Hpp = 1 << 2,
}; };
// information required at runtime begin execution of the compiled graph from the host // information required at runtime begin execution of the compiled graph from the host
struct RuntimeInputs struct RuntimeInputs
{ {
@ -51,10 +51,13 @@ namespace ScriptCanvas
static void Reflect(AZ::ReflectContext* reflectContext); static void Reflect(AZ::ReflectContext* reflectContext);
Grammar::ExecutionStateSelection m_executionSelection = Grammar::ExecutionStateSelection::InterpretedPure; Grammar::ExecutionStateSelection m_executionSelection = Grammar::ExecutionStateSelection::InterpretedPure;
AZStd::vector<Nodeable*> m_nodeables; AZStd::vector<Nodeable*> m_nodeables;
AZStd::vector<AZStd::pair<VariableId, Datum>> m_variables; AZStd::vector<AZStd::pair<VariableId, Datum>> m_variables;
// either the entityId was a (member) variable in the source graph, or it got promoted to one during parsing // either the entityId was a (member) variable in the source graph, or it got promoted to one during parsing
AZStd::vector<AZStd::pair<VariableId, Data::EntityIDType>> m_entityIds; AZStd::vector<AZStd::pair<VariableId, Data::EntityIDType>> m_entityIds;
// Statics required for internal, local values that need non-code constructible initialization, // Statics required for internal, local values that need non-code constructible initialization,
// when the system can't pass in the input from C++. // when the system can't pass in the input from C++.
AZStd::vector<AZStd::pair<VariableId, AZStd::any>> m_staticVariables; AZStd::vector<AZStd::pair<VariableId, AZStd::any>> m_staticVariables;
@ -84,7 +87,7 @@ namespace ScriptCanvas
using ErrorList = AZStd::vector<AZStd::string>; using ErrorList = AZStd::vector<AZStd::string>;
using Errors = AZStd::unordered_map<TargetFlags, ErrorList>; using Errors = AZStd::unordered_map<TargetFlags, ErrorList>;
using Translations = AZStd::unordered_map<TargetFlags, TargetResult>; using Translations = AZStd::unordered_map<TargetFlags, TargetResult>;
AZStd::sys_time_t SumDurations(const Translations& translation); AZStd::sys_time_t SumDurations(const Translations& translation);
class Result class Result
@ -98,6 +101,7 @@ namespace ScriptCanvas
const AZStd::sys_time_t m_translationDuration; const AZStd::sys_time_t m_translationDuration;
Result(AZStd::string invalidSourceInfo); Result(AZStd::string invalidSourceInfo);
Result(Result&& source);
Result(Grammar::AbstractCodeModelConstPtr model); Result(Grammar::AbstractCodeModelConstPtr model);
Result(Grammar::AbstractCodeModelConstPtr model, Translations&& translations, Errors&& errors); Result(Grammar::AbstractCodeModelConstPtr model, Translations&& translations, Errors&& errors);
@ -107,7 +111,7 @@ namespace ScriptCanvas
AZ::Outcome<void, AZStd::string> IsSuccess(TargetFlags flag) const; AZ::Outcome<void, AZStd::string> IsSuccess(TargetFlags flag) const;
bool TranslationSucceed(TargetFlags flag) const; bool TranslationSucceed(TargetFlags flag) const;
}; };
struct LuaAssetResult struct LuaAssetResult
{ {
AZ::Data::Asset<AZ::ScriptAsset> m_scriptAsset; AZ::Data::Asset<AZ::ScriptAsset> m_scriptAsset;
@ -117,7 +121,5 @@ namespace ScriptCanvas
AZStd::sys_time_t m_parseDuration; AZStd::sys_time_t m_parseDuration;
AZStd::sys_time_t m_translationDuration; AZStd::sys_time_t m_translationDuration;
}; };
}
} }
}

@ -166,7 +166,7 @@ namespace ScriptCanvas
return TranslationUtilitiesCPP::k_namespaceNameNative; return TranslationUtilitiesCPP::k_namespaceNameNative;
} }
AZStd::string_view GetAmazonCopyright() AZStd::string_view GetCopyright()
{ {
return return
"* 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.\n" "* 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.\n"

@ -34,7 +34,7 @@ namespace ScriptCanvas
AZStd::string EntityIdValueToString(const AZ::EntityId& entityId, const Configuration& config); AZStd::string EntityIdValueToString(const AZ::EntityId& entityId, const Configuration& config);
AZStd::string_view GetAmazonCopyright(); AZStd::string_view GetCopyright();
AZStd::string_view GetAutoNativeNamespace(); AZStd::string_view GetAutoNativeNamespace();

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -102,45 +102,45 @@ namespace ScriptCanvas
classElement.RemoveElementByName(AZ_CRC_CE("Scope")); classElement.RemoveElementByName(AZ_CRC_CE("Scope"));
classElement.AddElementWithData<VariableFlags::InitialValueSource>(context, "InitialValueSource", VariableFlags::InitialValueSource::Component); classElement.AddElementWithData<VariableFlags::InitialValueSource>(context, "InitialValueSource", VariableFlags::InitialValueSource::Component);
} }
classElement.RemoveElementByName(AZ_CRC("ExposeAsInput", 0x0f7879f0));
classElement.RemoveElementByName(AZ_CRC("Exposure", 0x398f29cd));
} }
else else
if (classElement.GetVersion() < 3) if (classElement.GetVersion() < 3)
{
bool exposeAsInputField = false;
classElement.GetChildData<bool>(AZ_CRC("ExposeAsInput", 0x0f7879f0), exposeAsInputField);
if (exposeAsInputField)
{
classElement.RemoveElementByName(AZ_CRC("Exposure", 0x398f29cd));
classElement.AddElementWithData<VariableFlags::Scope>(context, "Scope", VariableFlags::Scope::Graph);
}
else
{ {
AZ::u8 exposureType = VariableFlags::Deprecated::Exposure::Exp_Local; bool exposeAsInputField = false;
classElement.GetChildData<AZ::u8>(AZ_CRC("Exposure", 0x398f29cd), exposureType); classElement.GetChildData<bool>(AZ_CRC("ExposeAsInput", 0x0f7879f0), exposeAsInputField);
VariableFlags::Scope scope = VariableFlags::Scope::Graph; if (exposeAsInputField)
if ((exposureType & VariableFlags::Deprecated::Exposure::Exp_InOut) == VariableFlags::Deprecated::Exposure::Exp_InOut)
{
scope = VariableFlags::Scope::Graph;
}
else if (exposureType & VariableFlags::Deprecated::Exposure::Exp_Input)
{ {
scope = VariableFlags::Scope::Graph; classElement.RemoveElementByName(AZ_CRC("Exposure", 0x398f29cd));
classElement.AddElementWithData<VariableFlags::Scope>(context, "Scope", VariableFlags::Scope::Graph);
} }
else if (exposureType & VariableFlags::Deprecated::Exposure::Exp_Output) else
{ {
scope = VariableFlags::Scope::Function; AZ::u8 exposureType = VariableFlags::Deprecated::Exposure::Exp_Local;
classElement.GetChildData<AZ::u8>(AZ_CRC("Exposure", 0x398f29cd), exposureType);
VariableFlags::Scope scope = VariableFlags::Scope::Graph;
if (((exposureType & VariableFlags::Deprecated::Exposure::Exp_InOut) == VariableFlags::Deprecated::Exposure::Exp_InOut)
|| exposureType & VariableFlags::Deprecated::Exposure::Exp_Input)
{
scope = VariableFlags::Scope::Graph;
}
else if (exposureType & VariableFlags::Deprecated::Exposure::Exp_Output)
{
scope = VariableFlags::Scope::Function;
}
classElement.AddElementWithData<VariableFlags::Scope>(context, "Scope", scope);
} }
classElement.AddElementWithData<VariableFlags::Scope>(context, "Scope", scope); classElement.RemoveElementByName(AZ_CRC("Exposure", 0x398f29cd));
classElement.RemoveElementByName(AZ_CRC("ExposeAsInput", 0x0f7879f0));
} }
classElement.RemoveElementByName(AZ_CRC("Exposure", 0x398f29cd));
classElement.RemoveElementByName(AZ_CRC("ExposeAsInput", 0x0f7879f0));
}
return true; return true;
} }
@ -203,8 +203,8 @@ namespace ScriptCanvas
editContext->Class<GraphVariable>("Variable", "Represents a Variable field within a Script Canvas Graph") editContext->Class<GraphVariable>("Variable", "Represents a Variable field within a Script Canvas Graph")
->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Visibility, &GraphVariable::GetVisibility) ->Attribute(AZ::Edit::Attributes::Visibility, &GraphVariable::GetVisibility)
->Attribute(AZ::Edit::Attributes::ChildNameLabelOverride, &GraphVariable::GetDisplayName) ->Attribute(AZ::Edit::Attributes::ChildNameLabelOverride, &GraphVariable::GetVariableName)
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &GraphVariable::GetDisplayName) ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &GraphVariable::GetVariableName)
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &GraphVariable::GetDescriptionOverride) ->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &GraphVariable::GetDescriptionOverride)
->DataElement(AZ::Edit::UIHandlers::ComboBox, &GraphVariable::m_InitialValueSource, "Initial Value Source", "Variables can get their values from within the graph or through component properties.") ->DataElement(AZ::Edit::UIHandlers::ComboBox, &GraphVariable::m_InitialValueSource, "Initial Value Source", "Variables can get their values from within the graph or through component properties.")

@ -1,6 +1,6 @@
/* /*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. * 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 * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
@ -9,10 +9,11 @@
#include <AzCore/Component/EntityUtils.h> #include <AzCore/Component/EntityUtils.h>
#include <AzCore/Serialization/EditContext.h> #include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/Utils.h> #include <AzCore/Serialization/Utils.h>
#include <Libraries/Libraries.h> #include <Libraries/Libraries.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Core/Contract.h> #include <ScriptCanvas/Core/Contract.h>
#include <ScriptCanvas/Core/Graph.h> #include <ScriptCanvas/Core/Graph.h>
#include <ScriptCanvas/Core/Node.h> #include <ScriptCanvas/Core/Node.h>
@ -21,6 +22,7 @@
#include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h> #include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h>
#include <ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.h> #include <ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h> #include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <ScriptCanvas/Serialization/ScriptUserDataSerializer.h>
#include <ScriptCanvas/SystemComponent.h> #include <ScriptCanvas/SystemComponent.h>
#include <ScriptCanvas/Variable/GraphVariableManagerComponent.h> #include <ScriptCanvas/Variable/GraphVariableManagerComponent.h>
@ -53,7 +55,6 @@ namespace ScriptCanvasSystemComponentCpp
namespace ScriptCanvas namespace ScriptCanvas
{ {
void SystemComponent::Reflect(AZ::ReflectContext* context) void SystemComponent::Reflect(AZ::ReflectContext* context)
{ {
Nodeable::Reflect(context); Nodeable::Reflect(context);
@ -83,11 +84,16 @@ namespace ScriptCanvas
} }
} }
if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
{
jsonContext->Serializer<AZ::ScriptUserDataSerializer>()
->HandlesType<RuntimeVariable>();
}
#if defined(SC_EXECUTION_TRACE_ENABLED) #if defined(SC_EXECUTION_TRACE_ENABLED)
ExecutionLogData::Reflect(context); ExecutionLogData::Reflect(context);
ExecutionLogAsset::Reflect(context); ExecutionLogAsset::Reflect(context);
#endif//defined(SC_EXECUTION_TRACE_ENABLED) #endif//defined(SC_EXECUTION_TRACE_ENABLED)
} }
void SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) void SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
@ -144,7 +150,7 @@ namespace ScriptCanvas
ModPerformanceTracker()->CalculateReports(); ModPerformanceTracker()->CalculateReports();
Execution::PerformanceTrackingReport report = ModPerformanceTracker()->GetGlobalReport(); Execution::PerformanceTrackingReport report = ModPerformanceTracker()->GetGlobalReport();
const double ready = aznumeric_caster(report.timing.initializationTime); const double ready = aznumeric_caster(report.timing.initializationTime);
const double instant = aznumeric_caster(report.timing.executionTime); const double instant = aznumeric_caster(report.timing.executionTime);
const double latent = aznumeric_caster(report.timing.latentTime); const double latent = aznumeric_caster(report.timing.latentTime);
@ -357,11 +363,11 @@ namespace ScriptCanvas
auto dataRegistry = ScriptCanvas::GetDataRegistry(); auto dataRegistry = ScriptCanvas::GetDataRegistry();
for (const auto& classIter : behaviorContext->m_classes) for (const auto& classIter : behaviorContext->m_classes)
{ {
auto createability = GetCreatibility(serializeContext, classIter.second); auto createability = GetCreatibility(serializeContext, classIter.second);
if (createability.first != DataRegistry::Createability::None) if (createability.first != DataRegistry::Createability::None)
{ {
dataRegistry->RegisterType(classIter.second->m_typeId, createability.second, createability.first); dataRegistry->RegisterType(classIter.second->m_typeId, createability.second, createability.first);
} }
} }
} }

@ -588,6 +588,8 @@ set(FILES
Include/ScriptCanvas/Profiler/Aggregator.cpp Include/ScriptCanvas/Profiler/Aggregator.cpp
Include/ScriptCanvas/Profiler/DrillerEvents.h Include/ScriptCanvas/Profiler/DrillerEvents.h
Include/ScriptCanvas/Profiler/DrillerEvents.cpp Include/ScriptCanvas/Profiler/DrillerEvents.cpp
Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.h
Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.cpp
Include/ScriptCanvas/Data/DataTrait.cpp Include/ScriptCanvas/Data/DataTrait.cpp
Include/ScriptCanvas/Data/DataTrait.h Include/ScriptCanvas/Data/DataTrait.h
Include/ScriptCanvas/Data/PropertyTraits.cpp Include/ScriptCanvas/Data/PropertyTraits.cpp
@ -620,5 +622,4 @@ set(SKIP_UNITY_BUILD_INCLUSION_FILES
Include/ScriptCanvas/Libraries/Core/FunctionCallNode.h Include/ScriptCanvas/Libraries/Core/FunctionCallNode.h
Include/ScriptCanvas/Libraries/Core/FunctionCallNodeIsOutOfDate.h Include/ScriptCanvas/Libraries/Core/FunctionCallNodeIsOutOfDate.h
Include/ScriptCanvas/Libraries/Core/FunctionCallNodeIsOutOfDate.cpp Include/ScriptCanvas/Libraries/Core/FunctionCallNodeIsOutOfDate.cpp
) )

@ -7,6 +7,8 @@
set(FILES set(FILES
Builder/BuilderSystemComponent.h Builder/BuilderSystemComponent.h
Builder/ScriptCanvasBuilder.cpp
Builder/ScriptCanvasBuilder.h
Builder/ScriptCanvasBuilderComponent.cpp Builder/ScriptCanvasBuilderComponent.cpp
Builder/ScriptCanvasBuilderComponent.h Builder/ScriptCanvasBuilderComponent.h
Builder/ScriptCanvasBuilderWorker.cpp Builder/ScriptCanvasBuilderWorker.cpp

Loading…
Cancel
Save