doom3group.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  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. ///\file
  18. ///\brief Represents any Doom3 entity which does not have a fixed size specified in its entity-definition (e.g. func_static).
  19. ///
  20. /// This entity behaves as a group only when the "model" key is empty or is the same as the "name" key. Otherwise it behaves as a model.
  21. /// When behaving as a group, the "origin" key is the translation to be applied to all brushes (not patches) grouped under this entity.
  22. /// When behaving as a model, the "origin", "angle" and "rotation" keys directly control the entity's local-to-parent transform.
  23. /// When either the "curve_Nurbs" or "curve_CatmullRomSpline" keys define a curve, the curve is rendered and can be edited.
  24. #include "doom3group.h"
  25. #include "cullable.h"
  26. #include "renderable.h"
  27. #include "editable.h"
  28. #include "modelskin.h"
  29. #include "selectionlib.h"
  30. #include "instancelib.h"
  31. #include "transformlib.h"
  32. #include "traverselib.h"
  33. #include "entitylib.h"
  34. #include "render.h"
  35. #include "eclasslib.h"
  36. #include "stream/stringstream.h"
  37. #include "pivot.h"
  38. #include "targetable.h"
  39. #include "origin.h"
  40. #include "angle.h"
  41. #include "rotation.h"
  42. #include "model.h"
  43. #include "filters.h"
  44. #include "namedentity.h"
  45. #include "keyobservers.h"
  46. #include "namekeys.h"
  47. #include "curve.h"
  48. #include "modelskinkey.h"
  49. #include "entity.h"
  50. inline void PointVertexArray_testSelect(PointVertex* first, std::size_t count, SelectionTest& test, SelectionIntersection& best)
  51. {
  52. test.TestLineStrip(
  53. VertexPointer(
  54. reinterpret_cast<VertexPointer::pointer>(&first->vertex),
  55. sizeof(PointVertex)
  56. ),
  57. IndexPointer::index_type(count),
  58. best
  59. );
  60. }
  61. class Doom3Group :
  62. public Bounded,
  63. public Snappable
  64. {
  65. EntityKeyValues m_entity;
  66. KeyObserverMap m_keyObservers;
  67. TraversableNodeSet m_traverse;
  68. MatrixTransform m_transform;
  69. SingletonModel m_model;
  70. OriginKey m_originKey;
  71. Vector3 m_origin;
  72. RotationKey m_rotationKey;
  73. Float9 m_rotation;
  74. ClassnameFilter m_filter;
  75. NamedEntity m_named;
  76. NameKeys m_nameKeys;
  77. TraversableObserverPairRelay m_traverseObservers;
  78. Doom3GroupOrigin m_funcStaticOrigin;
  79. RenderablePivot m_renderOrigin;
  80. RenderableNamedEntity m_renderName;
  81. ModelSkinKey m_skin;
  82. public:
  83. NURBSCurve m_curveNURBS;
  84. CatmullRomSpline m_curveCatmullRom;
  85. private:
  86. mutable AABB m_curveBounds;
  87. Callback m_transformChanged;
  88. Callback m_evaluateTransform;
  89. CopiedString m_name;
  90. CopiedString m_modelKey;
  91. bool m_isModel;
  92. scene::Traversable* m_traversable;
  93. void construct()
  94. {
  95. default_rotation(m_rotation);
  96. m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
  97. m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
  98. m_keyObservers.insert("model", Doom3Group::ModelChangedCaller(*this));
  99. m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
  100. m_keyObservers.insert("angle", RotationKey::AngleChangedCaller(m_rotationKey));
  101. m_keyObservers.insert("rotation", RotationKey::RotationChangedCaller(m_rotationKey));
  102. m_keyObservers.insert("name", NameChangedCaller(*this));
  103. m_keyObservers.insert(curve_Nurbs, NURBSCurve::CurveChangedCaller(m_curveNURBS));
  104. m_keyObservers.insert(curve_CatmullRomSpline, CatmullRomSpline::CurveChangedCaller(m_curveCatmullRom));
  105. m_keyObservers.insert("skin", ModelSkinKey::SkinChangedCaller(m_skin));
  106. m_traverseObservers.attach(m_funcStaticOrigin);
  107. m_isModel = false;
  108. m_nameKeys.setKeyIsName(keyIsNameDoom3Doom3Group);
  109. attachTraverse();
  110. m_entity.attach(m_keyObservers);
  111. }
  112. void destroy()
  113. {
  114. m_entity.detach(m_keyObservers);
  115. if(isModel())
  116. {
  117. detachModel();
  118. }
  119. else
  120. {
  121. detachTraverse();
  122. }
  123. m_traverseObservers.detach(m_funcStaticOrigin);
  124. }
  125. void attachModel()
  126. {
  127. m_traversable = &m_model.getTraversable();
  128. m_model.attach(&m_traverseObservers);
  129. }
  130. void detachModel()
  131. {
  132. m_traversable = 0;
  133. m_model.detach(&m_traverseObservers);
  134. }
  135. void attachTraverse()
  136. {
  137. m_traversable = &m_traverse;
  138. m_traverse.attach(&m_traverseObservers);
  139. }
  140. void detachTraverse()
  141. {
  142. m_traversable = 0;
  143. m_traverse.detach(&m_traverseObservers);
  144. }
  145. bool isModel() const
  146. {
  147. return m_isModel;
  148. }
  149. void setIsModel(bool newValue)
  150. {
  151. if(newValue && !m_isModel)
  152. {
  153. detachTraverse();
  154. attachModel();
  155. m_nameKeys.setKeyIsName(Static<KeyIsName>::instance().m_keyIsName);
  156. m_model.modelChanged(m_modelKey.c_str());
  157. }
  158. else if(!newValue && m_isModel)
  159. {
  160. detachModel();
  161. attachTraverse();
  162. m_nameKeys.setKeyIsName(keyIsNameDoom3Doom3Group);
  163. }
  164. m_isModel = newValue;
  165. updateTransform();
  166. }
  167. void updateIsModel()
  168. {
  169. setIsModel(!string_empty(m_modelKey.c_str()) && !string_equal(m_modelKey.c_str(), m_name.c_str()));
  170. }
  171. void nameChanged(const char* value)
  172. {
  173. m_name = value;
  174. updateIsModel();
  175. }
  176. typedef MemberCaller1<Doom3Group, const char*, &Doom3Group::nameChanged> NameChangedCaller;
  177. void modelChanged(const char* value)
  178. {
  179. m_modelKey = value;
  180. updateIsModel();
  181. if(isModel())
  182. {
  183. m_model.modelChanged(value);
  184. }
  185. else
  186. {
  187. m_model.modelChanged("");
  188. }
  189. }
  190. typedef MemberCaller1<Doom3Group, const char*, &Doom3Group::modelChanged> ModelChangedCaller;
  191. void updateTransform()
  192. {
  193. m_transform.localToParent() = g_matrix4_identity;
  194. if(isModel())
  195. {
  196. matrix4_translate_by_vec3(m_transform.localToParent(), m_originKey.m_origin);
  197. matrix4_multiply_by_matrix4(m_transform.localToParent(), rotation_toMatrix(m_rotationKey.m_rotation));
  198. }
  199. m_transformChanged();
  200. if(!isModel())
  201. {
  202. m_funcStaticOrigin.originChanged();
  203. }
  204. }
  205. typedef MemberCaller<Doom3Group, &Doom3Group::updateTransform> UpdateTransformCaller;
  206. void originChanged()
  207. {
  208. m_origin = m_originKey.m_origin;
  209. updateTransform();
  210. }
  211. typedef MemberCaller<Doom3Group, &Doom3Group::originChanged> OriginChangedCaller;
  212. void rotationChanged()
  213. {
  214. rotation_assign(m_rotation, m_rotationKey.m_rotation);
  215. updateTransform();
  216. }
  217. typedef MemberCaller<Doom3Group, &Doom3Group::rotationChanged> RotationChangedCaller;
  218. void skinChanged()
  219. {
  220. if(isModel())
  221. {
  222. scene::Node* node = m_model.getNode();
  223. if(node != 0)
  224. {
  225. Node_modelSkinChanged(*node);
  226. }
  227. }
  228. }
  229. typedef MemberCaller<Doom3Group, &Doom3Group::skinChanged> SkinChangedCaller;
  230. public:
  231. Doom3Group(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& boundsChanged, const Callback& evaluateTransform) :
  232. m_entity(eclass),
  233. m_originKey(OriginChangedCaller(*this)),
  234. m_origin(ORIGINKEY_IDENTITY),
  235. m_rotationKey(RotationChangedCaller(*this)),
  236. m_filter(m_entity, node),
  237. m_named(m_entity),
  238. m_nameKeys(m_entity),
  239. m_funcStaticOrigin(m_traverse, m_origin),
  240. m_renderName(m_named, g_vector3_identity),
  241. m_skin(SkinChangedCaller(*this)),
  242. m_curveNURBS(boundsChanged),
  243. m_curveCatmullRom(boundsChanged),
  244. m_transformChanged(transformChanged),
  245. m_evaluateTransform(evaluateTransform),
  246. m_traversable(0)
  247. {
  248. construct();
  249. }
  250. Doom3Group(const Doom3Group& other, scene::Node& node, const Callback& transformChanged, const Callback& boundsChanged, const Callback& evaluateTransform) :
  251. m_entity(other.m_entity),
  252. m_originKey(OriginChangedCaller(*this)),
  253. m_origin(ORIGINKEY_IDENTITY),
  254. m_rotationKey(RotationChangedCaller(*this)),
  255. m_filter(m_entity, node),
  256. m_named(m_entity),
  257. m_nameKeys(m_entity),
  258. m_funcStaticOrigin(m_traverse, m_origin),
  259. m_renderName(m_named, g_vector3_identity),
  260. m_skin(SkinChangedCaller(*this)),
  261. m_curveNURBS(boundsChanged),
  262. m_curveCatmullRom(boundsChanged),
  263. m_transformChanged(transformChanged),
  264. m_evaluateTransform(evaluateTransform),
  265. m_traversable(0)
  266. {
  267. construct();
  268. }
  269. ~Doom3Group()
  270. {
  271. destroy();
  272. }
  273. InstanceCounter m_instanceCounter;
  274. void instanceAttach(const scene::Path& path)
  275. {
  276. if(++m_instanceCounter.m_count == 1)
  277. {
  278. m_filter.instanceAttach();
  279. m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
  280. m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end()));
  281. m_funcStaticOrigin.enable();
  282. }
  283. }
  284. void instanceDetach(const scene::Path& path)
  285. {
  286. if(--m_instanceCounter.m_count == 0)
  287. {
  288. m_funcStaticOrigin.disable();
  289. m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end()));
  290. m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
  291. m_filter.instanceDetach();
  292. }
  293. }
  294. EntityKeyValues& getEntity()
  295. {
  296. return m_entity;
  297. }
  298. const EntityKeyValues& getEntity() const
  299. {
  300. return m_entity;
  301. }
  302. scene::Traversable& getTraversable()
  303. {
  304. return *m_traversable;
  305. }
  306. Namespaced& getNamespaced()
  307. {
  308. return m_nameKeys;
  309. }
  310. Nameable& getNameable()
  311. {
  312. return m_named;
  313. }
  314. TransformNode& getTransformNode()
  315. {
  316. return m_transform;
  317. }
  318. ModelSkin& getModelSkin()
  319. {
  320. return m_skin.get();
  321. }
  322. void attach(scene::Traversable::Observer* observer)
  323. {
  324. m_traverseObservers.attach(*observer);
  325. }
  326. void detach(scene::Traversable::Observer* observer)
  327. {
  328. m_traverseObservers.detach(*observer);
  329. }
  330. const AABB& localAABB() const
  331. {
  332. m_curveBounds = m_curveNURBS.m_bounds;
  333. aabb_extend_by_aabb_safe(m_curveBounds, m_curveCatmullRom.m_bounds);
  334. return m_curveBounds;
  335. }
  336. void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
  337. {
  338. if(isModel() && selected)
  339. {
  340. m_renderOrigin.render(renderer, volume, localToWorld);
  341. }
  342. renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
  343. renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials);
  344. if(!m_curveNURBS.m_renderCurve.m_vertices.empty())
  345. {
  346. renderer.addRenderable(m_curveNURBS.m_renderCurve, localToWorld);
  347. }
  348. if(!m_curveCatmullRom.m_renderCurve.m_vertices.empty())
  349. {
  350. renderer.addRenderable(m_curveCatmullRom.m_renderCurve, localToWorld);
  351. }
  352. }
  353. void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
  354. {
  355. renderSolid(renderer, volume, localToWorld, selected);
  356. if(g_showNames && isModel())
  357. {
  358. renderer.addRenderable(m_renderName, localToWorld);
  359. }
  360. }
  361. void testSelect(Selector& selector, SelectionTest& test, SelectionIntersection& best)
  362. {
  363. PointVertexArray_testSelect(&m_curveNURBS.m_renderCurve.m_vertices[0], m_curveNURBS.m_renderCurve.m_vertices.size(), test, best);
  364. PointVertexArray_testSelect(&m_curveCatmullRom.m_renderCurve.m_vertices[0], m_curveCatmullRom.m_renderCurve.m_vertices.size(), test, best);
  365. }
  366. void translate(const Vector3& translation)
  367. {
  368. m_origin = origin_translated(m_origin, translation);
  369. }
  370. void rotate(const Quaternion& rotation)
  371. {
  372. rotation_rotate(m_rotation, rotation);
  373. }
  374. void snapto(float snap)
  375. {
  376. m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
  377. m_originKey.write(&m_entity);
  378. }
  379. void revertTransform()
  380. {
  381. m_origin = m_originKey.m_origin;
  382. rotation_assign(m_rotation, m_rotationKey.m_rotation);
  383. m_curveNURBS.m_controlPointsTransformed = m_curveNURBS.m_controlPoints;
  384. m_curveCatmullRom.m_controlPointsTransformed = m_curveCatmullRom.m_controlPoints;
  385. }
  386. void freezeTransform()
  387. {
  388. m_originKey.m_origin = m_origin;
  389. m_originKey.write(&m_entity);
  390. rotation_assign(m_rotationKey.m_rotation, m_rotation);
  391. m_rotationKey.write(&m_entity);
  392. m_curveNURBS.m_controlPoints = m_curveNURBS.m_controlPointsTransformed;
  393. ControlPoints_write(m_curveNURBS.m_controlPoints, curve_Nurbs, m_entity);
  394. m_curveCatmullRom.m_controlPoints = m_curveCatmullRom.m_controlPointsTransformed;
  395. ControlPoints_write(m_curveCatmullRom.m_controlPoints, curve_CatmullRomSpline, m_entity);
  396. }
  397. void transformChanged()
  398. {
  399. revertTransform();
  400. m_evaluateTransform();
  401. updateTransform();
  402. m_curveNURBS.curveChanged();
  403. m_curveCatmullRom.curveChanged();
  404. }
  405. typedef MemberCaller<Doom3Group, &Doom3Group::transformChanged> TransformChangedCaller;
  406. };
  407. class ControlPointAddBounds
  408. {
  409. AABB& m_bounds;
  410. public:
  411. ControlPointAddBounds(AABB& bounds) : m_bounds(bounds)
  412. {
  413. }
  414. void operator()(const Vector3& point) const
  415. {
  416. aabb_extend_by_point_safe(m_bounds, point);
  417. }
  418. };
  419. class Doom3GroupInstance :
  420. public TargetableInstance,
  421. public TransformModifier,
  422. public Renderable,
  423. public SelectionTestable,
  424. public ComponentSelectionTestable,
  425. public ComponentEditable,
  426. public ComponentSnappable
  427. {
  428. class TypeCasts
  429. {
  430. InstanceTypeCastTable m_casts;
  431. public:
  432. TypeCasts()
  433. {
  434. m_casts = TargetableInstance::StaticTypeCasts::instance().get();
  435. InstanceContainedCast<Doom3GroupInstance, Bounded>::install(m_casts);
  436. InstanceStaticCast<Doom3GroupInstance, Renderable>::install(m_casts);
  437. InstanceStaticCast<Doom3GroupInstance, SelectionTestable>::install(m_casts);
  438. InstanceStaticCast<Doom3GroupInstance, ComponentSelectionTestable>::install(m_casts);
  439. InstanceStaticCast<Doom3GroupInstance, ComponentEditable>::install(m_casts);
  440. InstanceStaticCast<Doom3GroupInstance, ComponentSnappable>::install(m_casts);
  441. InstanceStaticCast<Doom3GroupInstance, Transformable>::install(m_casts);
  442. InstanceIdentityCast<Doom3GroupInstance>::install(m_casts);
  443. }
  444. InstanceTypeCastTable& get()
  445. {
  446. return m_casts;
  447. }
  448. };
  449. Doom3Group& m_contained;
  450. CurveEdit m_curveNURBS;
  451. CurveEdit m_curveCatmullRom;
  452. mutable AABB m_aabb_component;
  453. public:
  454. typedef LazyStatic<TypeCasts> StaticTypeCasts;
  455. Bounded& get(NullType<Bounded>)
  456. {
  457. return m_contained;
  458. }
  459. STRING_CONSTANT(Name, "Doom3GroupInstance");
  460. Doom3GroupInstance(const scene::Path& path, scene::Instance* parent, Doom3Group& contained) :
  461. TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this),
  462. TransformModifier(Doom3Group::TransformChangedCaller(contained), ApplyTransformCaller(*this)),
  463. m_contained(contained),
  464. m_curveNURBS(m_contained.m_curveNURBS.m_controlPointsTransformed, SelectionChangedComponentCaller(*this)),
  465. m_curveCatmullRom(m_contained.m_curveCatmullRom.m_controlPointsTransformed, SelectionChangedComponentCaller(*this))
  466. {
  467. m_contained.instanceAttach(Instance::path());
  468. m_contained.m_curveNURBS.attach(CurveEdit::CurveChangedCaller(m_curveNURBS));
  469. m_contained.m_curveCatmullRom.attach(CurveEdit::CurveChangedCaller(m_curveCatmullRom));
  470. StaticRenderableConnectionLines::instance().attach(*this);
  471. }
  472. ~Doom3GroupInstance()
  473. {
  474. StaticRenderableConnectionLines::instance().detach(*this);
  475. m_contained.m_curveCatmullRom.detach(CurveEdit::CurveChangedCaller(m_curveCatmullRom));
  476. m_contained.m_curveNURBS.detach(CurveEdit::CurveChangedCaller(m_curveNURBS));
  477. m_contained.instanceDetach(Instance::path());
  478. }
  479. void renderSolid(Renderer& renderer, const VolumeTest& volume) const
  480. {
  481. m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
  482. m_curveNURBS.renderComponentsSelected(renderer, volume, localToWorld());
  483. m_curveCatmullRom.renderComponentsSelected(renderer, volume, localToWorld());
  484. }
  485. void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
  486. {
  487. m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
  488. m_curveNURBS.renderComponentsSelected(renderer, volume, localToWorld());
  489. m_curveCatmullRom.renderComponentsSelected(renderer, volume, localToWorld());
  490. }
  491. void renderComponents(Renderer& renderer, const VolumeTest& volume) const
  492. {
  493. if(GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex)
  494. {
  495. m_curveNURBS.renderComponents(renderer, volume, localToWorld());
  496. m_curveCatmullRom.renderComponents(renderer, volume, localToWorld());
  497. }
  498. }
  499. void testSelect(Selector& selector, SelectionTest& test)
  500. {
  501. test.BeginMesh(localToWorld());
  502. SelectionIntersection best;
  503. m_contained.testSelect(selector, test, best);
  504. if(best.valid())
  505. {
  506. Selector_add(selector, getSelectable(), best);
  507. }
  508. }
  509. bool isSelectedComponents() const
  510. {
  511. return m_curveNURBS.isSelected() || m_curveCatmullRom.isSelected();
  512. }
  513. void setSelectedComponents(bool selected, SelectionSystem::EComponentMode mode)
  514. {
  515. if(mode == SelectionSystem::eVertex)
  516. {
  517. m_curveNURBS.setSelected(selected);
  518. m_curveCatmullRom.setSelected(selected);
  519. }
  520. }
  521. void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode)
  522. {
  523. if(mode == SelectionSystem::eVertex)
  524. {
  525. test.BeginMesh(localToWorld());
  526. m_curveNURBS.testSelect(selector, test);
  527. m_curveCatmullRom.testSelect(selector, test);
  528. }
  529. }
  530. void transformComponents(const Matrix4& matrix)
  531. {
  532. if(m_curveNURBS.isSelected())
  533. {
  534. m_curveNURBS.transform(matrix);
  535. }
  536. if(m_curveCatmullRom.isSelected())
  537. {
  538. m_curveCatmullRom.transform(matrix);
  539. }
  540. }
  541. const AABB& getSelectedComponentsBounds() const
  542. {
  543. m_aabb_component = AABB();
  544. m_curveNURBS.forEachSelected(ControlPointAddBounds(m_aabb_component));
  545. m_curveCatmullRom.forEachSelected(ControlPointAddBounds(m_aabb_component));
  546. return m_aabb_component;
  547. }
  548. void snapComponents(float snap)
  549. {
  550. if(m_curveNURBS.isSelected())
  551. {
  552. m_curveNURBS.snapto(snap);
  553. m_curveNURBS.write(curve_Nurbs, m_contained.getEntity());
  554. }
  555. if(m_curveCatmullRom.isSelected())
  556. {
  557. m_curveCatmullRom.snapto(snap);
  558. m_curveCatmullRom.write(curve_CatmullRomSpline, m_contained.getEntity());
  559. }
  560. }
  561. void evaluateTransform()
  562. {
  563. if(getType() == TRANSFORM_PRIMITIVE)
  564. {
  565. m_contained.translate(getTranslation());
  566. m_contained.rotate(getRotation());
  567. }
  568. else
  569. {
  570. transformComponents(calculateTransform());
  571. }
  572. }
  573. void applyTransform()
  574. {
  575. m_contained.revertTransform();
  576. evaluateTransform();
  577. m_contained.freezeTransform();
  578. }
  579. typedef MemberCaller<Doom3GroupInstance, &Doom3GroupInstance::applyTransform> ApplyTransformCaller;
  580. void selectionChangedComponent(const Selectable& selectable)
  581. {
  582. GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable);
  583. GlobalSelectionSystem().onComponentSelection(*this, selectable);
  584. }
  585. typedef MemberCaller1<Doom3GroupInstance, const Selectable&, &Doom3GroupInstance::selectionChangedComponent> SelectionChangedComponentCaller;
  586. };
  587. class Doom3GroupNode :
  588. public scene::Node::Symbiot,
  589. public scene::Instantiable,
  590. public scene::Cloneable,
  591. public scene::Traversable::Observer
  592. {
  593. class TypeCasts
  594. {
  595. NodeTypeCastTable m_casts;
  596. public:
  597. TypeCasts()
  598. {
  599. NodeStaticCast<Doom3GroupNode, scene::Instantiable>::install(m_casts);
  600. NodeStaticCast<Doom3GroupNode, scene::Cloneable>::install(m_casts);
  601. NodeContainedCast<Doom3GroupNode, scene::Traversable>::install(m_casts);
  602. NodeContainedCast<Doom3GroupNode, Snappable>::install(m_casts);
  603. NodeContainedCast<Doom3GroupNode, TransformNode>::install(m_casts);
  604. NodeContainedCast<Doom3GroupNode, Entity>::install(m_casts);
  605. NodeContainedCast<Doom3GroupNode, Nameable>::install(m_casts);
  606. NodeContainedCast<Doom3GroupNode, Namespaced>::install(m_casts);
  607. NodeContainedCast<Doom3GroupNode, ModelSkin>::install(m_casts);
  608. }
  609. NodeTypeCastTable& get()
  610. {
  611. return m_casts;
  612. }
  613. };
  614. scene::Node m_node;
  615. InstanceSet m_instances;
  616. Doom3Group m_contained;
  617. void construct()
  618. {
  619. m_contained.attach(this);
  620. }
  621. void destroy()
  622. {
  623. m_contained.detach(this);
  624. }
  625. public:
  626. typedef LazyStatic<TypeCasts> StaticTypeCasts;
  627. scene::Traversable& get(NullType<scene::Traversable>)
  628. {
  629. return m_contained.getTraversable();
  630. }
  631. Snappable& get(NullType<Snappable>)
  632. {
  633. return m_contained;
  634. }
  635. TransformNode& get(NullType<TransformNode>)
  636. {
  637. return m_contained.getTransformNode();
  638. }
  639. Entity& get(NullType<Entity>)
  640. {
  641. return m_contained.getEntity();
  642. }
  643. Nameable& get(NullType<Nameable>)
  644. {
  645. return m_contained.getNameable();
  646. }
  647. Namespaced& get(NullType<Namespaced>)
  648. {
  649. return m_contained.getNamespaced();
  650. }
  651. ModelSkin& get(NullType<ModelSkin>)
  652. {
  653. return m_contained.getModelSkin();
  654. }
  655. Doom3GroupNode(EntityClass* eclass) :
  656. m_node(this, this, StaticTypeCasts::instance().get()),
  657. m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSet::BoundsChangedCaller(m_instances), InstanceSetEvaluateTransform<Doom3GroupInstance>::Caller(m_instances))
  658. {
  659. construct();
  660. }
  661. Doom3GroupNode(const Doom3GroupNode& other) :
  662. scene::Node::Symbiot(other),
  663. scene::Instantiable(other),
  664. scene::Cloneable(other),
  665. scene::Traversable::Observer(other),
  666. m_node(this, this, StaticTypeCasts::instance().get()),
  667. m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSet::BoundsChangedCaller(m_instances), InstanceSetEvaluateTransform<Doom3GroupInstance>::Caller(m_instances))
  668. {
  669. construct();
  670. }
  671. ~Doom3GroupNode()
  672. {
  673. destroy();
  674. }
  675. void release()
  676. {
  677. delete this;
  678. }
  679. scene::Node& node()
  680. {
  681. return m_node;
  682. }
  683. scene::Node& clone() const
  684. {
  685. return (new Doom3GroupNode(*this))->node();
  686. }
  687. void insert(scene::Node& child)
  688. {
  689. m_instances.insert(child);
  690. }
  691. void erase(scene::Node& child)
  692. {
  693. m_instances.erase(child);
  694. }
  695. scene::Instance* create(const scene::Path& path, scene::Instance* parent)
  696. {
  697. return new Doom3GroupInstance(path, parent, m_contained);
  698. }
  699. void forEachInstance(const scene::Instantiable::Visitor& visitor)
  700. {
  701. m_instances.forEachInstance(visitor);
  702. }
  703. void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
  704. {
  705. m_instances.insert(observer, path, instance);
  706. }
  707. scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
  708. {
  709. return m_instances.erase(observer, path);
  710. }
  711. };
  712. void Doom3Group_construct()
  713. {
  714. CurveEdit::Type::instance().m_controlsShader = GlobalShaderCache().capture("$POINT");
  715. CurveEdit::Type::instance().m_selectedShader = GlobalShaderCache().capture("$SELPOINT");
  716. }
  717. void Doom3Group_destroy()
  718. {
  719. GlobalShaderCache().release("$SELPOINT");
  720. GlobalShaderCache().release("$POINT");
  721. }
  722. scene::Node& New_Doom3Group(EntityClass* eclass)
  723. {
  724. return (new Doom3GroupNode(eclass))->node();
  725. }