LoggingCharacterContactListener.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2024 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Physics/Character/CharacterVirtual.h>
  6. // Character contact listener that just logs the calls made to it for later validation
  7. class LoggingCharacterContactListener : public CharacterContactListener
  8. {
  9. public:
  10. // Contact callback type
  11. enum class EType
  12. {
  13. ValidateBody,
  14. ValidateCharacter,
  15. AddBody,
  16. PersistBody,
  17. RemoveBody,
  18. AddCharacter,
  19. PersistCharacter,
  20. RemoveCharacter
  21. };
  22. // Entry written when a contact callback happens
  23. struct LogEntry
  24. {
  25. EType mType;
  26. const CharacterVirtual * mCharacter;
  27. BodyID mBody2;
  28. CharacterID mCharacterID2;
  29. SubShapeID mSubShapeID2;
  30. };
  31. virtual bool OnContactValidate(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2) override
  32. {
  33. mLog.push_back({ EType::ValidateBody, inCharacter, inBodyID2, CharacterID(), inSubShapeID2 });
  34. return true;
  35. }
  36. virtual bool OnCharacterContactValidate(const CharacterVirtual *inCharacter, const CharacterVirtual *inOtherCharacter, const SubShapeID &inSubShapeID2) override
  37. {
  38. mLog.push_back({ EType::ValidateCharacter, inCharacter, BodyID(), inOtherCharacter->GetID(), inSubShapeID2 });
  39. return true;
  40. }
  41. virtual void OnContactAdded(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2, RVec3Arg inContactPosition, Vec3Arg inContactNormal, CharacterContactSettings &ioSettings) override
  42. {
  43. mLog.push_back({ EType::AddBody, inCharacter, inBodyID2, CharacterID(), inSubShapeID2 });
  44. }
  45. virtual void OnContactPersisted(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2, RVec3Arg inContactPosition, Vec3Arg inContactNormal, CharacterContactSettings &ioSettings) override
  46. {
  47. mLog.push_back({ EType::PersistBody, inCharacter, inBodyID2, CharacterID(), inSubShapeID2 });
  48. }
  49. virtual void OnContactRemoved(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2) override
  50. {
  51. mLog.push_back({ EType::RemoveBody, inCharacter, inBodyID2, CharacterID(), inSubShapeID2 });
  52. }
  53. virtual void OnCharacterContactAdded(const CharacterVirtual *inCharacter, const CharacterVirtual *inOtherCharacter, const SubShapeID &inSubShapeID2, RVec3Arg inContactPosition, Vec3Arg inContactNormal, CharacterContactSettings &ioSettings) override
  54. {
  55. mLog.push_back({ EType::AddCharacter, inCharacter, BodyID(), inOtherCharacter->GetID(), inSubShapeID2 });
  56. }
  57. virtual void OnCharacterContactPersisted(const CharacterVirtual *inCharacter, const CharacterVirtual *inOtherCharacter, const SubShapeID &inSubShapeID2, RVec3Arg inContactPosition, Vec3Arg inContactNormal, CharacterContactSettings &ioSettings) override
  58. {
  59. mLog.push_back({ EType::PersistCharacter, inCharacter, BodyID(), inOtherCharacter->GetID(), inSubShapeID2 });
  60. }
  61. virtual void OnCharacterContactRemoved(const CharacterVirtual *inCharacter, const CharacterID &inOtherCharacterID, const SubShapeID &inSubShapeID2) override
  62. {
  63. mLog.push_back({ EType::RemoveCharacter, inCharacter, BodyID(), inOtherCharacterID, inSubShapeID2 });
  64. }
  65. void Clear()
  66. {
  67. mLog.clear();
  68. }
  69. size_t GetEntryCount() const
  70. {
  71. return mLog.size();
  72. }
  73. const LogEntry & GetEntry(size_t inIdx) const
  74. {
  75. return mLog[inIdx];
  76. }
  77. // Find first event with a particular type and involving a particular character vs body
  78. int Find(EType inType, const CharacterVirtual *inCharacter, const BodyID &inBody2) const
  79. {
  80. for (size_t i = 0; i < mLog.size(); ++i)
  81. {
  82. const LogEntry &e = mLog[i];
  83. if (e.mType == inType && e.mCharacter == inCharacter && e.mBody2 == inBody2 && e.mCharacterID2.IsInvalid())
  84. return int(i);
  85. }
  86. return -1;
  87. }
  88. // Check if event with a particular type and involving a particular character vs body
  89. bool Contains(EType inType, const CharacterVirtual *inCharacter, const BodyID &inBody2) const
  90. {
  91. return Find(inType, inCharacter, inBody2) >= 0;
  92. }
  93. // Find first event with a particular type and involving a particular character vs character
  94. int Find(EType inType, const CharacterVirtual *inCharacter, const CharacterID &inOtherCharacterID) const
  95. {
  96. for (size_t i = 0; i < mLog.size(); ++i)
  97. {
  98. const LogEntry &e = mLog[i];
  99. if (e.mType == inType && e.mCharacter == inCharacter && e.mBody2.IsInvalid() && e.mCharacterID2 == inOtherCharacterID)
  100. return int(i);
  101. }
  102. return -1;
  103. }
  104. // Check if event with a particular type and involving a particular character vs character
  105. bool Contains(EType inType, const CharacterVirtual *inCharacter, const CharacterID &inOtherCharacterID) const
  106. {
  107. return Find(inType, inCharacter, inOtherCharacterID) >= 0;
  108. }
  109. // Find first event with a particular type and involving a particular character vs body and sub shape ID
  110. int Find(EType inType, const CharacterVirtual *inCharacter, const BodyID &inBody2, const SubShapeID &inSubShapeID2) const
  111. {
  112. for (size_t i = 0; i < mLog.size(); ++i)
  113. {
  114. const LogEntry &e = mLog[i];
  115. if (e.mType == inType && e.mCharacter == inCharacter && e.mBody2 == inBody2 && e.mCharacterID2.IsInvalid() && e.mSubShapeID2 == inSubShapeID2)
  116. return int(i);
  117. }
  118. return -1;
  119. }
  120. // Check if a particular type and involving a particular character vs body and sub shape ID exists
  121. bool Contains(EType inType, const CharacterVirtual *inCharacter, const BodyID &inBody2, const SubShapeID &inSubShapeID2) const
  122. {
  123. return Find(inType, inCharacter, inBody2, inSubShapeID2) >= 0;
  124. }
  125. // Find first event with a particular type and involving a particular character vs character and sub shape ID
  126. int Find(EType inType, const CharacterVirtual *inCharacter, const CharacterID &inOtherCharacterID, const SubShapeID &inSubShapeID2) const
  127. {
  128. for (size_t i = 0; i < mLog.size(); ++i)
  129. {
  130. const LogEntry &e = mLog[i];
  131. if (e.mType == inType && e.mCharacter == inCharacter && e.mBody2.IsInvalid() && e.mCharacterID2 == inOtherCharacterID && e.mSubShapeID2 == inSubShapeID2)
  132. return int(i);
  133. }
  134. return -1;
  135. }
  136. // Check if a particular type and involving a particular character vs character and sub shape ID exists
  137. bool Contains(EType inType, const CharacterVirtual *inCharacter, const CharacterID &inOtherCharacterID, const SubShapeID &inSubShapeID2) const
  138. {
  139. return Find(inType, inCharacter, inOtherCharacterID, inSubShapeID2) >= 0;
  140. }
  141. private:
  142. Array<LogEntry> mLog;
  143. };