]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/entity/group.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / plugins / entity / group.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 does not have a fixed size specified in its entity-definition (except misc_model).
24 ///
25 /// This entity behaves as a group, i.e. it contains brushes.
26
27 #include "cullable.h"
28 #include "renderable.h"
29 #include "editable.h"
30
31 #include "selectionlib.h"
32 #include "instancelib.h"
33 #include "transformlib.h"
34 #include "traverselib.h"
35 #include "entitylib.h"
36 #include "render.h"
37 #include "eclasslib.h"
38
39 #include "targetable.h"
40 #include "origin.h"
41 #include "angles.h"
42 #include "scale.h"
43 #include "filters.h"
44 #include "namedentity.h"
45 #include "keyobservers.h"
46 #include "namekeys.h"
47
48 #include "entity.h"
49
50 /// The "origin" key directly controls the entity's local-to-parent transform.
51
52 class Group {
53     EntityKeyValues m_entity;
54     KeyObserverMap m_keyObservers;
55     MatrixTransform m_transform;
56     TraversableNodeSet m_traverse;
57
58     ClassnameFilter m_filter;
59     NamedEntity m_named;
60     NameKeys m_nameKeys;
61
62     OriginKey m_originKey;
63     Vector3 m_origin;
64
65     RenderableNamedEntity m_renderName;
66     mutable Vector3 m_name_origin;
67
68     Callback<void()> m_transformChanged;
69     Callback<void()> m_evaluateTransform;
70
71     void construct()
72     {
73         m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
74         m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
75         m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
76     }
77
78 public:
79     Group(EntityClass *eclass, scene::Node &node, const Callback<void()> &transformChanged,
80           const Callback<void()> &evaluateTransform) :
81             m_entity(eclass),
82             m_filter(m_entity, node),
83             m_named(m_entity),
84             m_nameKeys(m_entity),
85             m_originKey(OriginChangedCaller(*this)),
86             m_origin(ORIGINKEY_IDENTITY),
87             m_renderName(m_named, m_name_origin),
88             m_name_origin(g_vector3_identity),
89             m_transformChanged(transformChanged),
90             m_evaluateTransform(evaluateTransform)
91     {
92         construct();
93     }
94
95     Group(const Group &other, scene::Node &node, const Callback<void()> &transformChanged,
96           const Callback<void()> &evaluateTransform) :
97             m_entity(other.m_entity),
98             m_filter(m_entity, node),
99             m_named(m_entity),
100             m_nameKeys(m_entity),
101             m_originKey(OriginChangedCaller(*this)),
102             m_origin(ORIGINKEY_IDENTITY),
103             m_renderName(m_named, g_vector3_identity),
104             m_transformChanged(transformChanged),
105             m_evaluateTransform(evaluateTransform)
106     {
107         construct();
108     }
109
110     InstanceCounter m_instanceCounter;
111
112     void instanceAttach(const scene::Path &path)
113     {
114         if (++m_instanceCounter.m_count == 1) {
115             m_filter.instanceAttach();
116             m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
117             m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end()));
118             m_entity.attach(m_keyObservers);
119         }
120     }
121
122     void instanceDetach(const scene::Path &path)
123     {
124         if (--m_instanceCounter.m_count == 0) {
125             m_entity.detach(m_keyObservers);
126             m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end()));
127             m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
128             m_filter.instanceDetach();
129         }
130     }
131
132     EntityKeyValues &getEntity()
133     {
134         return m_entity;
135     }
136
137     const EntityKeyValues &getEntity() const
138     {
139         return m_entity;
140     }
141
142     scene::Traversable &getTraversable()
143     {
144         return m_traverse;
145     }
146
147     Namespaced &getNamespaced()
148     {
149         return m_nameKeys;
150     }
151
152     Nameable &getNameable()
153     {
154         return m_named;
155     }
156
157     TransformNode &getTransformNode()
158     {
159         return m_transform;
160     }
161
162     void attach(scene::Traversable::Observer *observer)
163     {
164         m_traverse.attach(observer);
165     }
166
167     void detach(scene::Traversable::Observer *observer)
168     {
169         m_traverse.detach(observer);
170     }
171
172     void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const
173     {
174         renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
175     }
176
177     void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld,
178                          const AABB &childBounds) const
179     {
180         renderSolid(renderer, volume, localToWorld);
181
182         if (g_showNames) {
183             // don't draw the name for worldspawn
184             if (!strcmp(m_entity.getEntityClass().name(), "worldspawn")) {
185                 return;
186             }
187
188             // place name in the middle of the "children cloud"
189             m_name_origin = childBounds.origin;
190
191             renderer.addRenderable(m_renderName, localToWorld);
192         }
193     }
194
195     void updateTransform()
196     {
197         m_transform.localToParent() = g_matrix4_identity;
198         matrix4_translate_by_vec3(m_transform.localToParent(), m_origin);
199         m_transformChanged();
200     }
201
202     typedef MemberCaller<Group, void(), &Group::updateTransform> UpdateTransformCaller;
203
204     void originChanged()
205     {
206         m_origin = m_originKey.m_origin;
207         updateTransform();
208     }
209
210     typedef MemberCaller<Group, void(), &Group::originChanged> OriginChangedCaller;
211
212     void translate(const Vector3 &translation)
213     {
214         m_origin = origin_translated(m_origin, translation);
215     }
216
217     void revertTransform()
218     {
219         m_origin = m_originKey.m_origin;
220     }
221
222     void freezeTransform()
223     {
224         m_originKey.m_origin = m_origin;
225         m_originKey.write(&m_entity);
226     }
227
228     void transformChanged()
229     {
230         revertTransform();
231         m_evaluateTransform();
232         updateTransform();
233     }
234
235     typedef MemberCaller<Group, void(), &Group::transformChanged> TransformChangedCaller;
236 };
237
238 #if 0
239 class TransformableSetTranslation
240 {
241 Translation m_value;
242 public:
243 TransformableSetTranslation( const Translation& value ) : m_value( value ){
244 }
245 void operator()( Transformable& transformable ) const {
246     transformable.setTranslation( m_value );
247 }
248 };
249
250 class TransformableSetRotation
251 {
252 Rotation m_value;
253 public:
254 TransformableSetRotation( const Rotation& value ) : m_value( value ){
255 }
256 void operator()( Transformable& transformable ) const {
257     transformable.setRotation( m_value );
258 }
259 };
260
261 class TransformableSetScale
262 {
263 Scale m_value;
264 public:
265 TransformableSetScale( const Scale& value ) : m_value( value ){
266 }
267 void operator()( Transformable& transformable ) const {
268     transformable.setScale( m_value );
269 }
270 };
271
272 class TransformableSetType
273 {
274 TransformModifierType m_value;
275 public:
276 TransformableSetType( const TransformModifierType& value ) : m_value( value ){
277 }
278 void operator()( Transformable& transformable ) const {
279     transformable.setType( m_value );
280 }
281 };
282
283 class TransformableFreezeTransform
284 {
285 TransformModifierType m_value;
286 public:
287 void operator()( Transformable& transformable ) const {
288     transformable.freezeTransform();
289 }
290 };
291
292 template<typename Functor>
293 inline void Scene_forEachChildTransformable( const Functor& functor, const scene::Path& path ){
294     GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply<Transformable, Functor> >( functor ), path );
295 }
296 #endif
297
298 class GroupInstance :
299         public TargetableInstance,
300         public TransformModifier,
301 #if 0
302         public Transformable,
303 #endif
304         public Renderable {
305     class TypeCasts {
306         InstanceTypeCastTable m_casts;
307     public:
308         TypeCasts()
309         {
310             m_casts = TargetableInstance::StaticTypeCasts::instance().get();
311             InstanceStaticCast<GroupInstance, Renderable>::install(m_casts);
312 #if 0
313             InstanceStaticCast<GroupInstance, Transformable>::install( m_casts );
314 #endif
315         }
316
317         InstanceTypeCastTable &get()
318         {
319             return m_casts;
320         }
321     };
322
323     Group &m_contained;
324 public:
325     typedef LazyStatic<TypeCasts> StaticTypeCasts;
326
327     GroupInstance(const scene::Path &path, scene::Instance *parent, Group &group) :
328             TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), group.getEntity(), *this),
329             TransformModifier(Group::TransformChangedCaller(group), ApplyTransformCaller(*this)),
330             m_contained(group)
331     {
332         m_contained.instanceAttach(Instance::path());
333         StaticRenderableConnectionLines::instance().attach(*this);
334     }
335
336     ~GroupInstance()
337     {
338         StaticRenderableConnectionLines::instance().detach(*this);
339         m_contained.instanceDetach(Instance::path());
340     }
341
342     void renderSolid(Renderer &renderer, const VolumeTest &volume) const
343     {
344         m_contained.renderSolid(renderer, volume, Instance::localToWorld());
345     }
346
347     void renderWireframe(Renderer &renderer, const VolumeTest &volume) const
348     {
349         m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), Instance::childBounds());
350     }
351
352     STRING_CONSTANT(Name, "GroupInstance");
353
354 #if 0
355     void setType( TransformModifierType type ){
356         Scene_forEachChildTransformable( TransformableSetType( type ), Instance::path() );
357     }
358     void setTranslation( const Translation& value ){
359         Scene_forEachChildTransformable( TransformableSetTranslation( value ), Instance::path() );
360     }
361     void setRotation( const Rotation& value ){
362         Scene_forEachChildTransformable( TransformableSetRotation( value ), Instance::path() );
363     }
364     void setScale( const Scale& value ){
365         Scene_forEachChildTransformable( TransformableSetScale( value ), Instance::path() );
366     }
367     void freezeTransform(){
368         Scene_forEachChildTransformable( TransformableFreezeTransform(), Instance::path() );
369     }
370
371     void evaluateTransform(){
372     }
373 #endif
374
375     void evaluateTransform()
376     {
377         if (getType() == TRANSFORM_PRIMITIVE) {
378             m_contained.translate(getTranslation());
379         }
380     }
381
382     void applyTransform()
383     {
384         m_contained.revertTransform();
385         evaluateTransform();
386         m_contained.freezeTransform();
387     }
388
389     typedef MemberCaller<GroupInstance, void(), &GroupInstance::applyTransform> ApplyTransformCaller;
390 };
391
392 class GroupNode :
393         public scene::Node::Symbiot,
394         public scene::Instantiable,
395         public scene::Cloneable,
396         public scene::Traversable::Observer {
397     class TypeCasts {
398         NodeTypeCastTable m_casts;
399     public:
400         TypeCasts()
401         {
402             NodeStaticCast<GroupNode, scene::Instantiable>::install(m_casts);
403             NodeStaticCast<GroupNode, scene::Cloneable>::install(m_casts);
404             NodeContainedCast<GroupNode, scene::Traversable>::install(m_casts);
405             NodeContainedCast<GroupNode, TransformNode>::install(m_casts);
406             NodeContainedCast<GroupNode, Entity>::install(m_casts);
407             NodeContainedCast<GroupNode, Nameable>::install(m_casts);
408             NodeContainedCast<GroupNode, Namespaced>::install(m_casts);
409         }
410
411         NodeTypeCastTable &get()
412         {
413             return m_casts;
414         }
415     };
416
417
418     scene::Node m_node;
419     InstanceSet m_instances;
420     Group m_contained;
421
422     void construct()
423     {
424         m_contained.attach(this);
425     }
426
427     void destroy()
428     {
429         m_contained.detach(this);
430     }
431
432 public:
433
434     typedef LazyStatic<TypeCasts> StaticTypeCasts;
435
436     scene::Traversable &get(NullType<scene::Traversable>)
437     {
438         return m_contained.getTraversable();
439     }
440
441     TransformNode &get(NullType<TransformNode>)
442     {
443         return m_contained.getTransformNode();
444     }
445
446     Entity &get(NullType<Entity>)
447     {
448         return m_contained.getEntity();
449     }
450
451     Nameable &get(NullType<Nameable>)
452     {
453         return m_contained.getNameable();
454     }
455
456     Namespaced &get(NullType<Namespaced>)
457     {
458         return m_contained.getNamespaced();
459     }
460
461     GroupNode(EntityClass *eclass) :
462             m_node(this, this, StaticTypeCasts::instance().get()),
463             m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances),
464                         InstanceSetEvaluateTransform<GroupInstance>::Caller(m_instances))
465     {
466         construct();
467     }
468
469     GroupNode(const GroupNode &other) :
470             scene::Node::Symbiot(other),
471             scene::Instantiable(other),
472             scene::Cloneable(other),
473             scene::Traversable::Observer(other),
474             m_node(this, this, StaticTypeCasts::instance().get()),
475             m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances),
476                         InstanceSetEvaluateTransform<GroupInstance>::Caller(m_instances))
477     {
478         construct();
479     }
480
481     ~GroupNode()
482     {
483         destroy();
484     }
485
486     void release()
487     {
488         delete this;
489     }
490
491     scene::Node &node()
492     {
493         return m_node;
494     }
495
496     scene::Node &clone() const
497     {
498         return (new GroupNode(*this))->node();
499     }
500
501     void insert(scene::Node &child)
502     {
503         m_instances.insert(child);
504     }
505
506     void erase(scene::Node &child)
507     {
508         m_instances.erase(child);
509     }
510
511     scene::Instance *create(const scene::Path &path, scene::Instance *parent)
512     {
513         return new GroupInstance(path, parent, m_contained);
514     }
515
516     void forEachInstance(const scene::Instantiable::Visitor &visitor)
517     {
518         m_instances.forEachInstance(visitor);
519     }
520
521     void insert(scene::Instantiable::Observer *observer, const scene::Path &path, scene::Instance *instance)
522     {
523         m_instances.insert(observer, path, instance);
524     }
525
526     scene::Instance *erase(scene::Instantiable::Observer *observer, const scene::Path &path)
527     {
528         return m_instances.erase(observer, path);
529     }
530 };
531
532 scene::Node &New_Group(EntityClass *eclass)
533 {
534     return (new GroupNode(eclass))->node();
535 }