targetable.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /*
  2. Copyright (C) 2001-2006, William Joseph.
  3. All Rights Reserved.
  4. This file is part of GtkRadiant.
  5. GtkRadiant is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. GtkRadiant is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GtkRadiant; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #if !defined(INCLUDED_TARGETABLE_H)
  18. #define INCLUDED_TARGETABLE_H
  19. #include <set>
  20. #include <map>
  21. #include "cullable.h"
  22. #include "renderable.h"
  23. #include "math/line.h"
  24. #include "render.h"
  25. #include "generic/callback.h"
  26. #include "selectionlib.h"
  27. #include "entitylib.h"
  28. #include "eclasslib.h"
  29. #include "stringio.h"
  30. class Targetable
  31. {
  32. public:
  33. virtual const Vector3& world_position() const = 0;
  34. };
  35. typedef std::set<Targetable*> targetables_t;
  36. extern const char* g_targetable_nameKey;
  37. targetables_t* getTargetables(const char* targetname);
  38. class EntityConnectionLine : public OpenGLRenderable
  39. {
  40. public:
  41. Vector3 start;
  42. Vector3 end;
  43. void render(RenderStateFlags state) const
  44. {
  45. float s1[2], s2[2];
  46. Vector3 dir(vector3_subtracted(end, start));
  47. double len = vector3_length(dir);
  48. vector3_scale(dir, 8.0 * (1.0 / len));
  49. s1[0] = dir[0] - dir[1];
  50. s1[1] = dir[0] + dir[1];
  51. s2[0] = dir[0] + dir[1];
  52. s2[1] = -dir[0] + dir[1];
  53. glBegin(GL_LINES);
  54. glVertex3fv(vector3_to_array(start));
  55. glVertex3fv(vector3_to_array(end));
  56. len*=0.0625; // half / 8
  57. Vector3 arrow(start);
  58. for (unsigned int i = 0, count = (len<32)? 1 : static_cast<unsigned int>(len*0.0625); i < count; i++)
  59. {
  60. vector3_add(arrow, vector3_scaled(dir, (len<32)?len:32));
  61. glVertex3fv(vector3_to_array(arrow));
  62. glVertex3f(arrow[0]+s1[0], arrow[1]+s1[1], arrow[2]+dir[2]);
  63. glVertex3fv(vector3_to_array(arrow));
  64. glVertex3f(arrow[0]+s2[0], arrow[1]+s2[1], arrow[2]+dir[2]);
  65. }
  66. glEnd();
  67. }
  68. };
  69. class TargetedEntity
  70. {
  71. Targetable& m_targetable;
  72. targetables_t* m_targets;
  73. void construct()
  74. {
  75. if(m_targets != 0)
  76. m_targets->insert(&m_targetable);
  77. }
  78. void destroy()
  79. {
  80. if(m_targets != 0)
  81. m_targets->erase(&m_targetable);
  82. }
  83. public:
  84. TargetedEntity(Targetable& targetable)
  85. : m_targetable(targetable), m_targets(getTargetables(""))
  86. {
  87. construct();
  88. }
  89. ~TargetedEntity()
  90. {
  91. destroy();
  92. }
  93. void targetnameChanged(const char* name)
  94. {
  95. destroy();
  96. m_targets = getTargetables(name);
  97. construct();
  98. }
  99. typedef MemberCaller1<TargetedEntity, const char*, &TargetedEntity::targetnameChanged> TargetnameChangedCaller;
  100. };
  101. class TargetingEntity
  102. {
  103. targetables_t* m_targets;
  104. public:
  105. TargetingEntity() :
  106. m_targets(getTargetables(""))
  107. {
  108. }
  109. void targetChanged(const char* target)
  110. {
  111. m_targets = getTargetables(target);
  112. }
  113. typedef MemberCaller1<TargetingEntity, const char*, &TargetingEntity::targetChanged> TargetChangedCaller;
  114. typedef targetables_t::iterator iterator;
  115. iterator begin() const
  116. {
  117. if(m_targets == 0)
  118. {
  119. return iterator();
  120. }
  121. return m_targets->begin();
  122. }
  123. iterator end() const
  124. {
  125. if(m_targets == 0)
  126. {
  127. return iterator();
  128. }
  129. return m_targets->end();
  130. }
  131. size_t size() const
  132. {
  133. if(m_targets == 0)
  134. {
  135. return 0;
  136. }
  137. return m_targets->size();
  138. }
  139. bool empty() const
  140. {
  141. return m_targets == 0 || m_targets->empty();
  142. }
  143. };
  144. template<typename Functor>
  145. void TargetingEntity_forEach(const TargetingEntity& targets, const Functor& functor)
  146. {
  147. for(TargetingEntity::iterator i = targets.begin(); i != targets.end(); ++i)
  148. {
  149. functor((*i)->world_position());
  150. }
  151. }
  152. typedef std::map<std::size_t, TargetingEntity> TargetingEntities;
  153. template<typename Functor>
  154. void TargetingEntities_forEach(const TargetingEntities& targetingEntities, const Functor& functor)
  155. {
  156. for(TargetingEntities::const_iterator i = targetingEntities.begin(); i != targetingEntities.end(); ++i)
  157. {
  158. TargetingEntity_forEach((*i).second, functor);
  159. }
  160. }
  161. class TargetLinesPushBack
  162. {
  163. RenderablePointVector& m_targetLines;
  164. const Vector3& m_worldPosition;
  165. const VolumeTest& m_volume;
  166. public:
  167. TargetLinesPushBack(RenderablePointVector& targetLines, const Vector3& worldPosition, const VolumeTest& volume) :
  168. m_targetLines(targetLines), m_worldPosition(worldPosition), m_volume(volume)
  169. {
  170. }
  171. void operator()(const Vector3& worldPosition) const
  172. {
  173. if(m_volume.TestLine(segment_for_startend(m_worldPosition, worldPosition)))
  174. {
  175. m_targetLines.push_back(PointVertex(reinterpret_cast<const Vertex3f&>(m_worldPosition)));
  176. m_targetLines.push_back(PointVertex(reinterpret_cast<const Vertex3f&>(worldPosition)));
  177. }
  178. }
  179. };
  180. class TargetKeys : public EntityKeyValues::Observer
  181. {
  182. TargetingEntities m_targetingEntities;
  183. Callback m_targetsChanged;
  184. bool readTargetKey(const char* key, std::size_t& index)
  185. {
  186. if(string_equal_n(key, "target", 6))
  187. {
  188. index = 0;
  189. if(string_empty(key + 6) || string_parse_size(key + 6, index))
  190. {
  191. return true;
  192. }
  193. }
  194. return false;
  195. }
  196. public:
  197. void setTargetsChanged(const Callback& targetsChanged)
  198. {
  199. m_targetsChanged = targetsChanged;
  200. }
  201. void targetsChanged()
  202. {
  203. m_targetsChanged();
  204. }
  205. void insert(const char* key, EntityKeyValues::Value& value)
  206. {
  207. std::size_t index;
  208. if(readTargetKey(key, index))
  209. {
  210. TargetingEntities::iterator i = m_targetingEntities.insert(TargetingEntities::value_type(index, TargetingEntity())).first;
  211. value.attach(TargetingEntity::TargetChangedCaller((*i).second));
  212. targetsChanged();
  213. }
  214. }
  215. void erase(const char* key, EntityKeyValues::Value& value)
  216. {
  217. std::size_t index;
  218. if(readTargetKey(key, index))
  219. {
  220. TargetingEntities::iterator i = m_targetingEntities.find(index);
  221. value.detach(TargetingEntity::TargetChangedCaller((*i).second));
  222. m_targetingEntities.erase(i);
  223. targetsChanged();
  224. }
  225. }
  226. const TargetingEntities& get() const
  227. {
  228. return m_targetingEntities;
  229. }
  230. };
  231. class RenderableTargetingEntity
  232. {
  233. TargetingEntity& m_targets;
  234. mutable RenderablePointVector m_target_lines;
  235. public:
  236. static Shader* m_state;
  237. RenderableTargetingEntity(TargetingEntity& targets)
  238. : m_targets(targets), m_target_lines(GL_LINES)
  239. {
  240. }
  241. void compile(const VolumeTest& volume, const Vector3& world_position) const
  242. {
  243. m_target_lines.clear();
  244. m_target_lines.reserve(m_targets.size() * 2);
  245. TargetingEntity_forEach(m_targets, TargetLinesPushBack(m_target_lines, world_position, volume));
  246. }
  247. void render(Renderer& renderer, const VolumeTest& volume, const Vector3& world_position) const
  248. {
  249. if(!m_targets.empty())
  250. {
  251. compile(volume, world_position);
  252. if(!m_target_lines.empty())
  253. {
  254. renderer.addRenderable(m_target_lines, g_matrix4_identity);
  255. }
  256. }
  257. }
  258. };
  259. class RenderableTargetingEntities
  260. {
  261. const TargetingEntities& m_targets;
  262. mutable RenderablePointVector m_target_lines;
  263. public:
  264. static Shader* m_state;
  265. RenderableTargetingEntities(const TargetingEntities& targets)
  266. : m_targets(targets), m_target_lines(GL_LINES)
  267. {
  268. }
  269. void compile(const VolumeTest& volume, const Vector3& world_position) const
  270. {
  271. m_target_lines.clear();
  272. TargetingEntities_forEach(m_targets, TargetLinesPushBack(m_target_lines, world_position, volume));
  273. }
  274. void render(Renderer& renderer, const VolumeTest& volume, const Vector3& world_position) const
  275. {
  276. if(!m_targets.empty())
  277. {
  278. compile(volume, world_position);
  279. if(!m_target_lines.empty())
  280. {
  281. renderer.addRenderable(m_target_lines, g_matrix4_identity);
  282. }
  283. }
  284. }
  285. };
  286. class TargetableInstance :
  287. public SelectableInstance,
  288. public Targetable,
  289. public EntityKeyValues::Observer
  290. {
  291. mutable Vertex3f m_position;
  292. EntityKeyValues& m_entity;
  293. TargetKeys m_targeting;
  294. TargetedEntity m_targeted;
  295. RenderableTargetingEntities m_renderable;
  296. public:
  297. TargetableInstance(
  298. const scene::Path& path,
  299. scene::Instance* parent,
  300. void* instance,
  301. InstanceTypeCastTable& casts,
  302. EntityKeyValues& entity,
  303. Targetable& targetable
  304. ) :
  305. SelectableInstance(path, parent, instance, casts),
  306. m_entity(entity),
  307. m_targeted(targetable),
  308. m_renderable(m_targeting.get())
  309. {
  310. m_entity.attach(*this);
  311. m_entity.attach(m_targeting);
  312. }
  313. ~TargetableInstance()
  314. {
  315. m_entity.detach(m_targeting);
  316. m_entity.detach(*this);
  317. }
  318. void setTargetsChanged(const Callback& targetsChanged)
  319. {
  320. m_targeting.setTargetsChanged(targetsChanged);
  321. }
  322. void targetsChanged()
  323. {
  324. m_targeting.targetsChanged();
  325. }
  326. void insert(const char* key, EntityKeyValues::Value& value)
  327. {
  328. if(string_equal(key, g_targetable_nameKey))
  329. {
  330. value.attach(TargetedEntity::TargetnameChangedCaller(m_targeted));
  331. }
  332. }
  333. void erase(const char* key, EntityKeyValues::Value& value)
  334. {
  335. if(string_equal(key, g_targetable_nameKey))
  336. {
  337. value.detach(TargetedEntity::TargetnameChangedCaller(m_targeted));
  338. }
  339. }
  340. const Vector3& world_position() const
  341. {
  342. #if 1
  343. const AABB& bounds = Instance::worldAABB();
  344. if(aabb_valid(bounds))
  345. {
  346. return bounds.origin;
  347. }
  348. #else
  349. const AABB& childBounds = Instance::childBounds();
  350. if(aabb_valid(childBounds))
  351. {
  352. return childBounds.origin;
  353. }
  354. #endif
  355. return localToWorld().t();
  356. }
  357. void render(Renderer& renderer, const VolumeTest& volume) const
  358. {
  359. renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
  360. renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials);
  361. m_renderable.render(renderer, volume, world_position());
  362. }
  363. const TargetingEntities& getTargeting() const
  364. {
  365. return m_targeting.get();
  366. }
  367. };
  368. class RenderableConnectionLines : public Renderable
  369. {
  370. typedef std::set<TargetableInstance*> TargetableInstances;
  371. TargetableInstances m_instances;
  372. public:
  373. void attach(TargetableInstance& instance)
  374. {
  375. ASSERT_MESSAGE(m_instances.find(&instance) == m_instances.end(), "cannot attach instance");
  376. m_instances.insert(&instance);
  377. }
  378. void detach(TargetableInstance& instance)
  379. {
  380. ASSERT_MESSAGE(m_instances.find(&instance) != m_instances.end(), "cannot detach instance");
  381. m_instances.erase(&instance);
  382. }
  383. void renderSolid(Renderer& renderer, const VolumeTest& volume) const
  384. {
  385. for(TargetableInstances::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i)
  386. {
  387. if((*i)->path().top().get().visible())
  388. {
  389. (*i)->render(renderer, volume);
  390. }
  391. }
  392. }
  393. void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
  394. {
  395. renderSolid(renderer, volume);
  396. }
  397. };
  398. typedef Static<RenderableConnectionLines> StaticRenderableConnectionLines;
  399. #endif