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_pushliteral(m_lua, "__index");
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_pushcclosure(m_lua, &Internal::Class__Index, 0);
}
lua_rawset(m_lua, -3); 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>
@ -119,7 +119,7 @@ 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())
{ {

@ -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())
@ -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);

@ -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)
{ {
@ -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())
@ -104,7 +173,7 @@ namespace ScriptCanvasEditor
->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
on ScriptCanvas assets.
AZ::Data::AssetInfo assetInfo;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, runtimeAssetId);
if (assetInfo.m_assetType == AZ::Data::s_invalidAssetType)
{ {
AZ_Warning("ScriptCanvas", false, "No ScriptCanvas Runtime Asset information for Entity ('%s' - '%s') Graph ('%s'), asset may be in error or deleted" AZ_Warning("ScriptCanvas", false, "EditorScriptCanvasComponent::BuildGameEntityData failed: %s", parseOutcome.GetError().c_str());
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
return; return;
} }
AzFramework::AssetSystem::AssetStatus statusResult = AzFramework::AssetSystem::AssetStatus_Unknown; auto& variableOverrides = parseOutcome.GetValue();
AzFramework::AssetSystemRequestBus::BroadcastResult(statusResult, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, runtimeAssetId);
if (statusResult != AzFramework::AssetSystem::AssetStatus_Compiled) if (!m_variableOverrides.IsEmpty())
{ {
AZ_Warning("ScriptCanvas", false, "No ScriptCanvas Runtime Asset for Entity ('%s' - '%s') Graph ('%s'), compilation may have failed or not completed" variableOverrides.CopyPreviousOverriddenValues(m_variableOverrides);
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
return;
} }
*/
// #functions2 dependency-ctor-args make recursive m_variableOverrides = parseOutcome.TakeValue();
auto executionComponent = gameEntity->CreateComponent<ScriptCanvas::RuntimeComponent>(runtimeAsset); m_runtimeDataIsValid = true;
ScriptCanvas::VariableData varData; }
for (const auto& varConfig : m_editableData.GetVariables()) void EditorScriptCanvasComponent::BuildGameEntity(AZ::Entity* gameEntity)
{ {
if (varConfig.m_graphVariable.GetDatum()->Empty()) if (!m_runtimeDataIsValid)
{ {
AZ_Error("ScriptCanvas", false, "Data loss detected for GraphVariable ('%s') on Entity ('%s' - '%s') Graph ('%s')" // this is fine, there could have been no graph set, or set to a graph that failed to compile
, varConfig.m_graphVariable.GetVariableName().data() return;
, gameEntity->GetName().c_str()
, GetEntityId().ToString().c_str()
, GetName().c_str());
} }
else
// build everything again as a sanity check against dependencies. All of the variable overrides that were valid will be copied over
BuildGameEntityData();
if (!m_runtimeDataIsValid)
{ {
varData.AddVariable(varConfig.m_graphVariable.GetVariableName(), varConfig.m_graphVariable); AZ_Error("ScriptCanvasBuilder", false, "Runtime information did not build for ScriptCanvas Component using asset: %s", m_scriptCanvasAssetHolder.GetAssetId().ToString<AZStd::string>().c_str());
} return;
} }
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);
} }
} }
@ -468,126 +511,18 @@ namespace ScriptCanvasEditor
void EditorScriptCanvasComponent::OnScriptCanvasAssetReady(const ScriptCanvasMemoryAsset::pointer memoryAsset) void EditorScriptCanvasComponent::OnScriptCanvasAssetReady(const ScriptCanvasMemoryAsset::pointer memoryAsset)
{ {
if (memoryAsset->GetFileAssetId() == m_scriptCanvasAssetHolder.GetAssetId()) if (memoryAsset->GetFileAssetId() == m_scriptCanvasAssetHolder.GetAssetId())
{
LoadVariables(memoryAsset);
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(); auto assetData = memoryAsset->GetAsset();
AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity(); AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity"); AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity");
BuildGameEntityData();
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); AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
UpdateName();
}
} }
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);
@ -55,4 +62,5 @@ namespace ScriptCanvasEditor
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())
{ {
@ -69,7 +85,8 @@ 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, {} });
} }
} }
@ -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,7 +27,6 @@ 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
@ -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,7 +69,7 @@ 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(); }
@ -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;
}; };
} }

@ -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>

@ -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
}; };
} }
@ -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

@ -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
) )
{} {}

@ -5,8 +5,8 @@
* *
*/ */
#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;
} }
} }

@ -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>
@ -205,6 +206,25 @@ namespace ScriptCanvas
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

@ -17,15 +17,55 @@
#include <AzCore/Math/Transform.h> #include <AzCore/Math/Transform.h>
#include <ScriptCanvas/Data/DataRegistry.h> #include <ScriptCanvas/Data/DataRegistry.h>
#include <ScriptCanvas/Core/GraphScopedTypes.h> #include <ScriptCanvas/Core/GraphScopedTypes.h>
#include "DatumBus.h" #include "DatumBus.h"
namespace DatumHelpers namespace DatumHelpers
{ {
enum Version
{
JSONSerializerSupport = 6,
// label your entry above
Current
};
using namespace ScriptCanvas; using namespace ScriptCanvas;
bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootDataElementNode)
{
if (rootDataElementNode.GetVersion() <= Version::JSONSerializerSupport)
{
auto storageElementIndex = rootDataElementNode.FindElement(AZ_CRC_CE("m_datumStorage"));
if (storageElementIndex == -1)
{
AZ_Error("ScriptCanvas", false, "Datum Version conversion failed: 'm_datumStorage' was missing.");
return false;
}
auto& storageElement = rootDataElementNode.GetSubElement(storageElementIndex);
AZStd::any previousStorage;
if (!storageElement.GetData(previousStorage))
{
AZ_Error("ScriptCanvas", false, "Datum Version conversion failed: Could not retrieve old version of 'm_datumStorage'.");
return false;
}
rootDataElementNode.RemoveElement(storageElementIndex);
RuntimeVariable newStorage(previousStorage);
if (!rootDataElementNode.AddElementWithData(context, "m_datumStorage", newStorage))
{
AZ_Error("ScriptCanvas", false, "Datum Version conversion failed: Could not add new version of 'm_datumStorage'.");
return false;
}
}
return true;
}
template<typename t_Value> template<typename t_Value>
struct ImplicitConversionHelp struct ImplicitConversionHelp
{ {
@ -169,7 +209,7 @@ namespace DatumHelpers
} }
else if (typeID == azrtti_typeid<AZ::Vector2>()) else if (typeID == azrtti_typeid<AZ::Vector2>())
{ {
target = BehaviorContextObject::Create<AZ::Vector2>(AZ::Vector2(static_cast<float>(sourceVector.GetX()), static_cast<float>(sourceVector.GetY())), behaviorClass); target = BehaviorContextObject::Create<AZ::Vector2>(AZ::Vector2((sourceVector.GetX()), (sourceVector.GetY())), behaviorClass);
} }
else if (typeID == azrtti_typeid<AZ::Vector4>()) else if (typeID == azrtti_typeid<AZ::Vector4>())
{ {
@ -224,7 +264,7 @@ namespace DatumHelpers
} }
else if (typeID == azrtti_typeid<AZ::Vector2>()) else if (typeID == azrtti_typeid<AZ::Vector2>())
{ {
target = BehaviorContextObject::Create<AZ::Vector2>(AZ::Vector2(static_cast<float>(sourceVector.GetX()), static_cast<float>(sourceVector.GetY())), behaviorClass); target = BehaviorContextObject::Create<AZ::Vector2>(AZ::Vector2((sourceVector.GetX()), (sourceVector.GetY())), behaviorClass);
} }
else if (typeID == azrtti_typeid<AZ::Vector4>()) else if (typeID == azrtti_typeid<AZ::Vector4>())
{ {
@ -1153,7 +1193,7 @@ namespace DatumHelpers
if (parameterDesc.m_typeId == azrtti_typeid<char>() && (parameterDesc.m_traits & (AZ::BehaviorParameter::TR_POINTER | AZ::BehaviorParameter::TR_CONST))) if (parameterDesc.m_typeId == azrtti_typeid<char>() && (parameterDesc.m_traits & (AZ::BehaviorParameter::TR_POINTER | AZ::BehaviorParameter::TR_CONST)))
{ {
AZStd::string_view parameterString = *reinterpret_cast<const char* const *>(source); AZStd::string_view parameterString = *reinterpret_cast<const char* const*>(source);
return AZ::Success(AZStd::string(parameterString)); return AZ::Success(AZStd::string(parameterString));
} }
else if (parameterDesc.m_typeId == azrtti_typeid<AZStd::string_view>()) else if (parameterDesc.m_typeId == azrtti_typeid<AZStd::string_view>())
@ -1161,7 +1201,7 @@ namespace DatumHelpers
const AZStd::string_view* parameterString = nullptr; const AZStd::string_view* parameterString = nullptr;
if (parameterDesc.m_traits & AZ::BehaviorParameter::TR_POINTER) if (parameterDesc.m_traits & AZ::BehaviorParameter::TR_POINTER)
{ {
parameterString = *reinterpret_cast<const AZStd::string_view* const *>(source); parameterString = *reinterpret_cast<const AZStd::string_view* const*>(source);
} }
else else
{ {
@ -1227,7 +1267,7 @@ namespace ScriptCanvas
Datum::Datum(const AZ::BehaviorValueParameter& value) Datum::Datum(const AZ::BehaviorValueParameter& value)
: Datum(value, : Datum(value,
!(value.m_traits & (AZ::BehaviorParameter::TR_POINTER | AZ::BehaviorParameter::TR_REFERENCE)) ? eOriginality::Original : eOriginality::Copy, !(value.m_traits& (AZ::BehaviorParameter::TR_POINTER | AZ::BehaviorParameter::TR_REFERENCE)) ? eOriginality::Original : eOriginality::Copy,
value.m_value) value.m_value)
{ {
} }
@ -1268,15 +1308,15 @@ namespace ScriptCanvas
if (classIter != behaviorContext->m_typeToClassMap.end()) if (classIter != behaviorContext->m_typeToClassMap.end())
{ {
BehaviorContextObjectPtr sourceObjectPtr = (*AZStd::any_cast<BehaviorContextObjectPtr>(&source.m_storage)); BehaviorContextObjectPtr sourceObjectPtr = (*AZStd::any_cast<BehaviorContextObjectPtr>(&source.m_storage.value));
BehaviorContextObjectPtr newObjectPtr = sourceObjectPtr->CloneObject((*classIter->second)); BehaviorContextObjectPtr newObjectPtr = sourceObjectPtr->CloneObject((*classIter->second));
m_storage = AZStd::move(newObjectPtr); m_storage.value = AZStd::move(newObjectPtr);
BehaviorContextObjectPtr newSourceObjectPtr = (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage)); BehaviorContextObjectPtr newSourceObjectPtr = (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage.value));
} }
} }
else else
{ {
m_storage = source.m_storage; m_storage.value = source.m_storage.value;
m_conversionStorage = source.m_conversionStorage; m_conversionStorage = source.m_conversionStorage;
} }
@ -1339,7 +1379,7 @@ namespace ScriptCanvas
void Datum::Clear() void Datum::Clear()
{ {
m_storage.clear(); m_storage.value.clear();
m_class = nullptr; m_class = nullptr;
m_type = Data::Type::Invalid(); m_type = Data::Type::Invalid();
} }
@ -1352,12 +1392,12 @@ namespace ScriptCanvas
{ {
if (m_pointer) if (m_pointer)
{ {
DatumHelpers::FromBehaviorContextNumber(resultType.m_typeId, m_pointer, m_storage); DatumHelpers::FromBehaviorContextNumber(resultType.m_typeId, m_pointer, m_storage.value);
} }
} }
else else
{ {
DatumHelpers::FromBehaviorContextNumber(resultType.m_typeId, reinterpret_cast<const void*>(&m_conversionStorage), m_storage); DatumHelpers::FromBehaviorContextNumber(resultType.m_typeId, reinterpret_cast<const void*>(&m_conversionStorage), m_storage.value);
} }
} }
else if (IS_A(Data::Type::String()) && !Data::IsString(resultType.m_typeId) && AZ::BehaviorContextHelper::IsStringParameter(resultType)) else if (IS_A(Data::Type::String()) && !Data::IsString(resultType.m_typeId) && AZ::BehaviorContextHelper::IsStringParameter(resultType))
@ -1365,7 +1405,7 @@ namespace ScriptCanvas
void* storageAddress = (resultType.m_traits & AZ::BehaviorParameter::TR_POINTER) ? reinterpret_cast<void*>(&m_pointer) : AZStd::any_cast<void>(&m_conversionStorage); void* storageAddress = (resultType.m_traits & AZ::BehaviorParameter::TR_POINTER) ? reinterpret_cast<void*>(&m_pointer) : AZStd::any_cast<void>(&m_conversionStorage);
if (auto stringOutcome = DatumHelpers::ConvertBehaviorContextString(resultType, storageAddress)) if (auto stringOutcome = DatumHelpers::ConvertBehaviorContextString(resultType, storageAddress))
{ {
m_storage = stringOutcome.GetValue(); m_storage.value = stringOutcome.GetValue();
} }
} }
else if (m_type.GetType() == Data::eType::BehaviorContextObject else if (m_type.GetType() == Data::eType::BehaviorContextObject
@ -1373,7 +1413,7 @@ namespace ScriptCanvas
{ {
if (m_pointer) if (m_pointer)
{ {
m_storage = BehaviorContextObject::CreateReference(resultType.m_typeId, m_pointer); m_storage.value = BehaviorContextObject::CreateReference(resultType.m_typeId, m_pointer);
} }
} }
} }
@ -1388,58 +1428,58 @@ namespace ScriptCanvas
switch (m_type.GetType()) switch (m_type.GetType())
{ {
case ScriptCanvas::Data::eType::AABB: case ScriptCanvas::Data::eType::AABB:
return DatumHelpers::FromBehaviorContextAABB(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextAABB(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::BehaviorContextObject: case ScriptCanvas::Data::eType::BehaviorContextObject:
return FromBehaviorContextObject(m_class, source); return FromBehaviorContextObject(m_class, source);
case ScriptCanvas::Data::eType::Boolean: case ScriptCanvas::Data::eType::Boolean:
return DatumHelpers::FromBehaviorContextBool(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextBool(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Color: case ScriptCanvas::Data::eType::Color:
return DatumHelpers::FromBehaviorContextColor(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextColor(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::CRC: case ScriptCanvas::Data::eType::CRC:
return DatumHelpers::FromBehaviorContextCRC(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextCRC(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::EntityID: case ScriptCanvas::Data::eType::EntityID:
return DatumHelpers::FromBehaviorContextEntityID(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextEntityID(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Matrix3x3: case ScriptCanvas::Data::eType::Matrix3x3:
return DatumHelpers::FromBehaviorContextMatrix3x3(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextMatrix3x3(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Matrix4x4: case ScriptCanvas::Data::eType::Matrix4x4:
return DatumHelpers::FromBehaviorContextMatrix4x4(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextMatrix4x4(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Number: case ScriptCanvas::Data::eType::Number:
return DatumHelpers::FromBehaviorContextNumber(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextNumber(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::OBB: case ScriptCanvas::Data::eType::OBB:
return DatumHelpers::FromBehaviorContextOBB(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextOBB(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Plane: case ScriptCanvas::Data::eType::Plane:
return DatumHelpers::FromBehaviorContextPlane(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextPlane(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Quaternion: case ScriptCanvas::Data::eType::Quaternion:
return DatumHelpers::FromBehaviorContextQuaternion(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextQuaternion(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::String: case ScriptCanvas::Data::eType::String:
return DatumHelpers::FromBehaviorContextString(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextString(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Transform: case ScriptCanvas::Data::eType::Transform:
return DatumHelpers::FromBehaviorContextTransform(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextTransform(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Vector2: case ScriptCanvas::Data::eType::Vector2:
return DatumHelpers::FromBehaviorContextVector2(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextVector2(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Vector3: case ScriptCanvas::Data::eType::Vector3:
return DatumHelpers::FromBehaviorContextVector3(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextVector3(typeID, source, m_storage.value);
case ScriptCanvas::Data::eType::Vector4: case ScriptCanvas::Data::eType::Vector4:
return DatumHelpers::FromBehaviorContextVector4(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextVector4(typeID, source, m_storage.value);
} }
} }
else if (DatumHelpers::ConvertImplicitlyChecked(type, source, m_type, m_storage, m_class)) else if (DatumHelpers::ConvertImplicitlyChecked(type, source, m_type, m_storage.value, m_class))
{ {
return true; return true;
} }
@ -1455,14 +1495,14 @@ namespace ScriptCanvas
bool Datum::FromBehaviorContextNumber(const void* source, const AZ::Uuid& typeID) bool Datum::FromBehaviorContextNumber(const void* source, const AZ::Uuid& typeID)
{ {
return DatumHelpers::FromBehaviorContextNumber(typeID, source, m_storage); return DatumHelpers::FromBehaviorContextNumber(typeID, source, m_storage.value);
} }
bool Datum::FromBehaviorContextObject(const AZ::BehaviorClass* behaviorClass, const void* source) bool Datum::FromBehaviorContextObject(const AZ::BehaviorClass* behaviorClass, const void* source)
{ {
if (behaviorClass) if (behaviorClass)
{ {
m_storage = BehaviorContextObject::CreateReference(behaviorClass->m_typeId, const_cast<void*>(source)); m_storage.value = BehaviorContextObject::CreateReference(behaviorClass->m_typeId, const_cast<void*>(source));
return true; return true;
} }
@ -1471,10 +1511,10 @@ namespace ScriptCanvas
const void* Datum::GetValueAddress() const const void* Datum::GetValueAddress() const
{ {
return !m_storage.empty() return !m_storage.value.empty()
? m_type.GetType() != Data::eType::BehaviorContextObject ? m_type.GetType() != Data::eType::BehaviorContextObject
? AZStd::any_cast<void>(&m_storage) ? AZStd::any_cast<void>(&m_storage.value)
: (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage))->Get() : (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage.value))->Get()
: nullptr; : nullptr;
} }
@ -1554,13 +1594,13 @@ namespace ScriptCanvas
bool Datum::InitializeAABB(const void* source) bool Datum::InitializeAABB(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::AABBType*>(source) : Data::Traits<Data::AABBType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::AABBType*>(source) : Data::Traits<Data::AABBType>::GetDefault();
return true; return true;
} }
bool Datum::InitializeAssetId(const void* source) bool Datum::InitializeAssetId(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::AssetIdType*>(source) : Data::Traits<Data::AssetIdType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::AssetIdType*>(source) : Data::Traits<Data::AssetIdType>::GetDefault();
return true; return true;
} }
@ -1621,11 +1661,11 @@ namespace ScriptCanvas
if (m_originality == eOriginality::Original) if (m_originality == eOriginality::Original)
{ {
m_storage = BehaviorContextObject::Create(behaviorClass, source); m_storage.value = BehaviorContextObject::Create(behaviorClass, source);
} }
else else
{ {
m_storage = BehaviorContextObject::CreateReference(behaviorClass.m_typeId, const_cast<void*>(source)); m_storage.value = BehaviorContextObject::CreateReference(behaviorClass.m_typeId, const_cast<void*>(source));
} }
return true; return true;
@ -1636,55 +1676,55 @@ namespace ScriptCanvas
bool Datum::InitializeBool(const void* source) bool Datum::InitializeBool(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::BooleanType*>(source) : Data::Traits<Data::BooleanType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::BooleanType*>(source) : Data::Traits<Data::BooleanType>::GetDefault();
return true; return true;
} }
bool Datum::InitializeColor(const void* source) bool Datum::InitializeColor(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::ColorType*>(source) : Data::Traits<Data::ColorType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::ColorType*>(source) : Data::Traits<Data::ColorType>::GetDefault();
return true; return true;
} }
bool Datum::InitializeCRC(const void* source) bool Datum::InitializeCRC(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::CRCType*>(source) : Data::Traits<Data::CRCType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::CRCType*>(source) : Data::Traits<Data::CRCType>::GetDefault();
return true; return true;
} }
bool Datum::InitializeEntityID(const void* source) bool Datum::InitializeEntityID(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::EntityIDType*>(source) : Data::Traits<Data::EntityIDType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::EntityIDType*>(source) : Data::Traits<Data::EntityIDType>::GetDefault();
return true; return true;
} }
bool Datum::InitializeNamedEntityID(const void* source) bool Datum::InitializeNamedEntityID(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::NamedEntityIDType*>(source) : Data::Traits<Data::NamedEntityIDType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::NamedEntityIDType*>(source) : Data::Traits<Data::NamedEntityIDType>::GetDefault();
return true; return true;
} }
bool Datum::InitializeMatrix3x3(const void* source) bool Datum::InitializeMatrix3x3(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::Matrix3x3Type*>(source) : Data::Traits<Data::Matrix3x3Type>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::Matrix3x3Type*>(source) : Data::Traits<Data::Matrix3x3Type>::GetDefault();
return true; return true;
} }
bool Datum::InitializeMatrix4x4(const void* source) bool Datum::InitializeMatrix4x4(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::Matrix4x4Type*>(source) : Data::Traits<Data::Matrix4x4Type>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::Matrix4x4Type*>(source) : Data::Traits<Data::Matrix4x4Type>::GetDefault();
return true; return true;
} }
bool Datum::InitializeNumber(const void* source, const AZ::Uuid& sourceTypeID) bool Datum::InitializeNumber(const void* source, const AZ::Uuid& sourceTypeID)
{ {
m_storage = Data::Traits<Data::NumberType>::GetDefault(); m_storage.value = Data::Traits<Data::NumberType>::GetDefault();
return (source && DatumHelpers::FromBehaviorContextNumber(sourceTypeID, source, m_storage)) || true; return (source && DatumHelpers::FromBehaviorContextNumber(sourceTypeID, source, m_storage.value)) || true;
} }
bool Datum::InitializeOBB(const void* source) bool Datum::InitializeOBB(const void* source)
{ {
m_storage = source m_storage.value = source
? *reinterpret_cast<const Data::OBBType*>(source) ? *reinterpret_cast<const Data::OBBType*>(source)
: Data::Traits<Data::OBBType>::GetDefault(); : Data::Traits<Data::OBBType>::GetDefault();
return true; return true;
@ -1692,12 +1732,12 @@ namespace ScriptCanvas
bool Datum::InitializePlane(const void* source) bool Datum::InitializePlane(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::PlaneType*>(source) : Data::Traits<Data::PlaneType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::PlaneType*>(source) : Data::Traits<Data::PlaneType>::GetDefault();
return true; return true;
} }
bool Datum::InitializeQuaternion(const void* source) bool Datum::InitializeQuaternion(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::QuaternionType*>(source) : Data::Traits<Data::QuaternionType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::QuaternionType*>(source) : Data::Traits<Data::QuaternionType>::GetDefault();
return true; return true;
} }
@ -1707,49 +1747,49 @@ namespace ScriptCanvas
{ {
if (sourceTypeID == azrtti_typeid<AZStd::string_view>()) if (sourceTypeID == azrtti_typeid<AZStd::string_view>())
{ {
m_storage = Data::StringType(*reinterpret_cast<const AZStd::string_view*>(source)); m_storage.value = Data::StringType(*reinterpret_cast<const AZStd::string_view*>(source));
} }
else if (sourceTypeID == azrtti_typeid<char>()) else if (sourceTypeID == azrtti_typeid<char>())
{ {
m_storage = Data::StringType(reinterpret_cast<const char*>(source)); m_storage.value = Data::StringType(reinterpret_cast<const char*>(source));
} }
else else
{ {
m_storage = *reinterpret_cast<const Data::StringType*>(source); m_storage.value = *reinterpret_cast<const Data::StringType*>(source);
} }
} }
else else
{ {
m_storage = Data::Traits<Data::StringType>::GetDefault(); m_storage.value = Data::Traits<Data::StringType>::GetDefault();
} }
return true; return true;
} }
bool Datum::InitializeTransform(const void* source) bool Datum::InitializeTransform(const void* source)
{ {
m_storage = source ? *reinterpret_cast<const Data::TransformType*>(source) : Data::Traits<Data::TransformType>::GetDefault(); m_storage.value = source ? *reinterpret_cast<const Data::TransformType*>(source) : Data::Traits<Data::TransformType>::GetDefault();
return true; return true;
} }
bool Datum::InitializeVector2(const void* source, const AZ::Uuid& sourceTypeID) bool Datum::InitializeVector2(const void* source, const AZ::Uuid& sourceTypeID)
{ {
m_storage = Data::Traits<Data::Vector2Type>::GetDefault(); m_storage.value = Data::Traits<Data::Vector2Type>::GetDefault();
// return a success regardless, but do the initialization first if source is not null // return a success regardless, but do the initialization first if source is not null
return (source && DatumHelpers::FromBehaviorContextVector2(sourceTypeID, source, m_storage)) || true; return (source && DatumHelpers::FromBehaviorContextVector2(sourceTypeID, source, m_storage.value)) || true;
} }
bool Datum::InitializeVector3(const void* source, const AZ::Uuid& sourceTypeID) bool Datum::InitializeVector3(const void* source, const AZ::Uuid& sourceTypeID)
{ {
m_storage = Data::Traits<Data::Vector3Type>::GetDefault(); m_storage.value = Data::Traits<Data::Vector3Type>::GetDefault();
// return a success regardless, but do the initialization first if source is not null // return a success regardless, but do the initialization first if source is not null
return (source && DatumHelpers::FromBehaviorContextVector3(sourceTypeID, source, m_storage)) || true; return (source && DatumHelpers::FromBehaviorContextVector3(sourceTypeID, source, m_storage.value)) || true;
} }
bool Datum::InitializeVector4(const void* source, const AZ::Uuid& sourceTypeID) bool Datum::InitializeVector4(const void* source, const AZ::Uuid& sourceTypeID)
{ {
m_storage = Data::Traits<Data::Vector4Type>::GetDefault(); m_storage.value = Data::Traits<Data::Vector4Type>::GetDefault();
// return a success regardless, but do the initialization first if source is not null // return a success regardless, but do the initialization first if source is not null
return (source && DatumHelpers::FromBehaviorContextVector4(sourceTypeID, source, m_storage)) || true; return (source && DatumHelpers::FromBehaviorContextVector4(sourceTypeID, source, m_storage.value)) || true;
} }
void Datum::SetType(const Data::Type& dataType) void Datum::SetType(const Data::Type& dataType)
@ -1787,7 +1827,7 @@ namespace ScriptCanvas
auto dataTraitIt = typeIdTraitMap.find(m_type.GetType()); auto dataTraitIt = typeIdTraitMap.find(m_type.GetType());
if (dataTraitIt != typeIdTraitMap.end()) if (dataTraitIt != typeIdTraitMap.end())
{ {
return dataTraitIt->second.m_dataTraits.IsDefault(m_storage, m_type); return dataTraitIt->second.m_dataTraits.IsDefault(m_storage.value, m_type);
} }
AZ_Error("Script Canvas", m_isOverloadedStorage, "Unsupported ScriptCanvas Data type"); AZ_Error("Script Canvas", m_isOverloadedStorage, "Unsupported ScriptCanvas Data type");
@ -1797,8 +1837,8 @@ namespace ScriptCanvas
void* Datum::ModResultAddress() void* Datum::ModResultAddress()
{ {
return m_type.GetType() != Data::eType::BehaviorContextObject return m_type.GetType() != Data::eType::BehaviorContextObject
? AZStd::any_cast<void>(&m_storage) ? AZStd::any_cast<void>(&m_storage.value)
: (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage))->Mod(); : (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage.value))->Mod();
} }
void* Datum::ModValueAddress() const void* Datum::ModValueAddress() const
@ -1821,12 +1861,12 @@ namespace ScriptCanvas
InitializeOverloadedStorage(source.m_type, m_originality); InitializeOverloadedStorage(source.m_type, m_originality);
m_class = AZStd::move(source.m_class); m_class = AZStd::move(source.m_class);
m_type = AZStd::move(source.m_type); m_type = AZStd::move(source.m_type);
if (!source.m_storage.empty()) if (!source.m_storage.value.empty())
{ {
m_storage = AZStd::move(source.m_storage); m_storage.value = AZStd::move(source.m_storage.value);
} }
} }
else if (!DatumHelpers::ConvertImplicitlyChecked(source.GetType(), source.GetValueAddress(), m_type, m_storage, m_class)) else if (!DatumHelpers::ConvertImplicitlyChecked(source.GetType(), source.GetValueAddress(), m_type, m_storage.value, m_class))
{ {
AZ_Error("Script Canvas", false, "Failed to convert from %s to %s", GetName(source.GetType()).c_str(), GetName(m_type).c_str()); AZ_Error("Script Canvas", false, "Failed to convert from %s to %s", GetName(source.GetType()).c_str(), GetName(m_type).c_str());
} }
@ -1852,9 +1892,9 @@ namespace ScriptCanvas
InitializeOverloadedStorage(source.m_type, m_originality); InitializeOverloadedStorage(source.m_type, m_originality);
m_class = source.m_class; m_class = source.m_class;
m_type = source.m_type; m_type = source.m_type;
m_storage = source.m_storage; m_storage.value = source.m_storage.value;
} }
else if (!DatumHelpers::ConvertImplicitlyChecked(source.GetType(), source.GetValueAddress(), m_type, m_storage, m_class)) else if (!DatumHelpers::ConvertImplicitlyChecked(source.GetType(), source.GetValueAddress(), m_type, m_storage.value, m_class))
{ {
AZ_Error("Script Canvas", false, "Failed to convert from %s to %s", GetName(source.GetType()).c_str(), GetName(m_type).c_str()); AZ_Error("Script Canvas", false, "Failed to convert from %s to %s", GetName(source.GetType()).c_str(), GetName(m_type).c_str());
} }
@ -2028,7 +2068,7 @@ namespace ScriptCanvas
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection)) if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
{ {
serializeContext->Class<Datum>() serializeContext->Class<Datum>()
->Version(6) ->Version(DatumHelpers::Version::Current, &DatumHelpers::VersionConverter)
->EventHandler<SerializeContextEventHandler>() ->EventHandler<SerializeContextEventHandler>()
->Field("m_isUntypedStorage", &Datum::m_isOverloadedStorage) ->Field("m_isUntypedStorage", &Datum::m_isOverloadedStorage)
->Field("m_type", &Datum::m_type) ->Field("m_type", &Datum::m_type)
@ -2079,7 +2119,7 @@ namespace ScriptCanvas
auto dataTraitIt = typeIdTraitMap.find(m_type.GetType()); auto dataTraitIt = typeIdTraitMap.find(m_type.GetType());
if (dataTraitIt != typeIdTraitMap.end()) if (dataTraitIt != typeIdTraitMap.end())
{ {
m_storage = dataTraitIt->second.m_dataTraits.GetDefault(m_type); m_storage.value = dataTraitIt->second.m_dataTraits.GetDefault(m_type);
} }
else else
{ {
@ -2129,12 +2169,12 @@ namespace ScriptCanvas
{ {
if (m_type.GetType() == Data::eType::BehaviorContextObject) if (m_type.GetType() == Data::eType::BehaviorContextObject)
{ {
BehaviorContextObjectPtr ptr = (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage)); BehaviorContextObjectPtr ptr = (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage.value));
return ptr->ToAny(); return ptr->ToAny();
} }
else else
{ {
return m_storage; return m_storage.value;
} }
} }
@ -2148,7 +2188,7 @@ namespace ScriptCanvas
const auto targetType = Data::FromAZType(destination.m_typeId); const auto targetType = Data::FromAZType(destination.m_typeId);
const bool success = const bool success =
( (IS_A(targetType) || IsConvertibleTo(targetType)) || (IS_A(Data::Type::String()) && AZ::BehaviorContextHelper::IsStringParameter(destination)) ) ((IS_A(targetType) || IsConvertibleTo(targetType)) || (IS_A(Data::Type::String()) && AZ::BehaviorContextHelper::IsStringParameter(destination)))
&& DatumHelpers::ToBehaviorContext(m_type, GetValueAddress(), destination, destinationBehaviorClass); && DatumHelpers::ToBehaviorContext(m_type, GetValueAddress(), destination, destinationBehaviorClass);
AZ_Error("Script Canvas", success, "Cannot push Datum with type %s into BehaviorValueParameter expecting type %s", GetName(m_type).c_str(), GetName(targetType).c_str()); AZ_Error("Script Canvas", success, "Cannot push Datum with type %s into BehaviorValueParameter expecting type %s", GetName(m_type).c_str(), GetName(targetType).c_str());
@ -2426,7 +2466,7 @@ namespace ScriptCanvas
AZStd::string Datum::ToStringAABB(const Data::AABBType& aabb) const AZStd::string Datum::ToStringAABB(const Data::AABBType& aabb) const
{ {
return AZStd::string::format return AZStd::string::format
( "(Min: %s, Max: %s)" ("(Min: %s, Max: %s)"
, ToStringVector3(aabb.GetMin()).c_str() , ToStringVector3(aabb.GetMin()).c_str()
, ToStringVector3(aabb.GetMax()).c_str()); , ToStringVector3(aabb.GetMax()).c_str());
} }
@ -2438,7 +2478,7 @@ namespace ScriptCanvas
AZStd::string Datum::ToStringColor(const Data::ColorType& c) const AZStd::string Datum::ToStringColor(const Data::ColorType& c) const
{ {
return AZStd::string::format("(r=%.7f,g=%.7f,b=%.7f,a=%.7f)", static_cast<float>(c.GetR()), static_cast<float>(c.GetG()), static_cast<float>(c.GetB()), static_cast<float>(c.GetA())); return AZStd::string::format("(r=%.7f,g=%.7f,b=%.7f,a=%.7f)", (c.GetR()), (c.GetG()), (c.GetB()), (c.GetA()));
} }
bool Datum::ToStringBehaviorClassObject(Data::StringType& stringOut) const bool Datum::ToStringBehaviorClassObject(Data::StringType& stringOut) const
@ -2474,7 +2514,7 @@ namespace ScriptCanvas
AZStd::string Datum::ToStringMatrix3x3(const AZ::Matrix3x3& m) const AZStd::string Datum::ToStringMatrix3x3(const AZ::Matrix3x3& m) const
{ {
return AZStd::string::format return AZStd::string::format
( "(%s, %s, %s)" ("(%s, %s, %s)"
, ToStringVector3(m.GetColumn(0)).c_str() , ToStringVector3(m.GetColumn(0)).c_str()
, ToStringVector3(m.GetColumn(1)).c_str() , ToStringVector3(m.GetColumn(1)).c_str()
, ToStringVector3(m.GetColumn(2)).c_str()); , ToStringVector3(m.GetColumn(2)).c_str());
@ -2484,7 +2524,7 @@ namespace ScriptCanvas
AZStd::string Datum::ToStringMatrix4x4(const AZ::Matrix4x4& m) const AZStd::string Datum::ToStringMatrix4x4(const AZ::Matrix4x4& m) const
{ {
return AZStd::string::format return AZStd::string::format
( "(%s, %s, %s, %s)" ("(%s, %s, %s, %s)"
, ToStringVector4(m.GetColumn(0)).c_str() , ToStringVector4(m.GetColumn(0)).c_str()
, ToStringVector4(m.GetColumn(1)).c_str() , ToStringVector4(m.GetColumn(1)).c_str()
, ToStringVector4(m.GetColumn(2)).c_str() , ToStringVector4(m.GetColumn(2)).c_str()
@ -2495,7 +2535,7 @@ namespace ScriptCanvas
AZStd::string Datum::ToStringOBB(const Data::OBBType& obb) const AZStd::string Datum::ToStringOBB(const Data::OBBType& obb) const
{ {
return AZStd::string::format return AZStd::string::format
( "(Position: %s, AxisX: %s, AxisY: %s, AxisZ: %s, halfLengthX: %.7f, halfLengthY: %.7f, halfLengthZ: %.7f)" ("(Position: %s, AxisX: %s, AxisY: %s, AxisZ: %s, halfLengthX: %.7f, halfLengthY: %.7f, halfLengthZ: %.7f)"
, ToStringVector3(obb.GetPosition()).c_str() , ToStringVector3(obb.GetPosition()).c_str()
, ToStringVector3(obb.GetAxisX()).c_str() , ToStringVector3(obb.GetAxisX()).c_str()
, ToStringVector3(obb.GetAxisY()).c_str() , ToStringVector3(obb.GetAxisY()).c_str()
@ -2514,10 +2554,10 @@ namespace ScriptCanvas
{ {
AZ::Vector3 eulerRotation = AZ::ConvertTransformToEulerDegrees(AZ::Transform::CreateFromQuaternion(source)); AZ::Vector3 eulerRotation = AZ::ConvertTransformToEulerDegrees(AZ::Transform::CreateFromQuaternion(source));
return AZStd::string::format return AZStd::string::format
( "(Pitch: %5.2f, Roll: %5.2f, Yaw: %5.2f)" ("(Pitch: %5.2f, Roll: %5.2f, Yaw: %5.2f)"
, static_cast<float>(eulerRotation.GetX()) , (eulerRotation.GetX())
, static_cast<float>(eulerRotation.GetY()) , (eulerRotation.GetY())
, static_cast<float>(eulerRotation.GetZ())); , (eulerRotation.GetZ()));
} }
AZStd::string Datum::ToStringTransform(const Data::TransformType& source) const AZStd::string Datum::ToStringTransform(const Data::TransformType& source) const
@ -2527,18 +2567,18 @@ namespace ScriptCanvas
float scale = copy.ExtractUniformScale(); float scale = copy.ExtractUniformScale();
AZ::Vector3 rotation = AZ::ConvertTransformToEulerDegrees(copy); AZ::Vector3 rotation = AZ::ConvertTransformToEulerDegrees(copy);
return AZStd::string::format return AZStd::string::format
( "(Position: X: %f, Y: %f, Z: %f," ("(Position: X: %f, Y: %f, Z: %f,"
" Rotation: X: %f, Y: %f, Z: %f," " Rotation: X: %f, Y: %f, Z: %f,"
" Scale: %f)" " Scale: %f)"
, static_cast<float>(pos.GetX()), static_cast<float>(pos.GetY()), static_cast<float>(pos.GetZ()) , (pos.GetX()), (pos.GetY()), (pos.GetZ())
, static_cast<float>(rotation.GetX()), static_cast<float>(rotation.GetY()), static_cast<float>(rotation.GetZ()) , (rotation.GetX()), (rotation.GetY()), (rotation.GetZ())
, scale); , scale);
} }
AZStd::string Datum::ToStringVector2(const AZ::Vector2& source) const AZStd::string Datum::ToStringVector2(const AZ::Vector2& source) const
{ {
return AZStd::string::format return AZStd::string::format
( "(X: %f, Y: %f)" ("(X: %f, Y: %f)"
, source.GetX() , source.GetX()
, source.GetY()); , source.GetY());
} }
@ -2546,20 +2586,20 @@ namespace ScriptCanvas
AZStd::string Datum::ToStringVector3(const AZ::Vector3& source) const AZStd::string Datum::ToStringVector3(const AZ::Vector3& source) const
{ {
return AZStd::string::format return AZStd::string::format
( "(X: %f, Y: %f, Z: %f)" ("(X: %f, Y: %f, Z: %f)"
, static_cast<float>(source.GetX()) , (source.GetX())
, static_cast<float>(source.GetY()) , (source.GetY())
, static_cast<float>(source.GetZ())); , (source.GetZ()));
} }
AZStd::string Datum::ToStringVector4(const AZ::Vector4& source) const AZStd::string Datum::ToStringVector4(const AZ::Vector4& source) const
{ {
return AZStd::string::format return AZStd::string::format
("(X: %f, Y: %f, Z: %f, W: %f)" ("(X: %f, Y: %f, Z: %f, W: %f)"
, static_cast<float>(source.GetX()) , (source.GetX())
, static_cast<float>(source.GetY()) , (source.GetY())
, static_cast<float>(source.GetZ()) , (source.GetZ())
, static_cast<float>(source.GetW())); , (source.GetW()));
} }
AZ::Outcome<void, AZStd::string> Datum::CallBehaviorContextMethod(const AZ::BehaviorMethod* method, AZ::BehaviorValueParameter* params, unsigned int numExpectedArgs) AZ::Outcome<void, AZStd::string> Datum::CallBehaviorContextMethod(const AZ::BehaviorMethod* method, AZ::BehaviorValueParameter* params, unsigned int numExpectedArgs)
@ -2608,5 +2648,4 @@ namespace ScriptCanvas
{ {
return datum != nullptr && !datum->Empty(); return datum != nullptr && !datum->Empty();
} }
} }

@ -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>
@ -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;
@ -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

@ -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();
}
} }
} }
@ -1036,10 +1030,10 @@ namespace ScriptCanvas
} }
} }
// for (auto connectionId : removableConnections) // for (auto connectionId : removableConnections)
// { // {
// DisconnectById(connectionId); // DisconnectById(connectionId);
// } // }
if (!removableConnections.empty()) if (!removableConnections.empty())
{ {

@ -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;

@ -7,6 +7,7 @@
#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,21 +38,25 @@ 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;
@ -60,74 +65,45 @@ namespace ScriptCanvas
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;
} }
} }

@ -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,13 +22,13 @@ 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
@ -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);

@ -34,16 +34,16 @@ namespace ScriptCanvas
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:
@ -54,7 +54,7 @@ namespace ScriptCanvas
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,6 +92,8 @@ 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)

@ -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;

@ -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,7 +386,6 @@ 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
@ -399,7 +396,6 @@ namespace ScriptCanvas
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
@ -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);
} }
@ -721,5 +716,4 @@ namespace ScriptCanvas
return Unpack(lua, constructionArgs); return Unpack(lua, constructionArgs);
} }
} }
} }

@ -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;
@ -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;
} }
} }

@ -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
; ;
} }
} }
} }

@ -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);

@ -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
@ -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());
} }
} }

@ -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;
}; };
} }

@ -7,6 +7,7 @@
#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,7 +42,7 @@ 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;
@ -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
@ -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,7 +767,7 @@ 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)
{ {
@ -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;
} }
@ -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,7 +1259,7 @@ 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;
} }
@ -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)
@ -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())));
} }
@ -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)
@ -2629,7 +2646,7 @@ 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
@ -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; });
@ -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);
} }
} }
@ -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))
@ -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
@ -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()));
} }
@ -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));
} }
@ -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();
} }
@ -5342,7 +5388,5 @@ namespace ScriptCanvas
{ {
return type == Data::eType::BehaviorContextObject; return type == Data::eType::BehaviorContextObject;
} }
} }
} }

@ -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;
@ -150,8 +150,6 @@ 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;
@ -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);
@ -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);
@ -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;
@ -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;
} }
} }
} }

@ -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
{ {
@ -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";
} }
@ -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; });
@ -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();

@ -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);
@ -204,5 +208,4 @@ namespace ScriptCanvas
void TraverseTree(const ExecutionTreeConstPtr& execution, ExecutionTreeTraversalListener& listener); void TraverseTree(const ExecutionTreeConstPtr& execution, ExecutionTreeTraversalListener& listener);
} }
} }

@ -216,8 +216,7 @@ namespace ScriptCanvas
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
@ -300,15 +299,15 @@ namespace ScriptCanvas
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)

@ -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.");
} }
} }

@ -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,
@ -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

@ -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;
};
}

@ -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);
} }

@ -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,37 +133,33 @@ 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));
} }
@ -163,22 +168,21 @@ namespace ScriptCanvas
{ {
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);
} }
} }
} }

@ -18,7 +18,9 @@ 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);
@ -27,5 +29,4 @@ namespace ScriptCanvas
Result ToLua(const Grammar::Request& request); Result ToLua(const Grammar::Request& request);
} }
} }

@ -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;
@ -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);
@ -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();

@ -102,6 +102,9 @@ 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)
@ -121,11 +124,8 @@ namespace ScriptCanvas
VariableFlags::Scope scope = VariableFlags::Scope::Graph; VariableFlags::Scope scope = VariableFlags::Scope::Graph;
if ((exposureType & VariableFlags::Deprecated::Exposure::Exp_InOut) == VariableFlags::Deprecated::Exposure::Exp_InOut) 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_Input)
{ {
scope = VariableFlags::Scope::Graph; scope = VariableFlags::Scope::Graph;
} }
@ -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.")

@ -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)

@ -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