2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
23 ///\brief Represents any entity which does not have a fixed size specified in its entity-definition (except misc_model).
25 /// This entity behaves as a group, i.e. it contains brushes.
28 #include "renderable.h"
31 #include "selectionlib.h"
32 #include "instancelib.h"
33 #include "transformlib.h"
34 #include "traverselib.h"
35 #include "entitylib.h"
37 #include "eclasslib.h"
39 #include "targetable.h"
44 #include "namedentity.h"
45 #include "keyobservers.h"
50 /// The "origin" key directly controls the entity's local-to-parent transform.
54 EntityKeyValues m_entity;
55 KeyObserverMap m_keyObservers;
56 MatrixTransform m_transform;
57 TraversableNodeSet m_traverse;
59 ClassnameFilter m_filter;
63 OriginKey m_originKey;
66 RenderableNamedEntity m_renderName;
67 mutable Vector3 m_name_origin;
69 Callback m_transformChanged;
70 Callback m_evaluateTransform;
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));
80 Group(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
82 m_filter(m_entity, node),
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)
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),
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)
108 InstanceCounter m_instanceCounter;
109 void instanceAttach(const scene::Path& path)
111 if(++m_instanceCounter.m_count == 1)
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);
119 void instanceDetach(const scene::Path& path)
121 if(--m_instanceCounter.m_count == 0)
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();
130 EntityKeyValues& getEntity()
134 const EntityKeyValues& getEntity() const
139 scene::Traversable& getTraversable()
143 Namespaced& getNamespaced()
147 Nameable& getNameable()
151 TransformNode& getTransformNode()
156 void attach(scene::Traversable::Observer* observer)
158 m_traverse.attach(observer);
160 void detach(scene::Traversable::Observer* observer)
162 m_traverse.detach(observer);
165 void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
167 renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
170 void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, const AABB& childBounds) const
172 renderSolid(renderer, volume, localToWorld);
176 // don't draw the name for worldspawn
177 if(!strcmp(m_entity.getEntityClass().name(), "worldspawn"))
180 // place name in the middle of the "children cloud"
181 m_name_origin = childBounds.origin;
183 renderer.addRenderable(m_renderName, localToWorld);
187 void updateTransform()
189 m_transform.localToParent() = g_matrix4_identity;
190 matrix4_translate_by_vec3(m_transform.localToParent(), m_origin);
191 m_transformChanged();
193 typedef MemberCaller<Group, &Group::updateTransform> UpdateTransformCaller;
196 m_origin = m_originKey.m_origin;
199 typedef MemberCaller<Group, &Group::originChanged> OriginChangedCaller;
201 void translate(const Vector3& translation)
203 m_origin = origin_translated(m_origin, translation);
206 void revertTransform()
208 m_origin = m_originKey.m_origin;
210 void freezeTransform()
212 m_originKey.m_origin = m_origin;
213 m_originKey.write(&m_entity);
215 void transformChanged()
218 m_evaluateTransform();
221 typedef MemberCaller<Group, &Group::transformChanged> TransformChangedCaller;
225 class TransformableSetTranslation
229 TransformableSetTranslation(const Translation& value) : m_value(value)
232 void operator()(Transformable& transformable) const
234 transformable.setTranslation(m_value);
238 class TransformableSetRotation
242 TransformableSetRotation(const Rotation& value) : m_value(value)
245 void operator()(Transformable& transformable) const
247 transformable.setRotation(m_value);
251 class TransformableSetScale
255 TransformableSetScale(const Scale& value) : m_value(value)
258 void operator()(Transformable& transformable) const
260 transformable.setScale(m_value);
264 class TransformableSetType
266 TransformModifierType m_value;
268 TransformableSetType(const TransformModifierType& value) : m_value(value)
271 void operator()(Transformable& transformable) const
273 transformable.setType(m_value);
277 class TransformableFreezeTransform
279 TransformModifierType m_value;
281 void operator()(Transformable& transformable) const
283 transformable.freezeTransform();
287 template<typename Functor>
288 inline void Scene_forEachChildTransformable(const Functor& functor, const scene::Path& path)
290 GlobalSceneGraph().traverse_subgraph(ChildInstanceWalker< InstanceApply<Transformable, Functor> >(functor), path);
294 class GroupInstance :
295 public TargetableInstance,
296 public TransformModifier,
298 public Transformable,
304 InstanceTypeCastTable m_casts;
308 m_casts = TargetableInstance::StaticTypeCasts::instance().get();
309 InstanceStaticCast<GroupInstance, Renderable>::install(m_casts);
311 InstanceStaticCast<GroupInstance, Transformable>::install(m_casts);
314 InstanceTypeCastTable& get()
322 typedef LazyStatic<TypeCasts> StaticTypeCasts;
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)),
329 m_contained.instanceAttach(Instance::path());
330 StaticRenderableConnectionLines::instance().attach(*this);
334 StaticRenderableConnectionLines::instance().detach(*this);
335 m_contained.instanceDetach(Instance::path());
337 void renderSolid(Renderer& renderer, const VolumeTest& volume) const
339 m_contained.renderSolid(renderer, volume, Instance::localToWorld());
341 void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
343 m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), Instance::childBounds());
346 STRING_CONSTANT(Name, "GroupInstance");
349 void setType(TransformModifierType type)
351 Scene_forEachChildTransformable(TransformableSetType(type), Instance::path());
353 void setTranslation(const Translation& value)
355 Scene_forEachChildTransformable(TransformableSetTranslation(value), Instance::path());
357 void setRotation(const Rotation& value)
359 Scene_forEachChildTransformable(TransformableSetRotation(value), Instance::path());
361 void setScale(const Scale& value)
363 Scene_forEachChildTransformable(TransformableSetScale(value), Instance::path());
365 void freezeTransform()
367 Scene_forEachChildTransformable(TransformableFreezeTransform(), Instance::path());
370 void evaluateTransform()
375 void evaluateTransform()
377 if(getType() == TRANSFORM_PRIMITIVE)
379 m_contained.translate(getTranslation());
382 void applyTransform()
384 m_contained.revertTransform();
386 m_contained.freezeTransform();
388 typedef MemberCaller<GroupInstance, &GroupInstance::applyTransform> ApplyTransformCaller;
392 public scene::Node::Symbiot,
393 public scene::Instantiable,
394 public scene::Cloneable,
395 public scene::Traversable::Observer
399 NodeTypeCastTable m_casts;
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);
411 NodeTypeCastTable& get()
419 InstanceSet m_instances;
424 m_contained.attach(this);
428 m_contained.detach(this);
433 typedef LazyStatic<TypeCasts> StaticTypeCasts;
435 scene::Traversable& get(NullType<scene::Traversable>)
437 return m_contained.getTraversable();
439 TransformNode& get(NullType<TransformNode>)
441 return m_contained.getTransformNode();
443 Entity& get(NullType<Entity>)
445 return m_contained.getEntity();
447 Nameable& get(NullType<Nameable>)
449 return m_contained.getNameable();
451 Namespaced& get(NullType<Namespaced>)
453 return m_contained.getNamespaced();
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))
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))
486 scene::Node& clone() const
488 return (new GroupNode(*this))->node();
491 void insert(scene::Node& child)
493 m_instances.insert(child);
495 void erase(scene::Node& child)
497 m_instances.erase(child);
500 scene::Instance* create(const scene::Path& path, scene::Instance* parent)
502 return new GroupInstance(path, parent, m_contained);
504 void forEachInstance(const scene::Instantiable::Visitor& visitor)
506 m_instances.forEachInstance(visitor);
508 void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
510 m_instances.insert(observer, path, instance);
512 scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
514 return m_instances.erase(observer, path);
518 scene::Node& New_Group(EntityClass* eclass)
520 return (new GroupNode(eclass))->node();