OpenXRVkBehaviorReflection.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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. #include <OpenXRVk/OpenXRVkReferenceSpacesInterface.h>
  9. #include <OpenXRVk/OpenXRVkActionsInterface.h>
  10. #include "OpenXRVkBehaviorReflection.h"
  11. namespace OpenXRVk
  12. {
  13. void PoseWithVelocities::Reflect(AZ::ReflectContext* context)
  14. {
  15. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  16. {
  17. serializeContext->Class<PoseWithVelocities>()
  18. ->Version(1)
  19. ->Field("Pose", &PoseWithVelocities::m_pose)
  20. ->Field("LinearVelocity", &PoseWithVelocities::m_linearVelocity)
  21. ->Field("AngularVelocitu", &PoseWithVelocities::m_angularVelocity)
  22. ;
  23. }
  24. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  25. {
  26. behaviorContext->Class<PoseWithVelocities>()
  27. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
  28. ->Attribute(AZ::Script::Attributes::Module, "openxr")
  29. ->Property("pose", BehaviorValueGetter(&PoseWithVelocities::m_pose), nullptr)
  30. ->Property("linearVelocity", BehaviorValueGetter(&PoseWithVelocities::m_linearVelocity), nullptr)
  31. ->Property("angularVelocity", BehaviorValueGetter(&PoseWithVelocities::m_angularVelocity), nullptr)
  32. ;
  33. }
  34. }
  35. //! This class implements the functions that are exported into the Behavior Context
  36. //! as a means to provide scripting access to OpenXRReferenceSpacesInterface.
  37. class OpenXRReferenceSpaces
  38. {
  39. public:
  40. AZ_TYPE_INFO(OpenXRReferenceSpaces, "{A060D5C5-1514-421B-9AAA-1E276BA2E33E}");
  41. AZ_CLASS_ALLOCATOR(OpenXRReferenceSpaces, AZ::SystemAllocator);
  42. static constexpr char LogName[] = "OpenXRReferenceSpaces";
  43. OpenXRReferenceSpaces() = default;
  44. ~OpenXRReferenceSpaces() = default;
  45. static AZStd::vector<AZStd::string> GetReferenceSpaceNames()
  46. {
  47. const auto iface = OpenXRReferenceSpacesInterface::Get();
  48. if (!iface)
  49. {
  50. AZ_Error(LogName, false, "%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__);
  51. return {};
  52. }
  53. return iface->GetReferenceSpaceNames();
  54. }
  55. static AZ::Outcome<bool, AZStd::string> AddReferenceSpace(IOpenXRReferenceSpaces::ReferenceSpaceId referenceSpaceType,
  56. const AZStd::string& spaceName, const AZ::Transform& poseInReferenceSpace)
  57. {
  58. const auto iface = OpenXRReferenceSpacesInterface::Get();
  59. if (!iface)
  60. {
  61. return AZ::Failure(
  62. AZStd::string::format("%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__)
  63. );
  64. }
  65. return iface->AddReferenceSpace(referenceSpaceType, spaceName, poseInReferenceSpace);
  66. }
  67. static AZ::Outcome<bool, AZStd::string> RemoveReferenceSpace(const AZStd::string& spaceName)
  68. {
  69. const auto iface = OpenXRReferenceSpacesInterface::Get();
  70. if (!iface)
  71. {
  72. return AZ::Failure(
  73. AZStd::string::format("%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__)
  74. );
  75. }
  76. return iface->RemoveReferenceSpace(spaceName);
  77. }
  78. static AZ::Outcome<AZ::Transform, AZStd::string> GetReferenceSpacePose(const AZStd::string& spaceName, const AZStd::string& baseSpaceName)
  79. {
  80. const auto iface = OpenXRReferenceSpacesInterface::Get();
  81. if (!iface)
  82. {
  83. return AZ::Failure(
  84. AZStd::string::format("%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__)
  85. );
  86. }
  87. return iface->GetReferenceSpacePose(spaceName, baseSpaceName);
  88. }
  89. static AZ::Outcome<bool, AZStd::string> SetBaseSpaceForViewSpacePose(const AZStd::string& spaceName)
  90. {
  91. const auto iface = OpenXRReferenceSpacesInterface::Get();
  92. if (!iface)
  93. {
  94. return AZ::Failure(
  95. AZStd::string::format("%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__)
  96. );
  97. }
  98. return iface->SetBaseSpaceForViewSpacePose(spaceName);
  99. }
  100. static const AZStd::string& GetBaseSpaceForViewSpacePose()
  101. {
  102. const auto iface = OpenXRReferenceSpacesInterface::Get();
  103. if (!iface)
  104. {
  105. AZ_Error(LogName, false, "%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__);
  106. static const AZStd::string emptyStr;
  107. return emptyStr;
  108. }
  109. return iface->GetBaseSpaceForViewSpacePose();
  110. }
  111. static const AZ::Transform& GetViewSpacePose()
  112. {
  113. const auto iface = OpenXRReferenceSpacesInterface::Get();
  114. if (!iface)
  115. {
  116. AZ_Error(LogName, false, "%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__);
  117. return AZ::Transform::Identity();
  118. }
  119. return iface->GetViewSpacePose();
  120. }
  121. static uint32_t GetViewCount()
  122. {
  123. const auto iface = OpenXRReferenceSpacesInterface::Get();
  124. if (!iface)
  125. {
  126. AZ_Error(LogName, false, "%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__);
  127. return 0;
  128. }
  129. return iface->GetViewCount();
  130. }
  131. static const AZ::Transform& GetViewPose(uint32_t eyeIndex)
  132. {
  133. const auto iface = OpenXRReferenceSpacesInterface::Get();
  134. if (!iface)
  135. {
  136. AZ_Error(LogName, false, "%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__);
  137. return AZ::Transform::Identity();
  138. }
  139. return iface->GetViewPose(eyeIndex);
  140. }
  141. static const AZStd::vector<AZ::Transform>& GetViewPoses()
  142. {
  143. const auto iface = OpenXRReferenceSpacesInterface::Get();
  144. if (!iface)
  145. {
  146. AZ_Error(LogName, false, "%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__);
  147. static AZStd::vector<AZ::Transform> EmptyList;
  148. return EmptyList;
  149. }
  150. return iface->GetViewPoses();
  151. }
  152. static void ForceViewPosesCacheUpdate()
  153. {
  154. const auto iface = OpenXRReferenceSpacesInterface::Get();
  155. if (!iface)
  156. {
  157. AZ_Error(LogName, false, "%s: OpenXRReferenceSpacesInterface is not available.", __FUNCTION__);
  158. return;
  159. }
  160. iface->ForceViewPosesCacheUpdate();
  161. }
  162. }; // class OpenXRReferenceSpaces
  163. //! This class implements the functions that are exported into the Behavior Context
  164. //! as a means to provide scripting access to OpenXRActionsInterface.
  165. class OpenXRActions
  166. {
  167. public:
  168. AZ_TYPE_INFO(OpenXRActions, "{290DF9D5-4042-4843-BF23-D49F9FAD6D90}");
  169. AZ_CLASS_ALLOCATOR(OpenXRActions, AZ::SystemAllocator);
  170. static constexpr char LogName[] = "OpenXRActions";
  171. OpenXRActions() = default;
  172. ~OpenXRActions() = default;
  173. static AZStd::vector<AZStd::string> GetAllActionSets()
  174. {
  175. const auto iface = OpenXRActionsInterface::Get();
  176. if (!iface)
  177. {
  178. AZ_Error(LogName, false, "%s: OpenXRActionsInterface is not available.", __FUNCTION__);
  179. return {};
  180. }
  181. return iface->GetAllActionSets();
  182. }
  183. static AZ::Outcome<bool, AZStd::string> GetActionSetState(const AZStd::string& actionSetName)
  184. {
  185. const auto iface = OpenXRActionsInterface::Get();
  186. if (!iface)
  187. {
  188. AZ_Error(LogName, false, "%s: OpenXRActionsInterface is not available.", __FUNCTION__);
  189. return {};
  190. }
  191. return iface->GetActionSetState(actionSetName);
  192. }
  193. static AZ::Outcome<bool, AZStd::string> SetActionSetState(const AZStd::string& actionSetName, bool activate)
  194. {
  195. const auto iface = OpenXRActionsInterface::Get();
  196. if (!iface)
  197. {
  198. AZ_Error(LogName, false, "%s: OpenXRActionsInterface is not available.", __FUNCTION__);
  199. return {};
  200. }
  201. return iface->SetActionSetState(actionSetName, activate);
  202. }
  203. //! REMARK: The original idea was to return an:
  204. //! AZ::Outcome<IOpenXRActions::ActionHandle, AZStd::string>
  205. //! But when compiling for Android the Behavior Context ->Method() would statically
  206. //! fail claiming that it was not constructible.
  207. static IOpenXRActions::ActionHandle GetActionHandle(const AZStd::string& actionSetName, const AZStd::string& actionName)
  208. {
  209. const auto iface = OpenXRActionsInterface::Get();
  210. if (!iface)
  211. {
  212. AZ_Error(LogName, false, "%s: OpenXRActionsInterface is not available.", __FUNCTION__);
  213. return {};
  214. }
  215. return iface->GetActionHandle(actionSetName, actionName);
  216. }
  217. static AZ::Outcome<bool, AZStd::string> GetActionStateBoolean(IOpenXRActions::ActionHandle actionHandle)
  218. {
  219. const auto iface = OpenXRActionsInterface::Get();
  220. if (!iface)
  221. {
  222. return AZ::Failure(
  223. AZStd::string::format("%s: OpenXRActionsInterface is not available.", __FUNCTION__)
  224. );
  225. }
  226. return iface->GetActionStateBoolean(actionHandle);
  227. }
  228. static AZ::Outcome<float, AZStd::string> GetActionStateFloat(IOpenXRActions::ActionHandle actionHandle)
  229. {
  230. const auto iface = OpenXRActionsInterface::Get();
  231. if (!iface)
  232. {
  233. return AZ::Failure(
  234. AZStd::string::format("%s: OpenXRActionsInterface is not available.", __FUNCTION__)
  235. );
  236. }
  237. return iface->GetActionStateFloat(actionHandle);
  238. }
  239. static AZ::Outcome<AZ::Vector2, AZStd::string> GetActionStateVector2(IOpenXRActions::ActionHandle actionHandle)
  240. {
  241. const auto iface = OpenXRActionsInterface::Get();
  242. if (!iface)
  243. {
  244. return AZ::Failure(
  245. AZStd::string::format("%s: OpenXRActionsInterface is not available.", __FUNCTION__)
  246. );
  247. }
  248. return iface->GetActionStateVector2(actionHandle);
  249. }
  250. static AZ::Outcome<bool, AZStd::string> SetBaseReferenceSpaceForPoseActions(const AZStd::string& visualizedSpaceName)
  251. {
  252. const auto iface = OpenXRActionsInterface::Get();
  253. if (!iface)
  254. {
  255. return AZ::Failure(
  256. AZStd::string::format("%s: OpenXRActionsInterface is not available.", __FUNCTION__)
  257. );
  258. }
  259. return iface->SetBaseReferenceSpaceForPoseActions(visualizedSpaceName);
  260. }
  261. static const AZStd::string& GetBaseReferenceSpaceForPoseActions()
  262. {
  263. const auto iface = OpenXRActionsInterface::Get();
  264. if (!iface)
  265. {
  266. AZ_Error(LogName, false, "%s: OpenXRActionsInterface is not available.", __FUNCTION__);
  267. static const AZStd::string emptyStr;
  268. return emptyStr;
  269. }
  270. return iface->GetBaseReferenceSpaceForPoseActions();
  271. }
  272. static AZ::Outcome<AZ::Transform, AZStd::string> GetActionStatePose(IOpenXRActions::ActionHandle actionHandle)
  273. {
  274. const auto iface = OpenXRActionsInterface::Get();
  275. if (!iface)
  276. {
  277. return AZ::Failure(
  278. AZStd::string::format("%s: OpenXRActionsInterface is not available.", __FUNCTION__)
  279. );
  280. }
  281. return iface->GetActionStatePose(actionHandle);
  282. }
  283. static AZ::Outcome<PoseWithVelocities, AZStd::string> GetActionStatePoseWithVelocities(IOpenXRActions::ActionHandle actionHandle)
  284. {
  285. const auto iface = OpenXRActionsInterface::Get();
  286. if (!iface)
  287. {
  288. return AZ::Failure(
  289. AZStd::string::format("%s: OpenXRActionsInterface is not available.", __FUNCTION__)
  290. );
  291. }
  292. return iface->GetActionStatePoseWithVelocities(actionHandle);
  293. }
  294. static AZ::Outcome<bool, AZStd::string> ApplyHapticVibrationAction(IOpenXRActions::ActionHandle actionHandle, uint64_t durationNanos, float frequencyHz, float amplitude)
  295. {
  296. const auto iface = OpenXRActionsInterface::Get();
  297. if (!iface)
  298. {
  299. return AZ::Failure(
  300. AZStd::string::format("%s: OpenXRActionsInterface is not available.", __FUNCTION__)
  301. );
  302. }
  303. return iface->ApplyHapticVibrationAction(actionHandle, durationNanos, frequencyHz, amplitude);
  304. }
  305. static AZ::Outcome<bool, AZStd::string> StopHapticVibrationAction(IOpenXRActions::ActionHandle actionHandle)
  306. {
  307. const auto iface = OpenXRActionsInterface::Get();
  308. if (!iface)
  309. {
  310. return AZ::Failure(
  311. AZStd::string::format("%s: OpenXRActionsInterface is not available.", __FUNCTION__)
  312. );
  313. }
  314. return iface->StopHapticVibrationAction(actionHandle);
  315. }
  316. }; // class OpenXRActions
  317. void OpenXRBehaviorReflect(AZ::BehaviorContext& context)
  318. {
  319. IOpenXRActions::ActionHandle::Reflect(&context);
  320. PoseWithVelocities::Reflect(&context);
  321. context.Class<OpenXRReferenceSpaces>("OpenXRReferenceSpaces")
  322. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
  323. ->Attribute(AZ::Script::Attributes::Module, "openxr")
  324. ->Constant("ReferenceSpaceIdView", BehaviorConstant(IOpenXRReferenceSpaces::ReferenceSpaceIdView))
  325. ->Constant("ReferenceSpaceIdLocal", BehaviorConstant(IOpenXRReferenceSpaces::ReferenceSpaceIdLocal))
  326. ->Constant("ReferenceSpaceIdStage", BehaviorConstant(IOpenXRReferenceSpaces::ReferenceSpaceIdStage))
  327. ->Constant("ReferenceSpaceNameView", BehaviorConstant(AZStd::string(IOpenXRReferenceSpaces::ReferenceSpaceNameView)))
  328. ->Constant("ReferenceSpaceNameLocal", BehaviorConstant(AZStd::string(IOpenXRReferenceSpaces::ReferenceSpaceNameLocal)))
  329. ->Constant("ReferenceSpaceNameStage", BehaviorConstant(AZStd::string(IOpenXRReferenceSpaces::ReferenceSpaceNameStage)))
  330. ->Constant("LeftEyeViewId", BehaviorConstant(IOpenXRReferenceSpaces::LeftEyeView))
  331. ->Constant("RightEyeViewId", BehaviorConstant(IOpenXRReferenceSpaces::RightEyeView))
  332. ->Method("GetReferenceSpaceNames", &OpenXRReferenceSpaces::GetReferenceSpaceNames)
  333. ->Method("AddReferenceSpace", &OpenXRReferenceSpaces::AddReferenceSpace)
  334. ->Method("RemoveReferenceSpace", &OpenXRReferenceSpaces::RemoveReferenceSpace)
  335. ->Method("GetReferenceSpacePose", &OpenXRReferenceSpaces::GetReferenceSpacePose)
  336. ->Method("SetBaseSpaceForViewSpacePose", &OpenXRReferenceSpaces::SetBaseSpaceForViewSpacePose)
  337. ->Method("GetBaseSpaceForViewSpacePose", &OpenXRReferenceSpaces::GetBaseSpaceForViewSpacePose)
  338. ->Method("GetViewSpacePose", &OpenXRReferenceSpaces::GetViewSpacePose)
  339. ->Method("GetViewCount", &OpenXRReferenceSpaces::GetViewCount)
  340. ->Method("GetViewPose", &OpenXRReferenceSpaces::GetViewPose)
  341. ->Method("GetViewPoses", &OpenXRReferenceSpaces::GetViewPoses)
  342. ->Method("ForceViewPosesCacheUpdate", &OpenXRReferenceSpaces::ForceViewPosesCacheUpdate)
  343. ;
  344. context.Class<OpenXRActions>("OpenXRActions")
  345. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
  346. ->Attribute(AZ::Script::Attributes::Module, "openxr")
  347. ->Method("GetAllActionSets", &OpenXRActions::GetAllActionSets)
  348. ->Method("GetActionSetState", &OpenXRActions::GetActionSetState)
  349. ->Method("SetActionSetState", &OpenXRActions::SetActionSetState)
  350. ->Method("GetActionHandle", &OpenXRActions::GetActionHandle)
  351. ->Method("GetActionStateBoolean", &OpenXRActions::GetActionStateBoolean)
  352. ->Method("GetActionStateFloat", &OpenXRActions::GetActionStateFloat)
  353. ->Method("GetActionStateVector2", &OpenXRActions::GetActionStateVector2)
  354. ->Method("SetBaseReferenceSpaceForPoseActions", &OpenXRActions::SetBaseReferenceSpaceForPoseActions)
  355. ->Method("GetBaseReferenceSpaceForPoseActions", &OpenXRActions::GetBaseReferenceSpaceForPoseActions)
  356. ->Method("GetActionStatePose", &OpenXRActions::GetActionStatePose)
  357. ->Method("GetActionStatePoseWithVelocities", &OpenXRActions::GetActionStatePoseWithVelocities)
  358. ->Method("ApplyHapticVibrationAction", &OpenXRActions::ApplyHapticVibrationAction)
  359. ->Method("StopHapticVibrationAction", &OpenXRActions::StopHapticVibrationAction)
  360. ;
  361. }
  362. }