Obstacle.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Core/Context.h"
  5. #include "../Graphics/DebugRenderer.h"
  6. #include "../IO/Log.h"
  7. #include "../Navigation/DynamicNavigationMesh.h"
  8. #include "../Navigation/Obstacle.h"
  9. #include "../Navigation/NavigationEvents.h"
  10. #include "../Scene/Scene.h"
  11. #include "../DebugNew.h"
  12. namespace Urho3D
  13. {
  14. extern const char* NAVIGATION_CATEGORY;
  15. Obstacle::Obstacle(Context* context) :
  16. Component(context),
  17. height_(5.0f),
  18. radius_(5.0f),
  19. obstacleId_(0)
  20. {
  21. }
  22. Obstacle::~Obstacle()
  23. {
  24. if (obstacleId_ > 0 && ownerMesh_)
  25. ownerMesh_->RemoveObstacle(this);
  26. }
  27. void Obstacle::RegisterObject(Context* context)
  28. {
  29. context->RegisterFactory<Obstacle>(NAVIGATION_CATEGORY);
  30. URHO3D_COPY_BASE_ATTRIBUTES(Component);
  31. URHO3D_ACCESSOR_ATTRIBUTE("Radius", GetRadius, SetRadius, 5.0f, AM_DEFAULT);
  32. URHO3D_ACCESSOR_ATTRIBUTE("Height", GetHeight, SetHeight, 5.0f, AM_DEFAULT);
  33. }
  34. void Obstacle::OnSetEnabled()
  35. {
  36. if (ownerMesh_)
  37. {
  38. if (IsEnabledEffective())
  39. ownerMesh_->AddObstacle(this);
  40. else
  41. ownerMesh_->RemoveObstacle(this);
  42. }
  43. }
  44. void Obstacle::SetHeight(float newHeight)
  45. {
  46. height_ = newHeight;
  47. if (ownerMesh_)
  48. ownerMesh_->ObstacleChanged(this);
  49. MarkNetworkUpdate();
  50. }
  51. void Obstacle::SetRadius(float newRadius)
  52. {
  53. radius_ = newRadius;
  54. if (ownerMesh_)
  55. ownerMesh_->ObstacleChanged(this);
  56. MarkNetworkUpdate();
  57. }
  58. void Obstacle::OnNodeSet(Node* node)
  59. {
  60. if (node)
  61. node->AddListener(this);
  62. }
  63. void Obstacle::OnSceneSet(Scene* scene)
  64. {
  65. if (scene)
  66. {
  67. if (scene == node_)
  68. {
  69. URHO3D_LOGWARNING(GetTypeName() + " should not be created to the root scene node");
  70. return;
  71. }
  72. if (!ownerMesh_)
  73. ownerMesh_ = node_->GetParentComponent<DynamicNavigationMesh>(true);
  74. if (ownerMesh_)
  75. {
  76. ownerMesh_->AddObstacle(this);
  77. SubscribeToEvent(ownerMesh_, E_NAVIGATION_TILE_ADDED, URHO3D_HANDLER(Obstacle, HandleNavigationTileAdded));
  78. }
  79. }
  80. else
  81. {
  82. if (obstacleId_ > 0 && ownerMesh_)
  83. ownerMesh_->RemoveObstacle(this);
  84. UnsubscribeFromEvent(E_NAVIGATION_TILE_ADDED);
  85. ownerMesh_.Reset();
  86. }
  87. }
  88. void Obstacle::OnMarkedDirty(Node* node)
  89. {
  90. if (IsEnabledEffective() && ownerMesh_)
  91. {
  92. Scene* scene = GetScene();
  93. /// \hack If scene already unassigned, or if it's being destroyed, do nothing
  94. if (!scene || scene->Refs() == 0)
  95. return;
  96. // If within threaded update, update later
  97. if (scene->IsThreadedUpdate())
  98. {
  99. scene->DelayedMarkedDirty(this);
  100. return;
  101. }
  102. ownerMesh_->ObstacleChanged(this);
  103. }
  104. }
  105. void Obstacle::HandleNavigationTileAdded(StringHash eventType, VariantMap& eventData)
  106. {
  107. // Re-add obstacle if it is intersected with newly added tile
  108. const IntVector2 tile = eventData[NavigationTileAdded::P_TILE].GetIntVector2();
  109. if (IsEnabledEffective() && ownerMesh_ && ownerMesh_->IsObstacleInTile(this, tile))
  110. ownerMesh_->ObstacleChanged(this);
  111. }
  112. void Obstacle::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
  113. {
  114. if (debug && IsEnabledEffective())
  115. debug->AddCylinder(node_->GetWorldPosition(), radius_, height_, Color(0.0f, 1.0f, 1.0f), depthTest);
  116. }
  117. void Obstacle::DrawDebugGeometry(bool depthTest)
  118. {
  119. Scene* scene = GetScene();
  120. if (scene)
  121. DrawDebugGeometry(scene->GetComponent<DebugRenderer>(), depthTest);
  122. }
  123. }