PythonUtility.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <Source/PythonCommon.h>
  10. #include <pybind11/pybind11.h>
  11. #include <AzCore/RTTI/BehaviorContext.h>
  12. #include <AzCore/RTTI/AttributeReader.h>
  13. #include <AzCore/std/string/string_view.h>
  14. #include <AzCore/std/optional.h>
  15. namespace AZ
  16. {
  17. struct BehaviorParameter;
  18. struct BehaviorArgument;
  19. class BehaviorMethod;
  20. }
  21. namespace EditorPythonBindings
  22. {
  23. namespace Scope
  24. {
  25. inline bool IsBehaviorFlaggedForEditor(const AZ::AttributeArray& attributes)
  26. {
  27. // defaults to Launcher
  28. AZ::Script::Attributes::ScopeFlags scopeType = AZ::Script::Attributes::ScopeFlags::Launcher;
  29. AZ::Attribute* scopeAttribute = AZ::FindAttribute(AZ::Script::Attributes::Scope, attributes);
  30. if (scopeAttribute)
  31. {
  32. AZ::AttributeReader scopeAttributeReader(nullptr, scopeAttribute);
  33. scopeAttributeReader.Read<AZ::Script::Attributes::ScopeFlags>(scopeType);
  34. }
  35. return (scopeType == AZ::Script::Attributes::ScopeFlags::Automation || scopeType == AZ::Script::Attributes::ScopeFlags::Common);
  36. }
  37. inline void FetchScriptName(const AZ::AttributeArray& attributes, AZStd::string& baseName)
  38. {
  39. AZ::Attribute* scriptNameAttribute = AZ::FindAttribute(AZ::Script::Attributes::Alias, attributes);
  40. if (scriptNameAttribute)
  41. {
  42. AZ::AttributeReader scopeAttributeReader(nullptr, scriptNameAttribute);
  43. scopeAttributeReader.Read<AZStd::string>(baseName);
  44. }
  45. }
  46. }
  47. namespace Module
  48. {
  49. using PackageMapType = AZStd::unordered_map<AZStd::string, pybind11::module>;
  50. //! Finds or creates a sub-module to add a base parent module; create all the sub-modules as well
  51. //! @param modulePackageMap keeps track of the known modules
  52. //! @param moduleName can be a dot separated string such as "mygen.mypackage.mymodule"
  53. //! @param parentModule the module to add new sub-modules
  54. //! @param fallbackModule the module to add new sub-modules
  55. //! @param alertUsingFallback issue a warning if using the fallback module
  56. //! @return the new submodule
  57. pybind11::module DeterminePackageModule(PackageMapType& modulePackageMap, AZStd::string_view moduleName, pybind11::module parentModule, pybind11::module fallbackModule, bool alertUsingFallback);
  58. inline AZStd::optional<AZStd::string_view> GetName(const AZ::AttributeArray& attributes)
  59. {
  60. AZ::Attribute* moduleAttribute = AZ::FindAttribute(AZ::Script::Attributes::Module, attributes);
  61. if (moduleAttribute)
  62. {
  63. const char* moduleName = nullptr;
  64. AZ::AttributeReader scopeAttributeReader(nullptr, moduleAttribute);
  65. scopeAttributeReader.Read<const char*>(moduleName);
  66. if (moduleName)
  67. {
  68. return { moduleName };
  69. }
  70. }
  71. return {};
  72. }
  73. }
  74. namespace Convert
  75. {
  76. // allocation pattern for BehaviorValueParameters being stored in the stack and needs to be cleaned at the end of a block
  77. using VariableDeleter = AZStd::function<void()>;
  78. struct StackVariableAllocator final
  79. : public AZStd::static_buffer_allocator<256, 16>
  80. {
  81. public:
  82. ~StackVariableAllocator();
  83. void StoreVariableDeleter(VariableDeleter&& deleter);
  84. private:
  85. AZStd::vector<VariableDeleter> m_cleanUpItems;
  86. };
  87. //! Converts a behavior value parameter to a Python object
  88. //! @param behaviorValue is a parameter that came from a result or some prepared behavior value
  89. //! @param stackVariableAllocator manages the allocated parameter while in scope
  90. //! @return a valid Python object or None if no conversion was possible
  91. pybind11::object BehaviorValueParameterToPython(AZ::BehaviorArgument& behaviorValue, Convert::StackVariableAllocator& stackVariableAllocator);
  92. //! Converts Python object to a behavior value parameter using an existing behaviorArgument from a Behavior Method
  93. //! @param behaviorArgument the stored argument slot from a Behavior Method to match with the pyObj to covert in the parameter
  94. //! @param parameter is the output of the conversion from Python to a Behavior value
  95. //! @param stackVariableAllocator manages the allocated parameter while in scope
  96. //! @return true if the conversion happened
  97. bool PythonToBehaviorValueParameter(const AZ::BehaviorParameter& behaviorArgument, pybind11::object pyObj, AZ::BehaviorArgument& parameter, Convert::StackVariableAllocator& stackVariableAllocator);
  98. //! Converts Python object to a PythonProxyObject, if possible
  99. //! @param behaviorArgument A stored PythonProxyObject in Python, returns FALSE if the Python object does not point to a PythonProxyObject
  100. //! @param parameter is the output of the conversion from Python to a Behavior value
  101. //! @return true if the conversion happened
  102. bool PythonProxyObjectToBehaviorValueParameter(const AZ::BehaviorParameter& behaviorArgument, pybind11::object pyObj, AZ::BehaviorArgument& parameter);
  103. //! Gets a readable type name for the Python object; this will unwrap a PythonProxyObject to find its underlying type name
  104. //! @param pyObj any valid Python object value
  105. //! @return text form of the Python object value type
  106. AZStd::string GetPythonTypeName(pybind11::object pyObj);
  107. }
  108. namespace Call
  109. {
  110. //! Calls a BehaviorMethod with a tuple of arguments for non-member functions
  111. pybind11::object StaticMethod(AZ::BehaviorMethod* behaviorMethod, pybind11::args args);
  112. //! Calls a BehaviorMethod with a tuple of arguments for member class level functions
  113. pybind11::object ClassMethod(AZ::BehaviorMethod* behaviorMethod, AZ::BehaviorObject self, pybind11::args args);
  114. }
  115. }