Added Hydra API to extract all the classes, globals and EBuses exposed (#4953)

* Added Hydra API to extract all the classes, globals and EBuses exposed
to lua:

azlmbr.script.LuaSymbolsReporterBus:
GetListOfClasses
GetListOfGlobalProperties
GetListOfGlobalFunctions
GetListOfEBuses

Also exposed to Hydra the classes that can be used to dump
the symbols
azlmbr.script.LuaPropertySymbol
azlmbr.script.LuaMethodSymbol
azlmbr.script.LuaClassSymbol
azlmbr.script.LuaEBusSender
azlmbr.script.LuaEBusSymbol

The python file Assets/Editor/Scripts/lua_symbols.py
can be used with "pyRunFile <script_name> [output.txt]"
to create Game/output.txt will all the symbols
OR
passing up to three additional arguments "c" or "g" or "e" to dump only
classes, globals or ebuses or a combination of those. Example:
To create an output file with only classes and Ebuses:
"pyRunFile <script_name> [output.txt] c e"

Signed-off-by: garrieta <garrieta@amazon.com>
This commit is contained in:
galibzon
2021-10-25 13:26:53 -05:00
committed by GitHub
parent da2ce2d7f0
commit 4d4deb1211
7 changed files with 782 additions and 1 deletions
@@ -0,0 +1,110 @@
/*
* 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/EBus/EBus.h>
#include <AzCore/Interface/Interface.h>
namespace AzToolsFramework
{
namespace Script
{
struct LuaPropertySymbol
{
AZ_TYPE_INFO(LuaPropertySymbol, "{5AFB147F-50A4-4F00-9F82-D8D5BBC970D6}");
static void Reflect(AZ::ReflectContext* context);
AZStd::string m_name;
bool m_canRead;
bool m_canWrite;
AZStd::string ToString() const;
};
struct LuaMethodSymbol
{
AZ_TYPE_INFO(LuaMethodSymbol, "{7B074A36-C81D-46A0-8D2F-62E426EBE38A}");
static void Reflect(AZ::ReflectContext* context);
AZStd::string m_name;
AZStd::string m_debugArgumentInfo;
AZStd::string ToString() const;
};
struct LuaClassSymbol
{
AZ_TYPE_INFO(LuaClassSymbol, "{5FBE5841-A8E1-44B6-BEDA-22302CF8DF5F}");
static void Reflect(AZ::ReflectContext* context);
AZStd::string m_name;
AZ::Uuid m_typeId;
AZStd::vector<LuaPropertySymbol> m_properties;
AZStd::vector<LuaMethodSymbol> m_methods;
AZStd::string ToString() const;
};
struct LuaEBusSender
{
AZ_TYPE_INFO(LuaEBusSender, "{23EE4188-0924-49DB-BF3F-EB7AAB6D5E5C}");
static void Reflect(AZ::ReflectContext* context);
AZStd::string m_name;
AZStd::string m_debugArgumentInfo;
AZStd::string m_category;
AZStd::string ToString() const;
};
struct LuaEBusSymbol
{
AZ_TYPE_INFO(LuaEBusSymbol, "{381C5639-A916-4D2E-B825-50A3F2D93137}");
static void Reflect(AZ::ReflectContext* context);
AZStd::string m_name;
bool m_canBroadcast;
bool m_canQueue;
bool m_hasHandler;
AZStd::vector<LuaEBusSender> m_senders;
AZStd::string ToString() const;
};
// This is an EBus useful to scrape classes, globals and EBuses exposed to game scripting
// e.g: Lua.
class LuaSymbolsReporterRequests
{
public:
AZ_RTTI(LuaSymbolsReporterRequests, "{3FF9A105-3159-49FF-8DC6-4948AE7B4AB8}");
virtual ~LuaSymbolsReporterRequests() = default;
// Put your public methods here
virtual const AZStd::vector<LuaClassSymbol>& GetListOfClasses() = 0;
virtual const AZStd::vector<LuaPropertySymbol>& GetListOfGlobalProperties() = 0;
virtual const AZStd::vector<LuaMethodSymbol>& GetListOfGlobalFunctions() = 0;
virtual const AZStd::vector<LuaEBusSymbol>& GetListOfEBuses() = 0;
};
class LuaSymbolsReporterBusTraits
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
};
using LuaSymbolsReporterRequestBus = AZ::EBus<LuaSymbolsReporterRequests, LuaSymbolsReporterBusTraits>;
} // namespace Script
} // namespace AzToolsFramework
@@ -0,0 +1,475 @@
/*
* 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/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Script/ScriptSystemBus.h>
#include <AzCore/Script/ScriptContextDebug.h>
#include "LuaSymbolsReporterSystemComponent.h"
namespace AzToolsFramework
{
namespace Script
{
AZStd::string LuaPropertySymbol::ToString() const
{
return AZStd::string::format("%s [%s/%s]",
m_name.c_str(),
m_canRead ? "R" : "_",
m_canWrite ? "W" : "_");
}
void LuaPropertySymbol::Reflect(AZ::ReflectContext* context)
{
auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<LuaPropertySymbol>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "script")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Property("name", BehaviorValueProperty(&LuaPropertySymbol::m_name))
->Property("canRead", BehaviorValueProperty(&LuaPropertySymbol::m_canRead))
->Property("canWrite", BehaviorValueProperty(&LuaPropertySymbol::m_canWrite))
->Method("ToString", &LuaPropertySymbol::ToString)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
;
}
}
AZStd::string LuaMethodSymbol::ToString() const
{
return AZStd::string::format("%s(%s)", m_name.c_str(), m_debugArgumentInfo.c_str());
}
void LuaMethodSymbol::Reflect(AZ::ReflectContext* context)
{
auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<LuaMethodSymbol>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "script")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Property("name", BehaviorValueProperty(&LuaMethodSymbol::m_name))
->Property("debugArgumentInfo", BehaviorValueProperty(&LuaMethodSymbol::m_debugArgumentInfo))
->Method("ToString", &LuaMethodSymbol::ToString)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
;
}
}
AZStd::string LuaClassSymbol::ToString() const
{
return AZStd::string::format("%s [%s]", m_name.c_str(), m_typeId.ToString<AZStd::string>().c_str());
}
void LuaClassSymbol::Reflect(AZ::ReflectContext* context)
{
auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<LuaClassSymbol>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "script")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Property("name", BehaviorValueProperty(&LuaClassSymbol::m_name))
->Property("typeId", BehaviorValueProperty(&LuaClassSymbol::m_typeId))
->Property("properties", BehaviorValueProperty(&LuaClassSymbol::m_properties))
->Property("methods", BehaviorValueProperty(&LuaClassSymbol::m_methods))
->Method("ToString", &LuaClassSymbol::ToString)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
;
}
}
AZStd::string LuaEBusSender::ToString() const
{
return AZStd::string::format("%s(%s) - [%s]", m_name.c_str(), m_debugArgumentInfo.c_str(), m_category.c_str());
}
void LuaEBusSender::Reflect(AZ::ReflectContext* context)
{
auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<LuaEBusSender>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "script")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Property("name", BehaviorValueProperty(&LuaEBusSender::m_name))
->Property("debugArgumentInfo", BehaviorValueProperty(&LuaEBusSender::m_debugArgumentInfo))
->Property("category", BehaviorValueProperty(&LuaEBusSender::m_category))
->Method("ToString", &LuaEBusSender::ToString)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
;
}
}
AZStd::string LuaEBusSymbol::ToString() const
{
auto boolToStr = +[](bool val) { return val ? "true" : "false"; };
return AZStd::string::format("%s: canBroadcast(%s), canQueue(%s), hasHandler(%s)",
m_name.c_str(),
boolToStr(m_canBroadcast), boolToStr(m_canQueue), boolToStr(m_hasHandler));
}
void LuaEBusSymbol::Reflect(AZ::ReflectContext* context)
{
auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<LuaEBusSymbol>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "script")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Property("name", BehaviorValueProperty(&LuaEBusSymbol::m_name))
->Property("canBroadcast", BehaviorValueProperty(&LuaEBusSymbol::m_canBroadcast))
->Property("canQueue", BehaviorValueProperty(&LuaEBusSymbol::m_canQueue))
->Property("hasHandler", BehaviorValueProperty(&LuaEBusSymbol::m_hasHandler))
->Property("senders", BehaviorValueProperty(&LuaEBusSymbol::m_senders))
->Method("ToString", &LuaEBusSymbol::ToString)
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
;
}
}
//! This local class helps us keeping private the sensitive data in LuaSymbolsReporterSystemComponent
//! Used inside the function pointers for several AZ::SciptContextDebug::Enumerate* functions.
class IntrusiveHelper
{
public:
static AZStd::vector<LuaClassSymbol>& GetClassSymbols(LuaSymbolsReporterSystemComponent& symbolsReporter) { return symbolsReporter.m_cachedClassSymbols; }
static AZStd::unordered_map<AZ::Uuid, size_t>& GetClassUuidToIndexMap(LuaSymbolsReporterSystemComponent& symbolsReporter) { return symbolsReporter.m_classUuidToIndexMap; }
static AZStd::vector<LuaPropertySymbol>& GetGlobalPropertySymbols(LuaSymbolsReporterSystemComponent& symbolsReporter) { return symbolsReporter.m_cachedGlobalPropertySymbols; }
static AZStd::vector<LuaMethodSymbol>& GetGlobalFunctionSymbols(LuaSymbolsReporterSystemComponent& symbolsReporter) { return symbolsReporter.m_cachedGlobalFunctionSymbols; }
static AZStd::vector<LuaEBusSymbol>& GetEBusSymbols(LuaSymbolsReporterSystemComponent& symbolsReporter) { return symbolsReporter.m_cachedEbusSymbols; }
static AZStd::unordered_map<AZStd::string, size_t>& GetEBusNameToIndexMap(LuaSymbolsReporterSystemComponent& symbolsReporter) { return symbolsReporter.m_ebusNameToIndexMap; }
};
void LuaSymbolsReporterSystemComponent::Reflect(AZ::ReflectContext* context)
{
LuaPropertySymbol::Reflect(context);
LuaMethodSymbol::Reflect(context);
LuaClassSymbol::Reflect(context);
LuaEBusSender::Reflect(context);
LuaEBusSymbol::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<LuaSymbolsReporterSystemComponent, AZ::Component>()
->Version(0);
serializeContext->RegisterGenericType<AZStd::vector<LuaPropertySymbol>>();
serializeContext->RegisterGenericType<AZStd::vector<LuaMethodSymbol>>();
serializeContext->RegisterGenericType<AZStd::vector<LuaClassSymbol>>();
serializeContext->RegisterGenericType<AZStd::vector<LuaEBusSender>>();
serializeContext->RegisterGenericType<AZStd::vector<LuaEBusSymbol>>();
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<LuaSymbolsReporterRequestBus>("LuaSymbolsReporterBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "script")
->Event("GetListOfClasses", &LuaSymbolsReporterRequests::GetListOfClasses)
->Event("GetListOfGlobalProperties", &LuaSymbolsReporterRequests::GetListOfGlobalProperties)
->Event("GetListOfGlobalFunctions", &LuaSymbolsReporterRequests::GetListOfGlobalFunctions)
->Event("GetListOfEBuses", &LuaSymbolsReporterRequests::GetListOfEBuses)
;
}
}
void LuaSymbolsReporterSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC_CE("LuaSymbolsReporterSystemService"));
}
void LuaSymbolsReporterSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC_CE("LuaSymbolsReporterSystemService"));
}
void LuaSymbolsReporterSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC_CE("ScriptService"));
}
void LuaSymbolsReporterSystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
// No dependent services.
}
void LuaSymbolsReporterSystemComponent::Activate()
{
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
LuaSymbolsReporterRequestBus::Handler::BusConnect();
}
void LuaSymbolsReporterSystemComponent::Deactivate()
{
LuaSymbolsReporterRequestBus::Handler::BusDisconnect();
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
}
AZ::ScriptContext* LuaSymbolsReporterSystemComponent::InitScriptContext()
{
if (m_scriptContext)
{
return m_scriptContext;
}
AZ::ScriptSystemRequestBus::BroadcastResult(m_scriptContext, &AZ::ScriptSystemRequests::GetContext, AZ::ScriptContextIds::DefaultScriptContextId);
return m_scriptContext;
}
void LuaSymbolsReporterSystemComponent::LoadGlobalSymbols()
{
auto scriptContext = InitScriptContext();
if (!scriptContext)
{
AZ_Error(LogName, false, "Invalid scriptContext");
return;
}
scriptContext->EnableDebug();
auto debugContext = scriptContext->GetDebugContext();
if (!debugContext)
{
AZ_Error(LogName, false, "Invalid debugContext from scriptContext");
return;
}
auto enumMethodFunc = +[]([[maybe_unused]] const AZ::Uuid* classTypeId, const char* methodName, const char* debugArgumentInfo, void* userData) -> bool
{
auto& mySelf = *reinterpret_cast<LuaSymbolsReporterSystemComponent*>(userData);
auto& methodSymbols = IntrusiveHelper::GetGlobalFunctionSymbols(mySelf);
methodSymbols.push_back({});
auto& methodSymbol = methodSymbols.back();
methodSymbol.m_name = methodName;
if (debugArgumentInfo)
{
methodSymbol.m_debugArgumentInfo = debugArgumentInfo;
}
return true;
};
auto enumPropertyFunc = +[]([[maybe_unused]] const AZ::Uuid* classTypeId, const char* propertyName, bool canRead, bool canWrite, void* userData) -> bool
{
auto& mySelf = *reinterpret_cast<LuaSymbolsReporterSystemComponent*>(userData);
auto& propertySymbols = IntrusiveHelper::GetGlobalPropertySymbols(mySelf);
propertySymbols.push_back({});
auto& propertySymbol = propertySymbols.back();
propertySymbol.m_name = propertyName;
propertySymbol.m_canRead = canRead;
propertySymbol.m_canWrite = canWrite;
return true;
};
debugContext->EnumRegisteredGlobals(enumMethodFunc, enumPropertyFunc, this);
scriptContext->DisableDebug();
}
///////////////////////////////////////////////////////////////////////////
/// LuaSymbolsReporterRequestBus::Handler
const AZStd::vector<LuaClassSymbol>& LuaSymbolsReporterSystemComponent::GetListOfClasses()
{
if (!m_cachedClassSymbols.empty())
{
return m_cachedClassSymbols;
}
auto scriptContext = InitScriptContext();
if (!scriptContext)
{
return m_cachedClassSymbols;
}
scriptContext->EnableDebug();
auto debugContext = scriptContext->GetDebugContext();
if (!debugContext)
{
return m_cachedClassSymbols;
}
auto enumClassFunc = +[](const char* className, const AZ::Uuid& classTypeId, void* userData) -> bool
{
auto& mySelf = *reinterpret_cast<LuaSymbolsReporterSystemComponent*>(userData);
auto& classSymbols = IntrusiveHelper::GetClassSymbols(mySelf);
classSymbols.push_back({});
auto& classSymbol = classSymbols.back();
classSymbol.m_name = className;
classSymbol.m_typeId = classTypeId;
auto& uuidToClassMap = IntrusiveHelper::GetClassUuidToIndexMap(mySelf);
uuidToClassMap.emplace(classTypeId, classSymbols.size() - 1);
return true;
};
auto enumMethodFunc = +[](const AZ::Uuid* classTypeId, const char* methodName, const char* debugArgumentInfo, void* userData) -> bool
{
auto& mySelf = *reinterpret_cast<LuaSymbolsReporterSystemComponent*>(userData);
auto& classUuidToIndexMap = IntrusiveHelper::GetClassUuidToIndexMap(mySelf);
auto itor = classUuidToIndexMap.find(*classTypeId);
if (itor == classUuidToIndexMap.end())
{
AZ_Error(LogName, false, "Can not add method [%s] because class uuid [%s] is not registered", methodName, classTypeId->ToString<AZStd::string>().c_str());
return false;
}
auto classIndex = itor->second;
auto& classSymbols = IntrusiveHelper::GetClassSymbols(mySelf);
auto& classSymbol = classSymbols[classIndex];
classSymbol.m_methods.push_back({});
auto& methodSymbol = classSymbol.m_methods.back();
methodSymbol.m_name = methodName;
if (debugArgumentInfo)
{
methodSymbol.m_debugArgumentInfo = debugArgumentInfo;
}
return true;
};
auto enumPropertyFunc = +[](const AZ::Uuid* classTypeId, const char* propertyName, bool canRead, bool canWrite, void* userData) -> bool
{
auto& mySelf = *reinterpret_cast<LuaSymbolsReporterSystemComponent*>(userData);
auto& classUuidToIndexMap = IntrusiveHelper::GetClassUuidToIndexMap(mySelf);
auto itor = classUuidToIndexMap.find(*classTypeId);
if (itor == classUuidToIndexMap.end())
{
AZ_Error(LogName, false, "Can not add property [%s] because class uuid [%s] is not registered", propertyName, classTypeId->ToString<AZStd::string>().c_str());
return false;
}
auto classIndex = itor->second;
auto& classSymbols = IntrusiveHelper::GetClassSymbols(mySelf);
auto& classSymbol = classSymbols[classIndex];
classSymbol.m_properties.push_back({});
auto& propertySymbol = classSymbol.m_properties.back();
propertySymbol.m_name = propertyName;
propertySymbol.m_canRead = canRead;
propertySymbol.m_canWrite = canWrite;
return true;
};
debugContext->EnumRegisteredClasses(enumClassFunc, enumMethodFunc, enumPropertyFunc, this);
scriptContext->DisableDebug();
return m_cachedClassSymbols;
}
const AZStd::vector<LuaPropertySymbol>& LuaSymbolsReporterSystemComponent::GetListOfGlobalProperties()
{
if (!m_cachedGlobalPropertySymbols.empty())
{
return m_cachedGlobalPropertySymbols;
}
LoadGlobalSymbols();
return m_cachedGlobalPropertySymbols;
}
const AZStd::vector<LuaMethodSymbol>& LuaSymbolsReporterSystemComponent::GetListOfGlobalFunctions()
{
if (!m_cachedGlobalFunctionSymbols.empty())
{
return m_cachedGlobalFunctionSymbols;
}
LoadGlobalSymbols();
return m_cachedGlobalFunctionSymbols;
}
const AZStd::vector<LuaEBusSymbol>& LuaSymbolsReporterSystemComponent::GetListOfEBuses()
{
if (!m_cachedEbusSymbols.empty())
{
return m_cachedEbusSymbols;
}
auto scriptContext = InitScriptContext();
if (!scriptContext)
{
return m_cachedEbusSymbols;
}
scriptContext->EnableDebug();
auto debugContext = scriptContext->GetDebugContext();
if (!debugContext)
{
return m_cachedEbusSymbols;
}
auto enumEBusFunc = +[](const AZStd::string& ebusName, bool canBroadcast, bool canQueue, bool hasHandler, void* userData) -> bool
{
auto& mySelf = *reinterpret_cast<LuaSymbolsReporterSystemComponent*>(userData);
auto& ebusSymbols = IntrusiveHelper::GetEBusSymbols(mySelf);
ebusSymbols.push_back({});
auto& ebusSymbol = ebusSymbols.back();
ebusSymbol.m_name = ebusName;
ebusSymbol.m_canBroadcast = canBroadcast;
ebusSymbol.m_canQueue = canQueue;
ebusSymbol.m_hasHandler = hasHandler;
auto& nameToIndexMap = IntrusiveHelper::GetEBusNameToIndexMap(mySelf);
nameToIndexMap.emplace(ebusName, ebusSymbols.size() - 1);
return true;
};
auto enumEBusSenderFunc = +[](const AZStd::string& ebusName, const AZStd::string& senderName, const AZStd::string& debugArgumentInfo, const AZStd::string& category, void* userData) -> bool
{
auto& mySelf = *reinterpret_cast<LuaSymbolsReporterSystemComponent*>(userData);
auto& nameToIndexMap = IntrusiveHelper::GetEBusNameToIndexMap(mySelf);
auto itor = nameToIndexMap.find(ebusName);
if (itor == nameToIndexMap.end())
{
AZ_Error(LogName, false, "Can not add ebus sender [%s] because ebus [%s] is not registered", senderName.c_str(), ebusName.c_str());
return false;
}
auto ebusIndex = itor->second;
auto& ebusSymbols = IntrusiveHelper::GetEBusSymbols(mySelf);
auto& ebusSymbol = ebusSymbols[ebusIndex];
ebusSymbol.m_senders.push_back({});
auto& ebusSender = ebusSymbol.m_senders.back();
ebusSender.m_name = senderName;
ebusSender.m_debugArgumentInfo = debugArgumentInfo;
ebusSender.m_category = category;
return true;
};
debugContext->EnumRegisteredEBuses(enumEBusFunc, enumEBusSenderFunc, this);
scriptContext->DisableDebug();
return m_cachedEbusSymbols;
}
///////////////////////////////////////////////////////////////////////////
} //namespace Script
} // namespace AzToolsFramework
@@ -0,0 +1,73 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Script/ScriptContext.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Script/LuaSymbolsReporterBus.h>
namespace AzToolsFramework
{
namespace Script
{
/// System component for LuaSymbolsReporterRequestBus
class LuaSymbolsReporterSystemComponent
: public AZ::Component
, public LuaSymbolsReporterRequestBus::Handler
, private AzToolsFramework::EditorEvents::Bus::Handler
{
public:
AZ_COMPONENT(LuaSymbolsReporterSystemComponent, "{DB8D95BA-FECF-4D81-A45C-8C05E706E2AC}");
static void Reflect(AZ::ReflectContext* context);
static constexpr char LogName[] = "LuaSymbolsReporter";
LuaSymbolsReporterSystemComponent() = default;
~LuaSymbolsReporterSystemComponent() = default;
///////////////////////////////////////////////////////////////////////////
/// LuaSymbolsReporterRequestBus::Handler
const AZStd::vector<LuaClassSymbol>& GetListOfClasses() override;
const AZStd::vector<LuaPropertySymbol>& GetListOfGlobalProperties() override;
const AZStd::vector<LuaMethodSymbol>& GetListOfGlobalFunctions() override;
const AZStd::vector<LuaEBusSymbol>& GetListOfEBuses() override;
///////////////////////////////////////////////////////////////////////////
private:
friend class IntrusiveHelper;
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
// AZ::Component
void Activate() override;
void Deactivate() override;
AZ::ScriptContext* InitScriptContext();
void LoadGlobalSymbols();
AZ::ScriptContext* m_scriptContext = nullptr;
AZStd::vector<LuaClassSymbol> m_cachedClassSymbols;
// The key is a class uuid, the value is the index in @m_cachedClassSymbols
AZStd::unordered_map<AZ::Uuid, size_t> m_classUuidToIndexMap;
AZStd::vector<LuaPropertySymbol> m_cachedGlobalPropertySymbols;
AZStd::vector<LuaMethodSymbol> m_cachedGlobalFunctionSymbols;
AZStd::vector<LuaEBusSymbol> m_cachedEbusSymbols;
// The key is the ebus name, the value is the index in @m_cachedEbusSymbols
AZStd::unordered_map<AZStd::string, size_t> m_ebusNameToIndexMap;
};
} // namespace Script
} // namespace AzToolsFramework