miscmodel.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  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 the Quake3 misc_model entity.
  19. ///
  20. /// This entity displays the model specified in its "model" key.
  21. /// The "origin", "angles" and "modelscale*" keys directly control the entity's local-to-parent transform.
  22. #include "cullable.h"
  23. #include "renderable.h"
  24. #include "editable.h"
  25. #include "selectionlib.h"
  26. #include "instancelib.h"
  27. #include "transformlib.h"
  28. #include "traverselib.h"
  29. #include "entitylib.h"
  30. #include "eclasslib.h"
  31. #include "render.h"
  32. #include "pivot.h"
  33. #include "targetable.h"
  34. #include "origin.h"
  35. #include "angles.h"
  36. #include "scale.h"
  37. #include "model.h"
  38. #include "filters.h"
  39. #include "namedentity.h"
  40. #include "keyobservers.h"
  41. #include "namekeys.h"
  42. #include "entity.h"
  43. class MiscModel :
  44. public Snappable
  45. {
  46. EntityKeyValues m_entity;
  47. KeyObserverMap m_keyObservers;
  48. MatrixTransform m_transform;
  49. OriginKey m_originKey;
  50. Vector3 m_origin;
  51. AnglesKey m_anglesKey;
  52. Vector3 m_angles;
  53. ScaleKey m_scaleKey;
  54. Vector3 m_scale;
  55. SingletonModel m_model;
  56. ClassnameFilter m_filter;
  57. NamedEntity m_named;
  58. NameKeys m_nameKeys;
  59. RenderablePivot m_renderOrigin;
  60. RenderableNamedEntity m_renderName;
  61. Callback m_transformChanged;
  62. Callback m_evaluateTransform;
  63. void construct()
  64. {
  65. m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
  66. m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
  67. m_keyObservers.insert("model", SingletonModel::ModelChangedCaller(m_model));
  68. m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
  69. m_keyObservers.insert("angle", AnglesKey::AngleChangedCaller(m_anglesKey));
  70. m_keyObservers.insert("angles", AnglesKey::AnglesChangedCaller(m_anglesKey));
  71. m_keyObservers.insert("modelscale", ScaleKey::UniformScaleChangedCaller(m_scaleKey));
  72. m_keyObservers.insert("modelscale_vec", ScaleKey::ScaleChangedCaller(m_scaleKey));
  73. }
  74. void updateTransform()
  75. {
  76. m_transform.localToParent() = g_matrix4_identity;
  77. matrix4_transform_by_euler_xyz_degrees(m_transform.localToParent(), m_origin, m_angles, m_scale);
  78. m_transformChanged();
  79. }
  80. void originChanged()
  81. {
  82. m_origin = m_originKey.m_origin;
  83. updateTransform();
  84. }
  85. typedef MemberCaller<MiscModel, &MiscModel::originChanged> OriginChangedCaller;
  86. void anglesChanged()
  87. {
  88. m_angles = m_anglesKey.m_angles;
  89. updateTransform();
  90. }
  91. typedef MemberCaller<MiscModel, &MiscModel::anglesChanged> AnglesChangedCaller;
  92. void scaleChanged()
  93. {
  94. m_scale = m_scaleKey.m_scale;
  95. updateTransform();
  96. }
  97. typedef MemberCaller<MiscModel, &MiscModel::scaleChanged> ScaleChangedCaller;
  98. public:
  99. MiscModel(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
  100. m_entity(eclass),
  101. m_originKey(OriginChangedCaller(*this)),
  102. m_origin(ORIGINKEY_IDENTITY),
  103. m_anglesKey(AnglesChangedCaller(*this)),
  104. m_angles(ANGLESKEY_IDENTITY),
  105. m_scaleKey(ScaleChangedCaller(*this)),
  106. m_scale(SCALEKEY_IDENTITY),
  107. m_filter(m_entity, node),
  108. m_named(m_entity),
  109. m_nameKeys(m_entity),
  110. m_renderName(m_named, g_vector3_identity),
  111. m_transformChanged(transformChanged),
  112. m_evaluateTransform(evaluateTransform)
  113. {
  114. construct();
  115. }
  116. MiscModel(const MiscModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
  117. m_entity(other.m_entity),
  118. m_originKey(OriginChangedCaller(*this)),
  119. m_origin(ORIGINKEY_IDENTITY),
  120. m_anglesKey(AnglesChangedCaller(*this)),
  121. m_angles(ANGLESKEY_IDENTITY),
  122. m_scaleKey(ScaleChangedCaller(*this)),
  123. m_scale(SCALEKEY_IDENTITY),
  124. m_filter(m_entity, node),
  125. m_named(m_entity),
  126. m_nameKeys(m_entity),
  127. m_renderName(m_named, g_vector3_identity),
  128. m_transformChanged(transformChanged),
  129. m_evaluateTransform(evaluateTransform)
  130. {
  131. construct();
  132. }
  133. InstanceCounter m_instanceCounter;
  134. void instanceAttach(const scene::Path& path)
  135. {
  136. if(++m_instanceCounter.m_count == 1)
  137. {
  138. m_filter.instanceAttach();
  139. m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
  140. m_entity.attach(m_keyObservers);
  141. }
  142. }
  143. void instanceDetach(const scene::Path& path)
  144. {
  145. if(--m_instanceCounter.m_count == 0)
  146. {
  147. m_entity.detach(m_keyObservers);
  148. m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
  149. m_filter.instanceDetach();
  150. }
  151. }
  152. EntityKeyValues& getEntity()
  153. {
  154. return m_entity;
  155. }
  156. const EntityKeyValues& getEntity() const
  157. {
  158. return m_entity;
  159. }
  160. scene::Traversable& getTraversable()
  161. {
  162. return m_model.getTraversable();
  163. }
  164. Namespaced& getNamespaced()
  165. {
  166. return m_nameKeys;
  167. }
  168. Nameable& getNameable()
  169. {
  170. return m_named;
  171. }
  172. TransformNode& getTransformNode()
  173. {
  174. return m_transform;
  175. }
  176. void attach(scene::Traversable::Observer* observer)
  177. {
  178. m_model.attach(observer);
  179. }
  180. void detach(scene::Traversable::Observer* observer)
  181. {
  182. m_model.detach(observer);
  183. }
  184. void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
  185. {
  186. if(selected)
  187. {
  188. m_renderOrigin.render(renderer, volume, localToWorld);
  189. }
  190. renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
  191. }
  192. void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
  193. {
  194. renderSolid(renderer, volume, localToWorld, selected);
  195. if(g_showNames)
  196. {
  197. renderer.addRenderable(m_renderName, localToWorld);
  198. }
  199. }
  200. void translate(const Vector3& translation)
  201. {
  202. m_origin = origin_translated(m_origin, translation);
  203. }
  204. void rotate(const Quaternion& rotation)
  205. {
  206. m_angles = angles_rotated(m_angles, rotation);
  207. }
  208. void scale(const Vector3& scaling)
  209. {
  210. m_scale = scale_scaled(m_scale, scaling);
  211. }
  212. void snapto(float snap)
  213. {
  214. m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
  215. m_originKey.write(&m_entity);
  216. }
  217. void revertTransform()
  218. {
  219. m_origin = m_originKey.m_origin;
  220. m_angles = m_anglesKey.m_angles;
  221. m_scale = m_scaleKey.m_scale;
  222. }
  223. void freezeTransform()
  224. {
  225. m_originKey.m_origin = m_origin;
  226. m_originKey.write(&m_entity);
  227. m_anglesKey.m_angles = m_angles;
  228. m_anglesKey.write(&m_entity);
  229. m_scaleKey.m_scale = m_scale;
  230. m_scaleKey.write(&m_entity);
  231. }
  232. void transformChanged()
  233. {
  234. revertTransform();
  235. m_evaluateTransform();
  236. updateTransform();
  237. }
  238. typedef MemberCaller<MiscModel, &MiscModel::transformChanged> TransformChangedCaller;
  239. };
  240. class MiscModelInstance : public TargetableInstance, public TransformModifier, public Renderable
  241. {
  242. class TypeCasts
  243. {
  244. InstanceTypeCastTable m_casts;
  245. public:
  246. TypeCasts()
  247. {
  248. m_casts = TargetableInstance::StaticTypeCasts::instance().get();
  249. InstanceStaticCast<MiscModelInstance, Renderable>::install(m_casts);
  250. InstanceStaticCast<MiscModelInstance, Transformable>::install(m_casts);
  251. InstanceIdentityCast<MiscModelInstance>::install(m_casts);
  252. }
  253. InstanceTypeCastTable& get()
  254. {
  255. return m_casts;
  256. }
  257. };
  258. MiscModel& m_contained;
  259. public:
  260. typedef LazyStatic<TypeCasts> StaticTypeCasts;
  261. STRING_CONSTANT(Name, "MiscModelInstance");
  262. MiscModelInstance(const scene::Path& path, scene::Instance* parent, MiscModel& miscmodel) :
  263. TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), miscmodel.getEntity(), *this),
  264. TransformModifier(MiscModel::TransformChangedCaller(miscmodel), ApplyTransformCaller(*this)),
  265. m_contained(miscmodel)
  266. {
  267. m_contained.instanceAttach(Instance::path());
  268. StaticRenderableConnectionLines::instance().attach(*this);
  269. }
  270. ~MiscModelInstance()
  271. {
  272. StaticRenderableConnectionLines::instance().detach(*this);
  273. m_contained.instanceDetach(Instance::path());
  274. }
  275. void renderSolid(Renderer& renderer, const VolumeTest& volume) const
  276. {
  277. m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
  278. }
  279. void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
  280. {
  281. m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
  282. }
  283. void evaluateTransform()
  284. {
  285. if(getType() == TRANSFORM_PRIMITIVE)
  286. {
  287. m_contained.translate(getTranslation());
  288. m_contained.rotate(getRotation());
  289. m_contained.scale(getScale());
  290. }
  291. }
  292. void applyTransform()
  293. {
  294. m_contained.revertTransform();
  295. evaluateTransform();
  296. m_contained.freezeTransform();
  297. }
  298. typedef MemberCaller<MiscModelInstance, &MiscModelInstance::applyTransform> ApplyTransformCaller;
  299. };
  300. class MiscModelNode :
  301. public scene::Node::Symbiot,
  302. public scene::Instantiable,
  303. public scene::Cloneable,
  304. public scene::Traversable::Observer
  305. {
  306. class TypeCasts
  307. {
  308. NodeTypeCastTable m_casts;
  309. public:
  310. TypeCasts()
  311. {
  312. NodeStaticCast<MiscModelNode, scene::Instantiable>::install(m_casts);
  313. NodeStaticCast<MiscModelNode, scene::Cloneable>::install(m_casts);
  314. NodeContainedCast<MiscModelNode, scene::Traversable>::install(m_casts);
  315. NodeContainedCast<MiscModelNode, Snappable>::install(m_casts);
  316. NodeContainedCast<MiscModelNode, TransformNode>::install(m_casts);
  317. NodeContainedCast<MiscModelNode, Entity>::install(m_casts);
  318. NodeContainedCast<MiscModelNode, Nameable>::install(m_casts);
  319. NodeContainedCast<MiscModelNode, Namespaced>::install(m_casts);
  320. }
  321. NodeTypeCastTable& get()
  322. {
  323. return m_casts;
  324. }
  325. };
  326. scene::Node m_node;
  327. InstanceSet m_instances;
  328. MiscModel m_contained;
  329. void construct()
  330. {
  331. m_contained.attach(this);
  332. }
  333. void destroy()
  334. {
  335. m_contained.detach(this);
  336. }
  337. public:
  338. typedef LazyStatic<TypeCasts> StaticTypeCasts;
  339. scene::Traversable& get(NullType<scene::Traversable>)
  340. {
  341. return m_contained.getTraversable();
  342. }
  343. Snappable& get(NullType<Snappable>)
  344. {
  345. return m_contained;
  346. }
  347. TransformNode& get(NullType<TransformNode>)
  348. {
  349. return m_contained.getTransformNode();
  350. }
  351. Entity& get(NullType<Entity>)
  352. {
  353. return m_contained.getEntity();
  354. }
  355. Nameable& get(NullType<Nameable>)
  356. {
  357. return m_contained.getNameable();
  358. }
  359. Namespaced& get(NullType<Namespaced>)
  360. {
  361. return m_contained.getNamespaced();
  362. }
  363. MiscModelNode(EntityClass* eclass) :
  364. m_node(this, this, StaticTypeCasts::instance().get()),
  365. m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<MiscModelInstance>::Caller(m_instances))
  366. {
  367. construct();
  368. }
  369. MiscModelNode(const MiscModelNode& other) :
  370. scene::Node::Symbiot(other),
  371. scene::Instantiable(other),
  372. scene::Cloneable(other),
  373. scene::Traversable::Observer(other),
  374. m_node(this, this, StaticTypeCasts::instance().get()),
  375. m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<MiscModelInstance>::Caller(m_instances))
  376. {
  377. construct();
  378. }
  379. ~MiscModelNode()
  380. {
  381. destroy();
  382. }
  383. void release()
  384. {
  385. delete this;
  386. }
  387. scene::Node& node()
  388. {
  389. return m_node;
  390. }
  391. scene::Node& clone() const
  392. {
  393. return (new MiscModelNode(*this))->node();
  394. }
  395. void insert(scene::Node& child)
  396. {
  397. m_instances.insert(child);
  398. }
  399. void erase(scene::Node& child)
  400. {
  401. m_instances.erase(child);
  402. }
  403. scene::Instance* create(const scene::Path& path, scene::Instance* parent)
  404. {
  405. return new MiscModelInstance(path, parent, m_contained);
  406. }
  407. void forEachInstance(const scene::Instantiable::Visitor& visitor)
  408. {
  409. m_instances.forEachInstance(visitor);
  410. }
  411. void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
  412. {
  413. m_instances.insert(observer, path, instance);
  414. }
  415. scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
  416. {
  417. return m_instances.erase(observer, path);
  418. }
  419. };
  420. scene::Node& New_MiscModel(EntityClass* eclass)
  421. {
  422. return (new MiscModelNode(eclass))->node();
  423. }
  424. void MiscModel_construct()
  425. {
  426. }
  427. void MiscModel_destroy()
  428. {
  429. }