1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423 |
- /*
- * 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 "TranslationGeneration.h"
- #include <Source/Translation/TranslationBus.h>
- #include <AzCore/JSON/rapidjson.h>
- #include <AzCore/JSON/document.h>
- #include <AzCore/JSON/stringbuffer.h>
- #include <AzCore/JSON/prettywriter.h>
- #include <AzCore/IO/FileIO.h>
- #include <AzCore/IO/SystemFile.h>
- #include <AzCore/IO/Path/Path.h>
- #include <AzCore/RTTI/BehaviorContext.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzCore/Serialization/EditContext.h>
- #include <AzCore/std/string/regex.h>
- #include <Libraries/Core/AzEventHandler.h>
- #include <Libraries/Libraries.h>
- #include <Libraries/Core/GetVariable.h>
- #include <Libraries/Core/SetVariable.h>
- #include <AzFramework/StringFunc/StringFunc.h>
- #include <AzQtComponents/Utilities/DesktopUtilities.h>
- #include <Editor/Translation/TranslationHelper.h>
- #include <Source/Translation/TranslationSerializer.h>
- #include "Data/DataRegistry.h"
- namespace ScriptCanvasEditorTools
- {
- namespace Helpers
- {
- //! Convenience function that writes a key/value string pair into a given JSON value
- void WriteString(rapidjson::Value& owner, const AZStd::string& key, const AZStd::string& value, rapidjson::Document& document);
- }
- TranslationGeneration::TranslationGeneration()
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- AZ::ComponentApplicationBus::BroadcastResult(m_behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext);
- }
- void TranslationGeneration::TranslateBehaviorClasses()
- {
- for (const auto& behaviorClassPair : m_behaviorContext->m_classes)
- {
- TranslateBehaviorClass(behaviorClassPair.second);
- }
- }
- void TranslationGeneration::TranslateEBus(const AZ::BehaviorEBus* behaviorEBus)
- {
- if (ShouldSkip(behaviorEBus))
- {
- return;
- }
- TranslationFormat translationRoot;
- // Get the handlers
- if (!TranslateEBusHandler(behaviorEBus, translationRoot))
- {
- if (behaviorEBus->m_events.empty())
- {
- return;
- }
- Entry entry;
- // Generate the translation file
- entry.m_key = behaviorEBus->m_name;
- entry.m_details.m_category = Helpers::GetStringAttribute(behaviorEBus, AZ::Script::Attributes::Category);;
- entry.m_details.m_tooltip = behaviorEBus->m_toolTip;
- entry.m_details.m_name = behaviorEBus->m_name;
- entry.m_context = ScriptCanvasEditor::TranslationHelper::AssetContext::EBusSenderContext;
- AZStd::string prettyName = Helpers::GetStringAttribute(behaviorEBus, AZ::ScriptCanvasAttributes::PrettyName);
- if (!prettyName.empty())
- {
- entry.m_details.m_name = prettyName;
- }
- SplitCamelCase(entry.m_details.m_name);
- for (auto event : behaviorEBus->m_events)
- {
- const AZ::BehaviorEBusEventSender& ebusSender = event.second;
- AZ::BehaviorMethod* method = ebusSender.m_event;
- if (!method)
- {
- method = ebusSender.m_broadcast;
- }
- if (!method)
- {
- AZ_Warning("Script Canvas", false, "Failed to find method: %s", event.first.c_str());
- continue;
- }
- Method eventEntry;
- const char* eventName = event.first.c_str();
- eventEntry.m_key = eventName;
- prettyName = Helpers::GetStringAttribute(behaviorEBus, AZ::ScriptCanvasAttributes::PrettyName);
- eventEntry.m_details.m_name = prettyName.empty() ? eventName : prettyName;
- eventEntry.m_details.m_tooltip = Helpers::ReadStringAttribute(event.second.m_attributes, AZ::Script::Attributes::ToolTip);
- SplitCamelCase(eventEntry.m_details.m_name);
- eventEntry.m_entry.m_name = "In";
- eventEntry.m_entry.m_tooltip = AZStd::string::format("When signaled, this will invoke %s", eventEntry.m_details.m_name.c_str());
- eventEntry.m_exit.m_name = "Out";
- eventEntry.m_exit.m_tooltip = AZStd::string::format("Signaled after %s is invoked", eventEntry.m_details.m_name.c_str());
- size_t start = method->HasBusId() ? 1 : 0;
- for (size_t i = start; i < method->GetNumArguments(); ++i)
- {
- Argument argument;
- auto argumentType = method->GetArgument(i)->m_typeId;
- // Check the BC for metadata
- Helpers::GetTypeNameAndDescription(argumentType, argument.m_details.m_name, argument.m_details.m_tooltip);
- auto name = method->GetArgumentName(i);
- if (name && !name->empty())
- {
- argument.m_details.m_name = *name;
- }
- auto tooltip = method->GetArgumentToolTip(i);
- if (tooltip && !tooltip->empty())
- {
- argument.m_details.m_tooltip = *tooltip;
- }
- argument.m_typeId = argumentType.ToString<AZStd::string>();
- SplitCamelCase(argument.m_details.m_name);
- eventEntry.m_arguments.push_back(argument);
- }
- if (method->HasResult())
- {
- TranslateMethodResults(method->GetResult(), eventEntry);
- }
- entry.m_methods.push_back(eventEntry);
- }
- translationRoot.m_entries.push_back(entry);
- SaveJSONData(AZStd::string::format("EBus/Senders/%s", behaviorEBus->m_name.c_str()), translationRoot);
- }
- else
- {
- SaveJSONData(AZStd::string::format("EBus/Handlers/%s", behaviorEBus->m_name.c_str()), translationRoot);
- }
- }
- AZ::Entity* TranslationGeneration::GetAZEventNode(const AZ::BehaviorMethod& method)
- {
- // Make sure the method returns an AZ::Event by reference or pointer
- if (AZ::MethodReturnsAzEventByReferenceOrPointer(method))
- {
- // Read in AZ Event Description data to retrieve the event name and parameter names
- AZ::Attribute* azEventDescAttribute = AZ::FindAttribute(AZ::Script::Attributes::AzEventDescription, method.m_attributes);
- AZ::BehaviorAzEventDescription behaviorAzEventDesc;
- AZ::AttributeReader azEventDescAttributeReader(nullptr, azEventDescAttribute);
- azEventDescAttributeReader.Read<decltype(behaviorAzEventDesc)>(behaviorAzEventDesc);
- if (behaviorAzEventDesc.m_eventName.empty())
- {
- AZ_Error("NodeUtils", false, "Cannot create an AzEvent node with empty event name")
- }
- auto scriptCanvasEntity = aznew AZ::Entity{ AZStd::string::format("SC-EventNode(%s)", behaviorAzEventDesc.m_eventName.c_str()) };
- scriptCanvasEntity->Init();
- auto azEventHandler = scriptCanvasEntity->CreateComponent<ScriptCanvas::Nodes::Core::AzEventHandler>();
- azEventHandler->InitEventFromMethod(method);
- return scriptCanvasEntity;
- }
- return nullptr;
- }
- bool TranslationGeneration::TranslateBehaviorClass(const AZ::BehaviorClass* behaviorClass)
- {
- if (ShouldSkip(behaviorClass))
- {
- return false;
- }
- AZStd::string className = behaviorClass->m_name;
- AZStd::string prettyName = Helpers::GetStringAttribute(behaviorClass, AZ::ScriptCanvasAttributes::PrettyName);
- if (!prettyName.empty())
- {
- className = prettyName;
- }
- TranslationFormat translationRoot;
- Entry entry;
- entry.m_context = ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorClassContext;
- entry.m_key = behaviorClass->m_name;
- EntryDetails& details = entry.m_details;
- details.m_name = className;
- details.m_category = Helpers::GetStringAttribute(behaviorClass, AZ::Script::Attributes::Category);
- details.m_tooltip = Helpers::GetStringAttribute(behaviorClass, AZ::Script::Attributes::ToolTip);
- SplitCamelCase(details.m_name);
- if (!behaviorClass->m_methods.empty())
- {
- for (const auto& methodPair : behaviorClass->m_methods)
- {
- const AZ::BehaviorMethod* behaviorMethod = methodPair.second;
- if (TranslateSingleAZEvent(behaviorMethod))
- {
- continue;
- }
- Method methodEntry;
- AZStd::string cleanName = GraphCanvas::TranslationKey::Sanitize(methodPair.first);
- methodEntry.m_key = cleanName;
- methodEntry.m_details.m_category = "";
- methodEntry.m_details.m_tooltip = "";
- methodEntry.m_details.m_name = methodPair.second->m_name;
- AZStd::string prefix = className + "::";
- AZ::StringFunc::Replace(methodEntry.m_details.m_name, prefix.c_str(), "");
- SplitCamelCase(methodEntry.m_details.m_name);
- methodEntry.m_entry.m_name = "In";
- methodEntry.m_entry.m_tooltip = AZStd::string::format("When signaled, this will invoke %s", methodEntry.m_details.m_name.c_str());
- methodEntry.m_exit.m_name = "Out";
- methodEntry.m_exit.m_tooltip = AZStd::string::format("Signaled after %s is invoked", methodEntry.m_details.m_name.c_str());
- if (!Helpers::MethodHasAttribute(behaviorMethod, AZ::ScriptCanvasAttributes::FloatingFunction))
- {
- methodEntry.m_details.m_category = details.m_category;
- }
- else if (Helpers::MethodHasAttribute(behaviorMethod, AZ::Script::Attributes::Category))
- {
- methodEntry.m_details.m_category = Helpers::ReadStringAttribute(behaviorMethod->m_attributes, AZ::Script::Attributes::Category);
- }
- // Arguments (Input Slots)
- TranslateMethodArguments(behaviorMethod, methodEntry);
- // Results (Output Slots)
- const AZ::BehaviorParameter* resultParameter = behaviorMethod->HasResult() ? behaviorMethod->GetResult() : nullptr;
- if (resultParameter)
- {
- TranslateMethodResults(resultParameter, methodEntry);
- }
- entry.m_methods.push_back(methodEntry);
- }
- }
- // Behavior Class properties
- if (!behaviorClass->m_properties.empty())
- {
- for (const auto& propertyEntry : behaviorClass->m_properties)
- {
- AZ::BehaviorProperty* behaviorProperty = propertyEntry.second;
- if (behaviorProperty)
- {
- TranslateBehaviorProperty(behaviorProperty, behaviorClass->m_name, ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorClassContext, &entry);
- }
- }
- }
- translationRoot.m_entries.push_back(entry);
- AZStd::string sanitizedFilename = GraphCanvas::TranslationKey::Sanitize(className);
- AZStd::string fileName = AZStd::string::format("Classes/%s", sanitizedFilename.c_str());
- SaveJSONData(fileName, translationRoot);
- return true;
- }
- //! Generate the translation data for a specific AZ::Event
- bool TranslationGeneration::TranslateSingleAZEvent(const AZ::BehaviorMethod* method)
- {
- AZ::Entity* node = GetAZEventNode(*method);
- if (!node)
- {
- return false;
- }
- TranslationFormat translationRoot;
- ScriptCanvas::Nodes::Core::AzEventHandler* nodeComponent = node->FindComponent<ScriptCanvas::Nodes::Core::AzEventHandler>();
- nodeComponent->Init();
- nodeComponent->Configure();
- const ScriptCanvas::Nodes::Core::AzEventEntry& azEventEntry{ nodeComponent->GetEventEntry() };
- Entry entry;
- entry.m_key = azEventEntry.m_eventName;
- entry.m_context = ScriptCanvasEditor::TranslationHelper::AssetContext::AZEventContext;
- entry.m_details.m_name = azEventEntry.m_eventName;
- SplitCamelCase(entry.m_details.m_name);
- for (const ScriptCanvas::Slot& slot : nodeComponent->GetSlots())
- {
- Slot slotEntry;
- if (slot.IsVisible())
- {
- slotEntry.m_key = slot.GetName();
- if (slot.GetId() == azEventEntry.m_azEventInputSlotId)
- {
- slotEntry.m_details.m_name = azEventEntry.m_eventName;
- }
- else
- {
- slotEntry.m_details.m_name = slot.GetName();
- }
- entry.m_slots.push_back(slotEntry);
- }
- }
- translationRoot.m_entries.push_back(entry);
- // delete the node, don't need to keep it beyond this point
- delete node;
- AZStd::string filename = GraphCanvas::TranslationKey::Sanitize(entry.m_key);
- AZStd::string targetFile = AZStd::string::format("AZEvents/%s", filename.c_str());
- SaveJSONData(targetFile, translationRoot);
- translationRoot.m_entries.clear();
- return true;
- }
- void TranslationGeneration::TranslateAZEvents()
- {
- GraphCanvas::TranslationKey translationKey;
- AZStd::vector<AZ::BehaviorMethod*> methods;
- // Methods
- for (const auto& behaviorMethod : m_behaviorContext->m_methods)
- {
- const auto method = behaviorMethod.second;
- methods.push_back(method);
- }
- // Methods in classes
- for (auto behaviorClass : m_behaviorContext->m_classes)
- {
- for (auto behaviorMethod : behaviorClass.second->m_methods)
- {
- const auto method = behaviorMethod.second;
- methods.push_back(method);
- }
- }
- for (auto& method : methods)
- {
- TranslateSingleAZEvent(method);
- }
- }
- void TranslationGeneration::TranslateNodes()
- {
- GraphCanvas::TranslationKey translationKey;
- AZStd::vector<AZ::TypeId> nodes;
- auto getNodeClasses = [this, &nodes](const AZ::SerializeContext::ClassData*, const AZ::Uuid& type)
- {
- bool foundBaseClass = false;
- auto baseClassVisitorFn = [&nodes, &type, &foundBaseClass](const AZ::SerializeContext::ClassData* reflectedBase, const AZ::TypeId& /*rttiBase*/)
- {
- if (!reflectedBase)
- {
- foundBaseClass = false;
- return false; // stop iterating
- }
- foundBaseClass = (reflectedBase->m_typeId == azrtti_typeid<ScriptCanvas::Node>());
- if (foundBaseClass)
- {
- nodes.push_back(type);
- return false; // we have a base, stop iterating
- }
- return true; // keep iterating
- };
- AZ::EntityUtils::EnumerateBaseRecursive(m_serializeContext, baseClassVisitorFn, type);
- return true;
- };
- m_serializeContext->EnumerateAll(getNodeClasses);
- for (auto& node : nodes)
- {
- TranslateNode(node);
- }
- }
- void TranslationGeneration::TranslateNode(const AZ::TypeId& nodeTypeId)
- {
- TranslationFormat translationRoot;
- if (const AZ::SerializeContext::ClassData* classData = m_serializeContext->FindClassData(nodeTypeId))
- {
- Entry entry;
- entry.m_key = classData->m_typeId.ToString<AZStd::string>();
- entry.m_context = ScriptCanvasEditor::TranslationHelper::AssetContext::CustomNodeContext;
- EntryDetails& details = entry.m_details;
- AZStd::string cleanName = GraphCanvas::TranslationKey::Sanitize(classData->m_name);
- if (classData->m_editData)
- {
- details.m_name = classData->m_editData->m_name;
- }
- else
- {
- details.m_name = cleanName;
- }
- SplitCamelCase(details.m_name);
- // Tooltip attribute takes priority over the edit data description
- AZStd::string tooltip = Helpers::GetStringAttribute(classData, AZ::Script::Attributes::ToolTip);
- if (!tooltip.empty())
- {
- details.m_tooltip = tooltip;
- }
- else
- {
- details.m_tooltip = classData->m_editData ? classData->m_editData->m_description : "";
- }
- details.m_category = Helpers::GetStringAttribute(classData, AZ::Script::Attributes::Category);
- if (details.m_subtitle.empty())
- {
- details.m_subtitle = details.m_category;
- }
- if (details.m_category.empty())
- {
- details.m_category = Helpers::GetStringAttribute(classData, AZ::Script::Attributes::Category);
- if (details.m_category.empty() && classData->m_editData)
- {
- details.m_category = Helpers::GetCategory(classData);
- if (details.m_category.empty())
- {
- auto elementData = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData);
- const AZStd::string categoryAttribute = Helpers::ReadStringAttribute(elementData->m_attributes, AZ::Script::Attributes::Category);
- if (!categoryAttribute.empty())
- {
- details.m_category = categoryAttribute;
- }
- }
- }
- }
- if (ScriptCanvas::Node* nodeComponent = reinterpret_cast<ScriptCanvas::Node*>(classData->m_factory->Create(classData->m_name)))
- {
- nodeComponent->Init();
- nodeComponent->Configure();
- int exeInputIndex = 0;
- int exeOutputIndex = 0;
- int dataInputIndex = 0;
- int dataOutputIndex = 0;
- const auto& allSlots = nodeComponent->GetAllSlots();
- for (const auto& slot : allSlots)
- {
- Slot slotEntry;
- if (slot->GetDescriptor().IsExecution())
- {
- if (slot->GetDescriptor().IsInput())
- {
- slotEntry.m_key = AZStd::string::format("Input_%s_%d", slot->GetName().c_str(), exeInputIndex);
- exeInputIndex++;
- slotEntry.m_details.m_name = slot->GetName();
- slotEntry.m_details.m_tooltip = slot->GetToolTip();
- }
- else if (slot->GetDescriptor().IsOutput())
- {
- slotEntry.m_key = AZStd::string::format("Output_%s_%d", slot->GetName().c_str(), exeOutputIndex);
- exeOutputIndex++;
- slotEntry.m_details.m_name = slot->GetName();
- slotEntry.m_details.m_tooltip = slot->GetToolTip();
- }
- entry.m_slots.push_back(slotEntry);
- }
- else
- {
- AZStd::string slotTypeKey = slot->GetDataType().IsValid() ? ScriptCanvas::Data::GetName(slot->GetDataType()) : "";
- if (slotTypeKey.empty())
- {
- if (!slot->GetDataType().GetAZType().IsNull())
- {
- slotTypeKey = slot->GetDataType().GetAZType().ToString<AZStd::string>();
- }
- }
- if (slotTypeKey.empty())
- {
- if (slot->GetDynamicDataType() == ScriptCanvas::DynamicDataType::Container)
- {
- slotTypeKey = "Container";
- }
- else if (slot->GetDynamicDataType() == ScriptCanvas::DynamicDataType::Value)
- {
- slotTypeKey = "Value";
- }
- else if (slot->GetDynamicDataType() == ScriptCanvas::DynamicDataType::Any)
- {
- slotTypeKey = "Any";
- }
- }
- Argument& argument = slotEntry.m_data;
- if (slot->GetDescriptor().IsInput())
- {
- slotEntry.m_key = AZStd::string::format("DataInput_%s_%d", slot->GetName().c_str(), dataInputIndex);
- dataInputIndex++;
- AZStd::string argumentKey = slotTypeKey;
- AZStd::string argumentName = slot->GetName();
- AZStd::string argumentDescription = slot->GetToolTip();
- argument.m_typeId = argumentKey;
- argument.m_details.m_name = argumentName;
- argument.m_details.m_tooltip = argumentDescription;
- }
- else if (slot->GetDescriptor().IsOutput())
- {
- slotEntry.m_key = AZStd::string::format("DataOutput_%s_%d", slot->GetName().c_str(), dataOutputIndex);
- dataOutputIndex++;
- AZStd::string resultKey = slotTypeKey;
- AZStd::string resultName = slot->GetName();
- AZStd::string resultDescription = slot->GetToolTip();
- argument.m_typeId = resultKey;
- argument.m_details.m_name = resultName;
- argument.m_details.m_tooltip = resultDescription;
- }
- entry.m_slots.push_back(slotEntry);
- }
- }
- delete nodeComponent;
- }
- translationRoot.m_entries.push_back(entry);
- if (details.m_category.empty())
- {
- details.m_category = "Uncategorized";
- }
- AZStd::string fileName = ScriptCanvasEditor::TranslationHelper::SanitizeCustomNodeFileName(details.m_name, classData->m_typeId);
- AZStd::string targetFile = AZStd::string::format("Nodes/%s", fileName.c_str());
- SaveJSONData(targetFile, translationRoot);
- translationRoot.m_entries.clear();
- }
- }
- void TranslationGeneration::TranslateOnDemandReflectedTypes(TranslationFormat& translationRoot)
- {
- AZStd::vector<AZ::Uuid> onDemandReflectedTypes;
- for (auto& typePair : m_behaviorContext->m_typeToClassMap)
- {
- if (m_behaviorContext->IsOnDemandTypeReflected(typePair.first))
- {
- onDemandReflectedTypes.push_back(typePair.first);
- }
- // Check for methods that come from node generics
- if (typePair.second->HasAttribute(AZ::ScriptCanvasAttributes::Internal::ImplementedAsNodeGeneric))
- {
- onDemandReflectedTypes.push_back(typePair.first);
- }
- }
- // Now that I know all the on demand reflected, I'll dump it out
- for (auto& onDemandReflectedType : onDemandReflectedTypes)
- {
- AZ::BehaviorClass* behaviorClass = m_behaviorContext->m_typeToClassMap[onDemandReflectedType];
- if (behaviorClass)
- {
- Entry entry;
- EntryDetails& details = entry.m_details;
- details.m_name = behaviorClass->m_name;
- SplitCamelCase(details.m_name);
- // Get the pretty name
- AZStd::string prettyName;
- if (AZ::Attribute* prettyNameAttribute = AZ::FindAttribute(AZ::ScriptCanvasAttributes::PrettyName, behaviorClass->m_attributes))
- {
- AZ::AttributeReader(nullptr, prettyNameAttribute).Read<AZStd::string>(prettyName, *m_behaviorContext);
- }
- entry.m_context = "OnDemandReflected";
- entry.m_key = behaviorClass->m_typeId.ToString<AZStd::string>().c_str();
- if (!prettyName.empty())
- {
- details.m_name = prettyName;
- }
- details.m_category = Helpers::GetStringAttribute(behaviorClass, AZ::Script::Attributes::Category);
- details.m_tooltip = Helpers::GetStringAttribute(behaviorClass, AZ::Script::Attributes::ToolTip);
- for (auto& methodPair : behaviorClass->m_methods)
- {
- AZ::BehaviorMethod* behaviorMethod = methodPair.second;
- if (behaviorMethod)
- {
- Method methodEntry;
- AZStd::string cleanName = GraphCanvas::TranslationKey::Sanitize(methodPair.first);
- methodEntry.m_key = cleanName;
- methodEntry.m_context = entry.m_key;
- methodEntry.m_details.m_tooltip = Helpers::GetStringAttribute(behaviorMethod, AZ::Script::Attributes::ToolTip);
- methodEntry.m_details.m_name = methodPair.second->m_name;
- SplitCamelCase(methodEntry.m_details.m_name);
- // Strip the className from the methodName
- AZStd::string qualifiedName = behaviorClass->m_name + "::";
- AzFramework::StringFunc::Replace(methodEntry.m_details.m_name, qualifiedName.c_str(), "");
- AZStd::string cleanMethodName = methodEntry.m_details.m_name;
- methodEntry.m_entry.m_name = "In";
- methodEntry.m_entry.m_tooltip = AZStd::string::format("When signaled, this will invoke %s", methodEntry.m_details.m_name.c_str());
- methodEntry.m_exit.m_name = "Out";
- methodEntry.m_exit.m_tooltip = AZStd::string::format("Signaled after %s is invoked", methodEntry.m_details.m_name.c_str());
- // Arguments (Input Slots)
- TranslateMethodArguments(behaviorMethod, methodEntry);
- const AZ::BehaviorParameter* resultParameter = behaviorMethod->HasResult() ? behaviorMethod->GetResult() : nullptr;
- if (resultParameter)
- {
- TranslateMethodResults(resultParameter, methodEntry);
- }
- entry.m_methods.push_back(methodEntry);
- }
- }
- translationRoot.m_entries.push_back(entry);
- }
- }
- SaveJSONData("Types/OnDemandReflectedTypes", translationRoot);
- }
- void TranslationGeneration::TranslateBehaviorGlobals()
- {
- for (const auto& [propertyName, behaviorProperty] : m_behaviorContext->m_properties)
- {
- TranslateBehaviorProperty(propertyName);
- }
- }
- void TranslationGeneration::TranslateBehaviorGlobalMethod(const AZStd::string& methodName)
- {
- const auto behaviorMethodEntry = m_behaviorContext->m_methods.find(methodName);
- if (behaviorMethodEntry == m_behaviorContext->m_methods.end())
- {
- return;
- }
- Entry entry;
- entry.m_key = methodName;
- entry.m_context = ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorGlobalMethodContext;
- entry.m_details.m_name = methodName;
- SplitCamelCase(entry.m_details.m_name);
- AZ::BehaviorMethod* behaviorMethod = behaviorMethodEntry->second;
- if (behaviorMethod)
- {
- AZStd::string cleanName = behaviorMethod->m_name;
- Method method;
- method.m_key = cleanName;
- method.m_details.m_name = cleanName;
- method.m_details.m_tooltip = behaviorMethod->m_debugDescription ? behaviorMethod->m_debugDescription : "";
- SplitCamelCase(method.m_details.m_name);
- TranslateMethod(behaviorMethod, method);
- entry.m_methods.push_back(method);
- }
- TranslationFormat translationRoot;
- translationRoot.m_entries.push_back(entry);
- AZStd::string cleanName = GraphCanvas::TranslationKey::Sanitize(behaviorMethod->m_name);
- AZStd::string fileName = AZStd::string::format("GlobalMethods/%s", cleanName.c_str());
- SaveJSONData(fileName, translationRoot);
- }
- void TranslationGeneration::TranslateBehaviorProperty(const AZStd::string& propertyName)
- {
- const auto behaviorPropertyEntry = m_behaviorContext->m_properties.find(propertyName);
- if (behaviorPropertyEntry == m_behaviorContext->m_properties.end())
- {
- return;
- }
- const AZ::BehaviorProperty* behaviorProperty = behaviorPropertyEntry->second;
- Entry entry;
- TranslateBehaviorProperty(behaviorProperty, propertyName, ScriptCanvasEditor::TranslationHelper::AssetContext::BehaviorGlobalPropertyContext, &entry);
- TranslationFormat translationRoot;
- translationRoot.m_entries.push_back(entry);
- AZStd::string cleanName = GraphCanvas::TranslationKey::Sanitize(behaviorProperty->m_name);
- AZStd::string fileName = AZStd::string::format("Properties/%s", cleanName.c_str());
- SaveJSONData(fileName, translationRoot);
- }
- void TranslationGeneration::TranslateDataTypes()
- {
- TranslationFormat translationRoot;
- auto dataRegistry = ScriptCanvas::GetDataRegistry();
-
- for (auto& typePair : dataRegistry->m_creatableTypes)
- {
- if (ScriptCanvas::Data::IsContainerType(typePair.first))
- {
- continue;
- }
- const AZStd::string typeIDStr = typePair.first.GetAZType().ToString<AZStd::string>();
- AZStd::string typeName = ScriptCanvas::Data::GetName(typePair.first);
- Entry entry;
- entry.m_key = typeIDStr;
- entry.m_context = "BehaviorType";
- entry.m_details.m_name = typeName;
- translationRoot.m_entries.emplace_back(entry);
- }
- SaveJSONData("Types/BehaviorTypes", translationRoot);
- }
- void TranslationGeneration::TranslateMethod(AZ::BehaviorMethod* behaviorMethod, Method& methodEntry)
- {
- // Arguments (Input Slots)
- TranslateMethodArguments(behaviorMethod, methodEntry);
- // Results (Output Slots)
- const AZ::BehaviorParameter* resultParameter = behaviorMethod->HasResult() ? behaviorMethod->GetResult() : nullptr;
- if (resultParameter)
- {
- TranslateMethodResults(resultParameter, methodEntry);
- }
- }
- void TranslationGeneration::TranslateMethodArguments(const AZ::BehaviorMethod* behaviorMethod, Method& methodEntry)
- {
- if (behaviorMethod->GetNumArguments() > 0)
- {
- for (size_t argIndex = 0; argIndex < behaviorMethod->GetNumArguments(); ++argIndex)
- {
- const AZ::BehaviorParameter* parameter = behaviorMethod->GetArgument(argIndex);
- Argument argument;
- AZStd::string argumentKey = parameter->m_typeId.ToString<AZStd::string>();
- AZStd::string argumentName = parameter->m_name;
- AZStd::string argumentDescription;
- Helpers::GetTypeNameAndDescription(parameter->m_typeId, argumentName, argumentDescription);
- argument.m_typeId = argumentKey;
- const AZStd::string* argName = behaviorMethod->GetArgumentName(argIndex);
- argument.m_details.m_name = (argName && !argName->empty()) ? *argName : argumentName;
- const AZStd::string* argToolTip = behaviorMethod->GetArgumentToolTip(argIndex);
- argument.m_details.m_tooltip = (argToolTip && !argToolTip->empty()) ? *argToolTip : argumentDescription;
- SplitCamelCase(argument.m_details.m_name);
- methodEntry.m_arguments.push_back(argument);
- }
- }
- }
- void TranslationGeneration::TranslateMethodResults(const AZ::BehaviorParameter* resultParameter, Method& methodEntry)
- {
- if (resultParameter)
- {
- AZStd::vector<AZ::TypeId> unpackedTypes = Helpers::GetUnpackedTypes(resultParameter->m_typeId);
- size_t resultNum = unpackedTypes.size();
- for (size_t resultIndex = 0; resultIndex < resultNum; ++resultIndex)
- {
- Argument result;
- AZStd::string resultKey = unpackedTypes[resultIndex].ToString<AZStd::string>();
- AZStd::string resultName;
- AZStd::string resultDescription;
- Helpers::GetTypeNameAndDescription(unpackedTypes[resultIndex], resultName, resultDescription);
- result.m_typeId = resultKey;
- result.m_details.m_name = resultName;
- result.m_details.m_tooltip = resultDescription;
- SplitCamelCase(result.m_details.m_name);
- methodEntry.m_results.push_back(result);
- }
- }
- }
- void TranslationGeneration::TranslateBehaviorProperty(const AZ::BehaviorProperty* behaviorProperty, const AZStd::string& className, const AZStd::string& context, Entry* entry)
- {
- if (!behaviorProperty->m_getter && !behaviorProperty->m_setter)
- {
- return;
- }
- Entry localEntry;
- if (!entry)
- {
- entry = &localEntry;
- }
- else if (entry->m_key.empty())
- {
- entry->m_key = className;
- entry->m_context = context;
- entry->m_details.m_name = className;
- SplitCamelCase(entry->m_details.m_name);
- }
- if (behaviorProperty->m_getter)
- {
- AZStd::string cleanName = behaviorProperty->m_name;
- AZ::StringFunc::Replace(cleanName, "::Getter", "");
- Method method;
- AZStd::string methodName = "Get";
- methodName.append(cleanName);
- method.m_key = methodName;
- method.m_context = "Getter";
- method.m_details.m_name = methodName;
- method.m_details.m_tooltip = behaviorProperty->m_getter->m_debugDescription ? behaviorProperty->m_getter->m_debugDescription : "";
- SplitCamelCase(method.m_details.m_name);
- TranslateMethod(behaviorProperty->m_getter, method);
- // We know this is a getter, so there will only be one parameter, we will use the method name as a best
- // guess for the argument name
- SplitCamelCase(cleanName);
- method.m_results[0].m_details.m_name = cleanName;
- entry->m_methods.push_back(method);
- }
- if (behaviorProperty->m_setter)
- {
- AZStd::string cleanName = behaviorProperty->m_name;
- AZ::StringFunc::Replace(cleanName, "::Setter", "");
- Method method;
- AZStd::string methodName = "Set";
- methodName.append(cleanName);
- method.m_key = methodName;
- method.m_context = "Setter";
- method.m_details.m_name = methodName;
- method.m_details.m_tooltip = behaviorProperty->m_setter->m_debugDescription ? behaviorProperty->m_getter->m_debugDescription : "";
- SplitCamelCase(method.m_details.m_name);
- TranslateMethod(behaviorProperty->m_setter, method);
- // We know this is a setter, so there will only be one parameter, we will use the method name as a best
- // guess for the argument name
- SplitCamelCase(cleanName);
- method.m_arguments[1].m_details.m_name = cleanName;
- entry->m_methods.push_back(method);
- }
- }
- bool TranslationGeneration::TranslateEBusHandler(const AZ::BehaviorEBus* behaviorEbus, TranslationFormat& translationRoot)
- {
- // Must be a valid ebus handler
- if (!behaviorEbus || !behaviorEbus->m_createHandler || !behaviorEbus->m_destroyHandler)
- {
- return false;
- }
- // Create the handler in order to get information out of it
- AZ::BehaviorEBusHandler* handler(nullptr);
- if (behaviorEbus->m_createHandler->InvokeResult(handler))
- {
- Entry entry;
- // Generate the translation file
- entry.m_key = behaviorEbus->m_name;
- entry.m_context = ScriptCanvasEditor::TranslationHelper::AssetContext::EBusHandlerContext;
- entry.m_details.m_name = behaviorEbus->m_name;
- entry.m_details.m_tooltip = behaviorEbus->m_toolTip;
- entry.m_details.m_category = "EBus Handlers";
- SplitCamelCase(entry.m_details.m_name);
- for (const AZ::BehaviorEBusHandler::BusForwarderEvent& event : handler->GetEvents())
- {
- Method methodEntry;
- AZStd::string cleanName = GraphCanvas::TranslationKey::Sanitize(event.m_name);
- methodEntry.m_key = cleanName;
- methodEntry.m_details.m_category = "";
- methodEntry.m_details.m_tooltip = "";
- methodEntry.m_details.m_name = event.m_name;
- SplitCamelCase(methodEntry.m_details.m_name);
- // Arguments (Input Slots)
- if (!event.m_parameters.empty())
- {
- for (size_t argIndex = AZ::eBehaviorBusForwarderEventIndices::ParameterFirst; argIndex < event.m_parameters.size(); ++argIndex)
- {
- const AZ::BehaviorParameter& parameter = event.m_parameters[argIndex];
- Argument argument;
- AZStd::string argumentKey = parameter.m_typeId.ToString<AZStd::string>();
- AZStd::string argumentName = event.m_name;
- AZStd::string argumentDescription = "";
- if (!event.m_metadataParameters.empty() && event.m_metadataParameters.size() > argIndex)
- {
- argumentName = event.m_metadataParameters[argIndex].m_name;
- argumentDescription = event.m_metadataParameters[argIndex].m_toolTip;
- }
- if (argumentName.empty())
- {
- Helpers::GetTypeNameAndDescription(parameter.m_typeId, argumentName, argumentDescription);
- }
- if (!event.m_metadataParameters.empty() && event.m_metadataParameters.size() > argIndex)
- {
- auto name = event.m_metadataParameters[argIndex].m_name;
- auto tooltip = event.m_metadataParameters[argIndex].m_toolTip;
- if (!name.empty())
- {
- argumentName = name;
- }
- if (!tooltip.empty())
- {
- argumentDescription = tooltip;
- }
- }
- argument.m_typeId = argumentKey;
- argument.m_details.m_name = argumentName;
- argument.m_details.m_tooltip = argumentDescription;
- SplitCamelCase(argument.m_details.m_name);
- methodEntry.m_arguments.push_back(argument);
- }
- }
- auto resultIndex = AZ::eBehaviorBusForwarderEventIndices::Result;
- const AZ::BehaviorParameter* resultParameter = event.HasResult() ? &event.m_parameters[resultIndex] : nullptr;
- if (resultParameter)
- {
- Argument result;
- AZStd::string resultKey = resultParameter->m_typeId.ToString<AZStd::string>();
- AZStd::string resultName = event.m_name;
- AZStd::string resultDescription = "";
- if (!event.m_metadataParameters.empty() && event.m_metadataParameters.size() > resultIndex)
- {
- resultName = event.m_metadataParameters[resultIndex].m_name;
- resultDescription = event.m_metadataParameters[resultIndex].m_toolTip;
- }
- if (resultName.empty())
- {
- Helpers::GetTypeNameAndDescription(resultParameter->m_typeId, resultName, resultDescription);
- }
- result.m_typeId = resultKey;
- result.m_details.m_name = resultName;
- result.m_details.m_tooltip = resultDescription;
- SplitCamelCase(result.m_details.m_name);
- methodEntry.m_results.push_back(result);
- }
- entry.m_methods.push_back(methodEntry);
- }
- behaviorEbus->m_destroyHandler->Invoke(handler); // Destroys the Created EbusHandler
- translationRoot.m_entries.push_back(entry);
- }
- if (!translationRoot.m_entries.empty())
- {
- return true;
- }
- return false;
- }
- void TranslationGeneration::SaveJSONData(const AZStd::string& filename, TranslationFormat& translationRoot)
- {
- rapidjson::Document document;
- document.SetObject();
- rapidjson::Value entries(rapidjson::kArrayType);
- // Here I'll need to parse translationRoot myself and produce the JSON
- for (const auto& entrySource : translationRoot.m_entries)
- {
- rapidjson::Value entry(rapidjson::kObjectType);
- rapidjson::Value value(rapidjson::kStringType);
- value.SetString(entrySource.m_key.c_str(), document.GetAllocator());
- entry.AddMember(GraphCanvas::Schema::Field::key, value, document.GetAllocator());
- value.SetString(entrySource.m_context.c_str(), document.GetAllocator());
- entry.AddMember(GraphCanvas::Schema::Field::context, value, document.GetAllocator());
- value.SetString(entrySource.m_variant.c_str(), document.GetAllocator());
- entry.AddMember(GraphCanvas::Schema::Field::variant, value, document.GetAllocator());
- rapidjson::Value details(rapidjson::kObjectType);
- value.SetString(entrySource.m_details.m_name.c_str(), document.GetAllocator());
- details.AddMember("name", value, document.GetAllocator());
- Helpers::WriteString(details, "category", entrySource.m_details.m_category, document);
- Helpers::WriteString(details, "tooltip", entrySource.m_details.m_tooltip, document);
- Helpers::WriteString(details, "subtitle", entrySource.m_details.m_subtitle, document);
- entry.AddMember("details", details, document.GetAllocator());
- if (!entrySource.m_methods.empty())
- {
- rapidjson::Value methods(rapidjson::kArrayType);
- for (const auto& methodSource : entrySource.m_methods)
- {
- rapidjson::Value theMethod(rapidjson::kObjectType);
- value.SetString(methodSource.m_key.c_str(), document.GetAllocator());
- theMethod.AddMember(GraphCanvas::Schema::Field::key, value, document.GetAllocator());
- if (!methodSource.m_context.empty())
- {
- value.SetString(methodSource.m_context.c_str(), document.GetAllocator());
- if (value == "Getter" || value == "Setter")
- {
- theMethod.AddMember(GraphCanvas::Schema::Field::context, value, document.GetAllocator());
- }
- }
- if (!methodSource.m_entry.m_name.empty())
- {
- rapidjson::Value entrySlot(rapidjson::kObjectType);
- value.SetString(methodSource.m_entry.m_name.c_str(), document.GetAllocator());
- entrySlot.AddMember("name", value, document.GetAllocator());
- Helpers::WriteString(entrySlot, "tooltip", methodSource.m_entry.m_tooltip, document);
- theMethod.AddMember("entry", entrySlot, document.GetAllocator());
- }
- if (!methodSource.m_exit.m_name.empty())
- {
- rapidjson::Value exitSlot(rapidjson::kObjectType);
- value.SetString(methodSource.m_exit.m_name.c_str(), document.GetAllocator());
- exitSlot.AddMember("name", value, document.GetAllocator());
- Helpers::WriteString(exitSlot, "tooltip", methodSource.m_exit.m_tooltip, document);
- theMethod.AddMember("exit", exitSlot, document.GetAllocator());
- }
- rapidjson::Value methodDetails(rapidjson::kObjectType);
- value.SetString(methodSource.m_details.m_name.c_str(), document.GetAllocator());
- methodDetails.AddMember("name", value, document.GetAllocator());
- Helpers::WriteString(methodDetails, "category", methodSource.m_details.m_category, document);
- Helpers::WriteString(methodDetails, "tooltip", methodSource.m_details.m_tooltip, document);
- theMethod.AddMember("details", methodDetails, document.GetAllocator());
- if (!methodSource.m_arguments.empty())
- {
- rapidjson::Value methodArguments(rapidjson::kArrayType);
- [[maybe_unused]] size_t index = 0;
- for (const auto& argSource : methodSource.m_arguments)
- {
- rapidjson::Value argument(rapidjson::kObjectType);
- rapidjson::Value argumentDetails(rapidjson::kObjectType);
- value.SetString(argSource.m_typeId.c_str(), document.GetAllocator());
- argument.AddMember("typeid", value, document.GetAllocator());
- value.SetString(argSource.m_details.m_name.c_str(), document.GetAllocator());
- argumentDetails.AddMember("name", value, document.GetAllocator());
- Helpers::WriteString(argumentDetails, "category", argSource.m_details.m_category, document);
- Helpers::WriteString(argumentDetails, "tooltip", argSource.m_details.m_tooltip, document);
- argument.AddMember("details", argumentDetails, document.GetAllocator());
- methodArguments.PushBack(argument, document.GetAllocator());
- }
- theMethod.AddMember("params", methodArguments, document.GetAllocator());
- }
- if (!methodSource.m_results.empty())
- {
- rapidjson::Value methodArguments(rapidjson::kArrayType);
- for (const auto& argSource : methodSource.m_results)
- {
- rapidjson::Value argument(rapidjson::kObjectType);
- rapidjson::Value argumentDetails(rapidjson::kObjectType);
- value.SetString(argSource.m_typeId.c_str(), document.GetAllocator());
- argument.AddMember("typeid", value, document.GetAllocator());
- value.SetString(argSource.m_details.m_name.c_str(), document.GetAllocator());
- argumentDetails.AddMember("name", value, document.GetAllocator());
- Helpers::WriteString(argumentDetails, "category", argSource.m_details.m_category, document);
- Helpers::WriteString(argumentDetails, "tooltip", argSource.m_details.m_tooltip, document);
- argument.AddMember("details", argumentDetails, document.GetAllocator());
- methodArguments.PushBack(argument, document.GetAllocator());
- }
- theMethod.AddMember("results", methodArguments, document.GetAllocator());
- }
- methods.PushBack(theMethod, document.GetAllocator());
- }
- entry.AddMember("methods", methods, document.GetAllocator());
- }
- if (!entrySource.m_slots.empty())
- {
- rapidjson::Value slotsArray(rapidjson::kArrayType);
- for (const auto& slotSource : entrySource.m_slots)
- {
- rapidjson::Value theSlot(rapidjson::kObjectType);
- value.SetString(slotSource.m_key.c_str(), document.GetAllocator());
- theSlot.AddMember(GraphCanvas::Schema::Field::key, value, document.GetAllocator());
- rapidjson::Value sloDetails(rapidjson::kObjectType);
- if (!slotSource.m_details.m_name.empty())
- {
- Helpers::WriteString(sloDetails, "name", slotSource.m_details.m_name, document);
- Helpers::WriteString(sloDetails, "tooltip", slotSource.m_details.m_tooltip, document);
- theSlot.AddMember("details", sloDetails, document.GetAllocator());
- }
- if (!slotSource.m_data.m_details.m_name.empty())
- {
- rapidjson::Value slotDataDetails(rapidjson::kObjectType);
- Helpers::WriteString(slotDataDetails, "name", slotSource.m_data.m_details.m_name, document);
- theSlot.AddMember("details", slotDataDetails, document.GetAllocator());
- }
- slotsArray.PushBack(theSlot, document.GetAllocator());
- }
- entry.AddMember("slots", slotsArray, document.GetAllocator());
- }
- entries.PushBack(entry, document.GetAllocator());
- }
- document.AddMember("entries", entries, document.GetAllocator());
- AZ::IO::Path gemPath = ScriptCanvasEditor::TranslationHelper::GetTranslationDefaultFolderPath();
- gemPath = gemPath / filename;
- gemPath.ReplaceExtension(".names");
- AZStd::string folderPath;
- AZ::StringFunc::Path::GetFolderPath(gemPath.c_str(), folderPath);
- if (!AZ::IO::FileIOBase::GetInstance()->Exists(folderPath.c_str()))
- {
- if (AZ::IO::FileIOBase::GetInstance()->CreatePath(folderPath.c_str()) != AZ::IO::ResultCode::Success)
- {
- AZ_Error("Translation", false, "Failed to create output folder");
- return;
- }
- }
- char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 };
- AZ::IO::FileIOBase::GetInstance()->ResolvePath(gemPath.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN);
- AZStd::string endPath = resolvedBuffer;
- AZ::StringFunc::Path::Normalize(endPath);
- AZ::IO::SystemFile outputFile;
- if (!outputFile.Open(endPath.c_str(),
- AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE |
- AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE_PATH |
- AZ::IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY))
- {
- AZ_Error("Translation", false, "Failed to open file for writing: %s", filename.c_str());
- return;
- }
- rapidjson::StringBuffer scratchBuffer;
- rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(scratchBuffer);
- document.Accept(writer);
- outputFile.Write(scratchBuffer.GetString(), scratchBuffer.GetSize());
- outputFile.Close();
- scratchBuffer.Clear();
- // AzQtComponents::ShowFileOnDesktop(endPath.c_str());
- }
- void TranslationGeneration::SplitCamelCase(AZStd::string& text)
- {
- AZStd::regex splitRegex(R"(/[a-z]+|[0-9]+|(?:[A-Z][a-z]+)|(?:[A-Z]+(?=(?:[A-Z][a-z])|[^AZa-z]|[$\d\n]))/g)");
- text = AZStd::regex_replace(text, splitRegex, " $&");
- text = AZ::StringFunc::LStrip(text);
- AZ::StringFunc::Replace(text, " ", " ");
- }
- namespace Helpers
- {
- AZStd::string ReadStringAttribute(const AZ::AttributeArray& attributes, const AZ::Crc32& attribute)
- {
- AZStd::string attributeValue = "";
- if (auto attributeItem = azrtti_cast<AZ::AttributeData<AZStd::string>*>(AZ::FindAttribute(attribute, attributes)))
- {
- attributeValue = attributeItem->Get(nullptr);
- return attributeValue;
- }
- if (auto attributeItem = azrtti_cast<AZ::AttributeData<const char*>*>(AZ::FindAttribute(attribute, attributes)))
- {
- attributeValue = attributeItem->Get(nullptr);
- return attributeValue;
- }
- return {};
- }
- bool MethodHasAttribute(const AZ::BehaviorMethod* method, AZ::Crc32 attribute)
- {
- return AZ::FindAttribute(attribute, method->m_attributes) != nullptr; // warning C4800: 'AZ::Attribute *': forcing value to bool 'true' or 'false' (performance warning)
- }
- void GetTypeNameAndDescription(AZ::TypeId typeId, AZStd::string& outName, AZStd::string& outDescription)
- {
- AZ::SerializeContext* serializeContext{};
- AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- AZ_Assert(serializeContext, "Serialize Context is required");
- if (const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(typeId))
- {
- if (classData->m_editData)
- {
- outName = classData->m_editData->m_name ? classData->m_editData->m_name : classData->m_name;
- outDescription = classData->m_editData->m_description ? classData->m_editData->m_description : "";
- }
- else
- {
- outName = classData->m_name;
- }
- }
- }
- AZStd::string GetCategory(const AZ::SerializeContext::ClassData* classData)
- {
- AZStd::string categoryPath;
- if (classData->m_editData)
- {
- auto editorElementData = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData);
- if (editorElementData)
- {
- if (auto categoryAttribute = editorElementData->FindAttribute(AZ::Edit::Attributes::Category))
- {
- if (auto categoryAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(categoryAttribute))
- {
- categoryPath = categoryAttributeData->Get(nullptr);
- }
- }
- }
- }
- return categoryPath;
- }
- AZStd::vector<AZ::TypeId> GetUnpackedTypes(const AZ::TypeId& typeID)
- {
- using namespace AZ::ScriptCanvasAttributes;
- if (const AZ::BehaviorClass* bcClass = AZ::BehaviorContextHelper::GetClass(typeID))
- {
- if (AZ::Attribute* attribute = AZ::FindAttribute(ReturnValueTypesFunction, bcClass->m_attributes))
- {
- GetUnpackedReturnValueTypesHolder holder;
- AZ::AttributeReader attributeReader(nullptr, attribute);
- attributeReader.Read<GetUnpackedReturnValueTypesHolder>(holder);
- return AZStd::invoke(holder.m_function);
- }
- }
- return { typeID };
- }
- void WriteString(rapidjson::Value& owner, const AZStd::string& key, const AZStd::string& value, rapidjson::Document& document)
- {
- if (key.empty() || value.empty())
- {
- return;
- }
- rapidjson::Value item(rapidjson::kStringType);
- item.SetString(value.c_str(), document.GetAllocator());
- rapidjson::Value keyVal(rapidjson::kStringType);
- keyVal.SetString(key.c_str(), document.GetAllocator());
- owner.AddMember(keyVal, item, document.GetAllocator());
- }
- }
- }
|