]> git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/entity/generic.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / plugins / entity / generic.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 ///\file
23 ///\brief Represents any entity which has a fixed size specified in its entity-definition and does not display a model (e.g. info_player_start).
24 ///
25 /// This entity displays an axis-aligned bounding box of the size and colour specified in its entity-definition.
26 /// The "origin" key directly controls the entity's local-to-parent transform.
27 /// An arrow is drawn to visualise the "angle" key.
28
29 #include "cullable.h"
30 #include "renderable.h"
31 #include "editable.h"
32
33 #include "math/frustum.h"
34 #include "selectionlib.h"
35 #include "instancelib.h"
36 #include "transformlib.h"
37 #include "entitylib.h"
38 #include "render.h"
39 #include "eclasslib.h"
40 #include "math/line.h"
41
42 #include "targetable.h"
43 #include "origin.h"
44 #include "angles.h"
45 #include "filters.h"
46 #include "namedentity.h"
47 #include "keyobservers.h"
48 #include "namekeys.h"
49 #include "rotation.h"
50
51 #include "entity.h"
52
53
54 class RenderableArrow : public OpenGLRenderable {
55     const Vector3 &m_origin;
56     const Vector3 &m_angles;
57
58 public:
59     RenderableArrow(const Vector3 &origin, const Vector3 &angles)
60             : m_origin(origin), m_angles(angles)
61     {
62     }
63
64     void render(RenderStateFlags state) const
65     {
66         Matrix4 mat = matrix4_rotation_for_euler_xyz_degrees(m_angles);
67         arrow_draw(m_origin, matrix4_transformed_direction(mat, Vector3(1, 0, 0)),
68                    matrix4_transformed_direction(mat, Vector3(0, 1, 0)),
69                    matrix4_transformed_direction(mat, Vector3(0, 0, 1)));
70     }
71 };
72
73 inline void read_aabb(AABB &aabb, const EntityClass &eclass)
74 {
75     aabb = aabb_for_minmax(eclass.mins, eclass.maxs);
76 }
77
78
79 class GenericEntity :
80         public Cullable,
81         public Bounded,
82         public Snappable {
83     EntityKeyValues m_entity;
84     KeyObserverMap m_keyObservers;
85     MatrixTransform m_transform;
86
87     OriginKey m_originKey;
88     Vector3 m_origin;
89     AnglesKey m_anglesKey;
90     Vector3 m_angles;
91
92     ClassnameFilter m_filter;
93     NamedEntity m_named;
94     NameKeys m_nameKeys;
95
96     AABB m_aabb_local;
97
98     RenderableArrow m_arrow;
99     RenderableSolidAABB m_aabb_solid;
100     RenderableWireframeAABB m_aabb_wire;
101     RenderableNamedEntity m_renderName;
102
103     Callback<void()> m_transformChanged;
104     Callback<void()> m_evaluateTransform;
105
106     void construct()
107     {
108         read_aabb(m_aabb_local, m_entity.getEntityClass());
109
110         m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
111         m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
112         m_keyObservers.insert("angle", AnglesKey::AngleChangedCaller(m_anglesKey));
113         m_keyObservers.insert("angles", AnglesKey::AnglesChangedCaller(m_anglesKey));
114         m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
115     }
116
117 // vc 2k5 compiler fix
118 #if _MSC_VER >= 1400
119     public:
120 #endif
121
122     void updateTransform()
123     {
124         m_transform.localToParent() = g_matrix4_identity;
125         matrix4_translate_by_vec3(m_transform.localToParent(), m_origin);
126         m_transformChanged();
127     }
128
129     typedef MemberCaller<GenericEntity, void(), &GenericEntity::updateTransform> UpdateTransformCaller;
130
131     void originChanged()
132     {
133         m_origin = m_originKey.m_origin;
134         updateTransform();
135     }
136
137     typedef MemberCaller<GenericEntity, void(), &GenericEntity::originChanged> OriginChangedCaller;
138
139     void anglesChanged()
140     {
141         m_angles = m_anglesKey.m_angles;
142         updateTransform();
143     }
144
145     typedef MemberCaller<GenericEntity, void(), &GenericEntity::anglesChanged> AnglesChangedCaller;
146 public:
147
148     GenericEntity(EntityClass *eclass, scene::Node &node, const Callback<void()> &transformChanged,
149                   const Callback<void()> &evaluateTransform) :
150             m_entity(eclass),
151             m_originKey(OriginChangedCaller(*this)),
152             m_origin(ORIGINKEY_IDENTITY),
153             m_anglesKey(AnglesChangedCaller(*this)),
154             m_angles(ANGLESKEY_IDENTITY),
155             m_filter(m_entity, node),
156             m_named(m_entity),
157             m_nameKeys(m_entity),
158             m_arrow(m_aabb_local.origin, m_angles),
159             m_aabb_solid(m_aabb_local),
160             m_aabb_wire(m_aabb_local),
161             m_renderName(m_named, g_vector3_identity),
162             m_transformChanged(transformChanged),
163             m_evaluateTransform(evaluateTransform)
164     {
165         construct();
166     }
167
168     GenericEntity(const GenericEntity &other, scene::Node &node, const Callback<void()> &transformChanged,
169                   const Callback<void()> &evaluateTransform) :
170             m_entity(other.m_entity),
171             m_originKey(OriginChangedCaller(*this)),
172             m_origin(ORIGINKEY_IDENTITY),
173             m_anglesKey(AnglesChangedCaller(*this)),
174             m_angles(ANGLESKEY_IDENTITY),
175             m_filter(m_entity, node),
176             m_named(m_entity),
177             m_nameKeys(m_entity),
178             m_arrow(m_aabb_local.origin, m_angles),
179             m_aabb_solid(m_aabb_local),
180             m_aabb_wire(m_aabb_local),
181             m_renderName(m_named, g_vector3_identity),
182             m_transformChanged(transformChanged),
183             m_evaluateTransform(evaluateTransform)
184     {
185         construct();
186     }
187
188     InstanceCounter m_instanceCounter;
189
190     void instanceAttach(const scene::Path &path)
191     {
192         if (++m_instanceCounter.m_count == 1) {
193             m_filter.instanceAttach();
194             m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
195             m_entity.attach(m_keyObservers);
196         }
197     }
198
199     void instanceDetach(const scene::Path &path)
200     {
201         if (--m_instanceCounter.m_count == 0) {
202             m_entity.detach(m_keyObservers);
203             m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
204             m_filter.instanceDetach();
205         }
206     }
207
208     EntityKeyValues &getEntity()
209     {
210         return m_entity;
211     }
212
213     const EntityKeyValues &getEntity() const
214     {
215         return m_entity;
216     }
217
218     Namespaced &getNamespaced()
219     {
220         return m_nameKeys;
221     }
222
223     Nameable &getNameable()
224     {
225         return m_named;
226     }
227
228     TransformNode &getTransformNode()
229     {
230         return m_transform;
231     }
232
233     const AABB &localAABB() const
234     {
235         return m_aabb_local;
236     }
237
238     VolumeIntersectionValue intersectVolume(const VolumeTest &volume, const Matrix4 &localToWorld) const
239     {
240         return volume.TestAABB(localAABB(), localToWorld);
241     }
242
243     void renderArrow(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const
244     {
245         if (g_showAngles) {
246             renderer.addRenderable(m_arrow, localToWorld);
247         }
248     }
249
250     void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const
251     {
252         renderer.SetState(m_entity.getEntityClass().m_state_fill, Renderer::eFullMaterials);
253         renderer.addRenderable(m_aabb_solid, localToWorld);
254         renderArrow(renderer, volume, localToWorld);
255     }
256
257     void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const
258     {
259         renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
260         renderer.addRenderable(m_aabb_wire, localToWorld);
261         renderArrow(renderer, volume, localToWorld);
262         if (g_showNames) {
263             renderer.addRenderable(m_renderName, localToWorld);
264         }
265     }
266
267
268     void testSelect(Selector &selector, SelectionTest &test, const Matrix4 &localToWorld)
269     {
270         test.BeginMesh(localToWorld);
271
272         SelectionIntersection best;
273         aabb_testselect(m_aabb_local, test, best);
274         if (best.valid()) {
275             selector.addIntersection(best);
276         }
277     }
278
279     void translate(const Vector3 &translation)
280     {
281         m_origin = origin_translated(m_origin, translation);
282     }
283
284     void rotate(const Quaternion &rotation)
285     {
286         m_angles = angles_rotated(m_angles, rotation);
287     }
288
289     void snapto(float snap)
290     {
291         m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
292         m_originKey.write(&m_entity);
293     }
294
295     void revertTransform()
296     {
297         m_origin = m_originKey.m_origin;
298         m_angles = m_anglesKey.m_angles;
299     }
300
301     void freezeTransform()
302     {
303         m_originKey.m_origin = m_origin;
304         m_originKey.write(&m_entity);
305         m_anglesKey.m_angles = m_angles;
306         m_anglesKey.write(&m_entity);
307     }
308
309     void transformChanged()
310     {
311         revertTransform();
312         m_evaluateTransform();
313         updateTransform();
314     }
315
316     typedef MemberCaller<GenericEntity, void(), &GenericEntity::transformChanged> TransformChangedCaller;
317 };
318
319 class GenericEntityInstance :
320         public TargetableInstance,
321         public TransformModifier,
322         public Renderable,
323         public SelectionTestable {
324     class TypeCasts {
325         InstanceTypeCastTable m_casts;
326     public:
327         TypeCasts()
328         {
329             m_casts = TargetableInstance::StaticTypeCasts::instance().get();
330             InstanceContainedCast<GenericEntityInstance, Bounded>::install(m_casts);
331             InstanceContainedCast<GenericEntityInstance, Cullable>::install(m_casts);
332             InstanceStaticCast<GenericEntityInstance, Renderable>::install(m_casts);
333             InstanceStaticCast<GenericEntityInstance, SelectionTestable>::install(m_casts);
334             InstanceStaticCast<GenericEntityInstance, Transformable>::install(m_casts);
335             InstanceIdentityCast<GenericEntityInstance>::install(m_casts);
336         }
337
338         InstanceTypeCastTable &get()
339         {
340             return m_casts;
341         }
342     };
343
344     GenericEntity &m_contained;
345     mutable AABB m_bounds;
346 public:
347
348     typedef LazyStatic<TypeCasts> StaticTypeCasts;
349
350     Bounded &get(NullType<Bounded>)
351     {
352         return m_contained;
353     }
354
355     Cullable &get(NullType<Cullable>)
356     {
357         return m_contained;
358     }
359
360     STRING_CONSTANT(Name, "GenericEntityInstance");
361
362     GenericEntityInstance(const scene::Path &path, scene::Instance *parent, GenericEntity &contained) :
363             TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this),
364             TransformModifier(GenericEntity::TransformChangedCaller(contained), ApplyTransformCaller(*this)),
365             m_contained(contained)
366     {
367         m_contained.instanceAttach(Instance::path());
368
369         StaticRenderableConnectionLines::instance().attach(*this);
370     }
371
372     ~GenericEntityInstance()
373     {
374         StaticRenderableConnectionLines::instance().detach(*this);
375
376         m_contained.instanceDetach(Instance::path());
377     }
378
379     void renderSolid(Renderer &renderer, const VolumeTest &volume) const
380     {
381         m_contained.renderSolid(renderer, volume, Instance::localToWorld());
382     }
383
384     void renderWireframe(Renderer &renderer, const VolumeTest &volume) const
385     {
386         m_contained.renderWireframe(renderer, volume, Instance::localToWorld());
387     }
388
389     void testSelect(Selector &selector, SelectionTest &test)
390     {
391         m_contained.testSelect(selector, test, Instance::localToWorld());
392     }
393
394     void evaluateTransform()
395     {
396         if (getType() == TRANSFORM_PRIMITIVE) {
397             m_contained.translate(getTranslation());
398             m_contained.rotate(getRotation());
399         }
400     }
401
402     void applyTransform()
403     {
404         m_contained.revertTransform();
405         evaluateTransform();
406         m_contained.freezeTransform();
407     }
408
409     typedef MemberCaller<GenericEntityInstance, void(), &GenericEntityInstance::applyTransform> ApplyTransformCaller;
410 };
411
412 class GenericEntityNode :
413         public scene::Node::Symbiot,
414         public scene::Instantiable,
415         public scene::Cloneable {
416     class TypeCasts {
417         NodeTypeCastTable m_casts;
418     public:
419         TypeCasts()
420         {
421             NodeStaticCast<GenericEntityNode, scene::Instantiable>::install(m_casts);
422             NodeStaticCast<GenericEntityNode, scene::Cloneable>::install(m_casts);
423             NodeContainedCast<GenericEntityNode, Snappable>::install(m_casts);
424             NodeContainedCast<GenericEntityNode, TransformNode>::install(m_casts);
425             NodeContainedCast<GenericEntityNode, Entity>::install(m_casts);
426             NodeContainedCast<GenericEntityNode, Nameable>::install(m_casts);
427             NodeContainedCast<GenericEntityNode, Namespaced>::install(m_casts);
428         }
429
430         NodeTypeCastTable &get()
431         {
432             return m_casts;
433         }
434     };
435
436
437     InstanceSet m_instances;
438
439     scene::Node m_node;
440     GenericEntity m_contained;
441
442 public:
443     typedef LazyStatic<TypeCasts> StaticTypeCasts;
444
445     Snappable &get(NullType<Snappable>)
446     {
447         return m_contained;
448     }
449
450     TransformNode &get(NullType<TransformNode>)
451     {
452         return m_contained.getTransformNode();
453     }
454
455     Entity &get(NullType<Entity>)
456     {
457         return m_contained.getEntity();
458     }
459
460     Nameable &get(NullType<Nameable>)
461     {
462         return m_contained.getNameable();
463     }
464
465     Namespaced &get(NullType<Namespaced>)
466     {
467         return m_contained.getNamespaced();
468     }
469
470     GenericEntityNode(EntityClass *eclass) :
471             m_node(this, this, StaticTypeCasts::instance().get()),
472             m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances),
473                         InstanceSetEvaluateTransform<GenericEntityInstance>::Caller(m_instances))
474     {
475     }
476
477     GenericEntityNode(const GenericEntityNode &other) :
478             scene::Node::Symbiot(other),
479             scene::Instantiable(other),
480             scene::Cloneable(other),
481             m_node(this, this, StaticTypeCasts::instance().get()),
482             m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances),
483                         InstanceSetEvaluateTransform<GenericEntityInstance>::Caller(m_instances))
484     {
485     }
486
487     void release()
488     {
489         delete this;
490     }
491
492     scene::Node &node()
493     {
494         return m_node;
495     }
496
497     scene::Node &clone() const
498     {
499         return (new GenericEntityNode(*this))->node();
500     }
501
502     scene::Instance *create(const scene::Path &path, scene::Instance *parent)
503     {
504         return new GenericEntityInstance(path, parent, m_contained);
505     }
506
507     void forEachInstance(const scene::Instantiable::Visitor &visitor)
508     {
509         m_instances.forEachInstance(visitor);
510     }
511
512     void insert(scene::Instantiable::Observer *observer, const scene::Path &path, scene::Instance *instance)
513     {
514         m_instances.insert(observer, path, instance);
515     }
516
517     scene::Instance *erase(scene::Instantiable::Observer *observer, const scene::Path &path)
518     {
519         return m_instances.erase(observer, path);
520     }
521 };
522
523 scene::Node &New_GenericEntity(EntityClass *eclass)
524 {
525     return (new GenericEntityNode(eclass))->node();
526 }