ScriptableImGui.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. #pragma once
  13. #include <AzCore/RTTI/RTTI.h>
  14. #include <AzCore/std/string/string.h>
  15. #include <AzCore/std/containers/unordered_map.h>
  16. #include <AzCore/Math/Vector3.h>
  17. #include <imgui/imgui.h>
  18. #define SCRIPTABLE_IMGUI
  19. #ifdef SCRIPTABLE_IMGUI
  20. #define Scriptable_ImGui AtomSampleViewer::ScriptableImGui
  21. #endif
  22. namespace AtomSampleViewer
  23. {
  24. class ScriptManager;
  25. //! Wraps the ImGui API in a reflection system that automatically exposes ImGui data elements
  26. //! to the scripting system. It enhances standard ImGui functions to check for scripted
  27. //! actions that can perform the same actions as a user.
  28. class ScriptableImGui final
  29. {
  30. friend class ScriptManager;
  31. public:
  32. AZ_CLASS_ALLOCATOR(ScriptableImGui, AZ::SystemAllocator, 0);
  33. //! Utility for calling ScriptableImGui::PushNameContext and ScriptableImGui::PopNameContext
  34. class ScopedNameContext final
  35. {
  36. public:
  37. ScopedNameContext(const AZStd::string& nameContext) { ScriptableImGui::PushNameContext(nameContext); }
  38. ~ScopedNameContext() { ScriptableImGui::PopNameContext(); }
  39. };
  40. //! This can be used to add some context around the ImGui labels that are exposed to the script system.
  41. //! Each call to PushNameContext() will add a prefix the ImGui labels to form the script field IDs.
  42. //! For example, the following will result in a script field ID of "A/B/MyButton" instead of just "MyButton".
  43. //! PushNameContext("A");
  44. //! PushNameContext("B");
  45. //! Button("MyButton",...);
  46. //! PopNameContext();
  47. //! PopNameContext();
  48. //! This is especially useful for disambiguating similar ImGui labels.
  49. //! There is also a ScopedNameContext utility class for managing the push/pop using the call stack.
  50. static void PushNameContext(const AZStd::string& nameContext);
  51. static void PopNameContext();
  52. //////////////////////////////////////////////////////////////////
  53. // ImGui bridge functions...
  54. // These follow the same API as the corresponding ImGui functions.
  55. // Add more bridge functions as needed.
  56. static bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0);
  57. static void End();
  58. static bool Checkbox(const char* label, bool* v);
  59. static bool Button(const char* label, const ImVec2& size_arg = ImVec2(0, 0));
  60. static bool ListBox(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1);
  61. static bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1);
  62. static bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%d");
  63. static bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
  64. static bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
  65. static bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
  66. static bool SliderAngle(const char* label, float* v, float v_min = -360.0f, float v_max = 360.0f, const char* format = "%.0f deg");
  67. static bool ColorEdit3(const char* label, float v[3], ImGuiColorEditFlags flags);
  68. static bool ColorPicker3(const char* label, float v[3], ImGuiColorEditFlags flags);
  69. static bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0));
  70. static bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0));
  71. static bool TreeNodeEx(const char* label, ImGuiSelectableFlags flags = 0);
  72. static void TreePop();
  73. static bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
  74. static void EndCombo();
  75. static bool BeginMenu(const char* label, bool enabled = true);
  76. static void EndMenu();
  77. static bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true);
  78. static bool RadioButton(const char* label, int* v, int v_button);
  79. private:
  80. /////////////////////////////////////////////////////////////////////////////////////////////////
  81. // Private API for ScriptManager to call...
  82. static void Create();
  83. static void Destory();
  84. //! Call this every frame to report errors when scripted actions aren't consumed through ImGui API function calls.
  85. //! This usually indicates that a script is trying to manipulate ImGui elements that don't exist.
  86. static void CheckAllActionsConsumed();
  87. //! Clears any scripted actions that were scheduled. This should be called every frame to make sure old actions
  88. //! don't hang around indefinitely and get consumed later and cause unexpected behavior.
  89. static void ClearActions();
  90. //! These functions are called through scripts to schedule a scripted action.
  91. //! This data will be consumed by subsequent calls to ImGui API functions.
  92. //! @param pathToImGuiItem - full path to an ImGui item, including the name context
  93. static void SetBool(const AZStd::string& name, bool value);
  94. static void SetNumber(const AZStd::string& name, float value);
  95. static void SetVector(const AZStd::string& name, const AZ::Vector2& value);
  96. static void SetVector(const AZStd::string& name, const AZ::Vector3& value);
  97. static void SetString(const AZStd::string& name, const AZStd::string& value);
  98. /////////////////////////////////////////////////////////////////////////////////////////////////
  99. using InvalidActionItem = AZStd::monostate;
  100. // Note we don't include an int type because Lua only supports floats
  101. using ActionItem = AZStd::variant<InvalidActionItem, bool, float, AZ::Vector2, AZ::Vector3, AZStd::string>;
  102. //! This utility function factors out common steps that most of the ImGui API bridge functions must perform.
  103. template<typename ActionDataT>
  104. static bool ActionHelper(
  105. const char* label,
  106. AZStd::function<bool()> imguiAction,
  107. AZStd::function<void(const AZStd::string& /*pathToImGuiItem*/)> reportScriptableAction,
  108. AZStd::function<bool(ActionDataT /*scriptArg*/)> handleScriptedAction,
  109. bool shouldReportScriptableActionAfterAnyChange = false);
  110. template<typename ImGuiActionType>
  111. static bool ThreeComponentHelper(const char* label, float v[3], ImGuiActionType& imguiAction);
  112. //! Finds a scheduled script action and removes it from the list of actions.
  113. //! @param pathToImGuiItem - full path to an ImGui item, including the name context
  114. static ActionItem FindAndRemoveAction(const AZStd::string& pathToImGuiItem);
  115. //! Makes a full script field ID path for the given ImGui label, by prefixing the current name context
  116. static AZStd::string MakeFullPath(const AZStd::string& forLabel);
  117. //! Utility function to ensure all script errors use a similar format
  118. static void ReportScriptError(const char* message);
  119. //! Provides a name context prefix to script field IDs for disambiguation.
  120. AZStd::vector<AZStd::string> m_nameContextStack;
  121. using ActionMap = AZStd::unordered_map<AZStd::string, ActionItem>;
  122. ActionMap m_scriptedActions;
  123. bool m_isInScriptedComboPopup = false;
  124. static ScriptableImGui* s_instance;
  125. };
  126. } // namespace AtomSampleViewer