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