RectDetector.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. //===========================================================================================================================
  2. // Spirenkov Maxim, 2003
  3. //===========================================================================================================================//
  4. // Mission objects
  5. //===========================================================================================================================
  6. // RectDetector
  7. //============================================================================================
  8. #include "RectDetector.h"
  9. //============================================================================================
  10. RectDetector::RectDetector()
  11. {
  12. Show(false);
  13. isDown = false;
  14. ignoreDistance = 5.0f;
  15. }
  16. RectDetector::~RectDetector()
  17. {
  18. }
  19. //============================================================================================
  20. //Инициализировать объект
  21. bool RectDetector::Create(MOPReader & reader)
  22. {
  23. isDown = false;
  24. target.Reset();
  25. ignoreDistance = 5.0f;
  26. if(!DetectorObject::Create(reader)) return false;
  27. //Получим идентификатор объекта
  28. targetID = reader.String();
  29. //Получим позицию
  30. Vector pos = reader.Position();
  31. //Получим направление
  32. Vector ang = reader.Angles();
  33. mtx.Build(ang, pos);
  34. //Плоскость
  35. plane.normal = mtx.vz;
  36. plane.Move(pos);
  37. //Матрица преобразования
  38. imtx = mtx;
  39. imtx.Inverse();
  40. //Получим размеры
  41. width05 = reader.Float()*0.5f;
  42. height05 = reader.Float()*0.5f;
  43. //Имя отсылаемого события
  44. event.Init(reader);
  45. //Состояние
  46. Activate(reader.Bool());
  47. //Сбрасывать ли состояние после срабатывания
  48. autoReset = reader.Bool();
  49. //Одно или двух сторонний
  50. isDoubleSide = reader.Bool();
  51. //
  52. ignoreDistance = reader.Float();
  53. //Ищим объект среди существующих
  54. return UpdateTarget();
  55. }
  56. //Получить матрицу объекта
  57. Matrix & RectDetector::GetMatrix(Matrix & mtx)
  58. {
  59. return (mtx = this->mtx);
  60. }
  61. //Инициализировать объект
  62. bool RectDetector::EditMode_Create(MOPReader & reader)
  63. {
  64. isDown = false;
  65. if(!DetectorObject::Create(reader)) return false;
  66. SetUpdate(&RectDetector::EditModeWork, ML_ALPHA5);
  67. Create(reader);
  68. highlight = 0.0f;
  69. resetTime = 0.0f;
  70. return true;
  71. }
  72. //Обновить параметры
  73. bool RectDetector::EditMode_Update(MOPReader & reader)
  74. {
  75. Create(reader);
  76. return true;
  77. }
  78. //Получить размеры описывающего ящика
  79. void RectDetector::EditMode_GetSelectBox(Vector & min, Vector & max)
  80. {
  81. min = Vector(-width05 - 0.1f, -height05 - 0.1f, -0.1f);
  82. max = Vector(width05 + 0.1f, height05 + 0.1f, 0.1f);
  83. }
  84. //Активация детектора
  85. void RectDetector::ActivateDetector(const char * initiatorID)
  86. {
  87. if(!EditMode_IsOn())
  88. {
  89. LogicDebug("Triggering");
  90. event.Activate(Mission(), false);
  91. }
  92. }
  93. //Активировать
  94. void RectDetector::Activate(bool isActive)
  95. {
  96. DetectorObject::Activate(isActive);
  97. if(IsActive())
  98. {
  99. LogicDebug("Activate");
  100. SetUpdate(&RectDetector::Work, ML_TRIGGERS);
  101. }else{
  102. LogicDebug("Deactivate");
  103. DelUpdate(&RectDetector::Work);
  104. }
  105. }
  106. //============================================================================================
  107. //Работа детектора
  108. void _cdecl RectDetector::Work(float dltTime, long level)
  109. {
  110. if(!target.Validate())
  111. {
  112. target.Reset();
  113. return;
  114. }
  115. //Отработали и не сами себя востанавливаем - неработаем
  116. if(isDown && !autoReset) return;
  117. //Не активны - не работаем
  118. if(!IsActive()) return;
  119. //Анализируем
  120. Matrix mtx;
  121. target.Ptr()->GetMatrix(mtx);
  122. //Проверяем пересечение плоскости
  123. Vector res;
  124. isDown = false;
  125. if(plane.Intersection(targetPos, mtx.pos, res))
  126. {
  127. if(double(~(targetPos - mtx.pos)) < double(ignoreDistance)*ignoreDistance)
  128. {
  129. //Произошло пересечение плоскости
  130. res = imtx*res;
  131. if(-width05 <= res.x && res.x <= width05)
  132. {
  133. if(-height05 <= res.y && res.y <= height05)
  134. {
  135. isDown = true;
  136. if(!isDoubleSide)
  137. {
  138. if(((mtx.pos - targetPos) | plane.n) > 0.0f) isDown = false;
  139. }
  140. }
  141. }
  142. }
  143. }
  144. targetPos = mtx.pos;
  145. if(isDown)
  146. {
  147. if(!EditMode_IsOn())
  148. {
  149. ActivateDetector(target.Ptr()->GetObjectID().c_str());
  150. }else{
  151. highlight = 1.0f;
  152. resetTime = 4.0f;
  153. }
  154. }
  155. }
  156. //Нарисовать детектор
  157. void _cdecl RectDetector::EditModeWork(float dltTime, long level)
  158. {
  159. if(!Mission().EditMode_IsAdditionalDraw()) return;
  160. if(!EditMode_IsVisible()) return;
  161. //Структура вершины
  162. #pragma pack(push, 1)
  163. struct Vertex{ Vector p; dword c; };
  164. #pragma pack(pop)
  165. //Работа детектора
  166. Work(dltTime, level);
  167. //Обновляем состояние
  168. highlight -= dltTime;
  169. if(highlight < 0.0f) highlight = 0.0f;
  170. if(isDown)
  171. {
  172. resetTime -= dltTime;
  173. if(resetTime <= 0.0f)
  174. {
  175. isDown = false;
  176. resetTime = 0.0f;
  177. }
  178. }
  179. //Проверяем наличие объекта
  180. if(!target.Validate())
  181. {
  182. UpdateTarget();
  183. }
  184. //Выбираем цвета
  185. Color front, back;
  186. if(target.Validate())
  187. {
  188. if(IsActive())
  189. {
  190. if(!isDown)
  191. {
  192. front = Color(0.0f, 0.8f, 0.0f, 0.8f);
  193. back = Color(0.0f, 0.4f, 0.0f, 0.8f);
  194. }else{
  195. front = Color(0.8f, 0.0f, 0.0f, 0.8f);
  196. back = Color(0.4f, 0.0f, 0.0f, 0.8f);
  197. }
  198. }else{
  199. front = Color(0.8f, 0.8f, 0.8f, 0.5f);
  200. back = Color(0.4f, 0.4f, 0.4f, 0.5f);
  201. }
  202. }else{
  203. front = Color(1.0f, 0.0f, 1.0f, 0.8f);
  204. back = Color(0.6f, 0.0f, 0.6f, 0.8f);
  205. }
  206. front += highlight;
  207. back += highlight;
  208. front.Clamp();
  209. back.Clamp();
  210. dword dfront = front.GetDword();
  211. dword dback = back.GetDword();
  212. //Рисуем
  213. Vertex v[12];
  214. v[0].p.x = -width05; v[0].p.y = -height05; v[0].p.z = 0.0f; v[0].c = dfront;
  215. v[1].p.x = -width05; v[1].p.y = height05; v[1].p.z = 0.0f; v[1].c = dfront;
  216. v[2].p.x = width05; v[2].p.y = height05; v[2].p.z = 0.0f; v[2].c = dfront;
  217. v[3].p.x = -width05; v[3].p.y = -height05; v[3].p.z = 0.0f; v[3].c = dfront;
  218. v[4].p.x = width05; v[4].p.y = height05; v[4].p.z = 0.0f; v[4].c = dfront;
  219. v[5].p.x = width05; v[5].p.y = -height05; v[5].p.z = 0.0f; v[5].c = dfront;
  220. v[6].p.x = -width05; v[6].p.y = -height05; v[6].p.z = 0.0f; v[6].c = dback;
  221. v[7].p.x = width05; v[7].p.y = height05; v[7].p.z = 0.0f; v[7].c = dback;
  222. v[8].p.x = -width05; v[8].p.y = height05; v[8].p.z = 0.0f; v[8].c = dback;
  223. v[9].p.x = -width05; v[9].p.y = -height05; v[9].p.z = 0.0f; v[9].c = dback;
  224. v[10].p.x = width05; v[10].p.y = -height05; v[10].p.z = 0.0f; v[10].c = dback;
  225. v[11].p.x = width05; v[11].p.y = height05; v[11].p.z = 0.0f; v[11].c = dback;
  226. Render().SetWorld(mtx);
  227. ShaderId id;
  228. Render().GetShaderId("ShowDetector", id);
  229. Render().DrawPrimitiveUP(id, PT_TRIANGLELIST, 4, v, sizeof(Vertex));
  230. if(EditMode_IsSelect())
  231. {
  232. Render().Print(mtx.pos, -1.0f, -1.0f, 0xffffffff, "Object id: %s", GetObjectID().c_str());
  233. Render().Print(mtx.pos, -1.0f, 0.0f, 0xffffffff, "Target: %s", targetID.c_str());
  234. Render().Print(mtx.pos, -1.0f, 1.0f, 0xffffffff, IsActive() ? "State: on" : "State: off");
  235. }
  236. }
  237. //Обновить цель
  238. bool RectDetector::UpdateTarget()
  239. {
  240. if(!FindObject(targetID, target)) return false;
  241. Matrix mtx(true);
  242. target.Ptr()->GetMatrix(mtx);
  243. targetPos = mtx.pos;
  244. return true;
  245. }
  246. //============================================================================================
  247. //Параметры инициализации
  248. //============================================================================================
  249. MOP_BEGINLISTCG(RectDetector, "Rect detector", '1.00', 0x0fffffff, "Detector triggering if mission object intersection it.", "Logic")
  250. MOP_STRING("Object id", "Player")
  251. MOP_POSITION("Position", Vector(0.0f))
  252. MOP_ANGLES("Angles", Vector(0.0f))
  253. MOP_FLOATEX("Width", 1.0f, 0.01f, 1000000.0f)
  254. MOP_FLOATEX("Height", 1.0f, 0.01f, 1000000.0f)
  255. MOP_MISSIONTRIGGERG("Events", "")
  256. MOP_BOOL("Active", true)
  257. MOP_BOOL("Auto reset", false)
  258. MOP_BOOL("Double side", true)
  259. MOP_FLOATEXC("Ignore distance", 5.0f, 0.1f, 1000000.0f, "If length of target path per frame more then this distance, detector ignore that moving")
  260. MOP_ENDLIST(RectDetector)