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 mutable Vector3 m_name_origin;
67 RenderableNamedEntity m_renderName;
69 Callback<void()> m_transformChanged;
70 Callback<void()> m_evaluateTransform;
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 ) );
79 Group( EntityClass* eclass, scene::Node& node, const Callback<void()>& transformChanged, const Callback<void()>& evaluateTransform ) :
81 m_filter( m_entity, node ),
83 m_nameKeys( m_entity ),
84 m_originKey( OriginChangedCaller( *this ) ),
85 m_origin( ORIGINKEY_IDENTITY ),
86 m_name_origin( g_vector3_identity ),
87 m_renderName( m_named, m_name_origin ),
88 m_transformChanged( transformChanged ),
89 m_evaluateTransform( evaluateTransform ){
92 Group( const Group& other, scene::Node& node, const Callback<void()>& transformChanged, const Callback<void()>& evaluateTransform ) :
93 m_entity( other.m_entity ),
94 m_filter( m_entity, node ),
96 m_nameKeys( m_entity ),
97 m_originKey( OriginChangedCaller( *this ) ),
98 m_origin( ORIGINKEY_IDENTITY ),
99 m_name_origin( g_vector3_identity ),
100 m_renderName( m_named, m_name_origin ),
101 m_transformChanged( transformChanged ),
102 m_evaluateTransform( evaluateTransform ){
106 InstanceCounter m_instanceCounter;
107 void instanceAttach( const scene::Path& path ){
108 if ( ++m_instanceCounter.m_count == 1 ) {
109 m_filter.instanceAttach();
110 m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
111 m_traverse.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
112 m_entity.attach( m_keyObservers );
115 void instanceDetach( const scene::Path& path ){
116 if ( --m_instanceCounter.m_count == 0 ) {
117 m_entity.detach( m_keyObservers );
118 m_traverse.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
119 m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
120 m_filter.instanceDetach();
124 EntityKeyValues& getEntity(){
127 const EntityKeyValues& getEntity() const {
131 scene::Traversable& getTraversable(){
134 Namespaced& getNamespaced(){
137 Nameable& getNameable(){
140 TransformNode& getTransformNode(){
144 void attach( scene::Traversable::Observer* observer ){
145 m_traverse.attach( observer );
147 void detach( scene::Traversable::Observer* observer ){
148 m_traverse.detach( observer );
151 void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
152 renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly );
155 void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, const AABB& childBounds ) const {
156 renderSolid( renderer, volume, localToWorld );
159 // don't draw the name for worldspawn
160 if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) {
164 // place name in the middle of the "children cloud"
165 m_name_origin = childBounds.origin;
167 renderer.addRenderable( m_renderName, localToWorld );
171 void updateTransform(){
172 m_transform.localToParent() = g_matrix4_identity;
173 matrix4_translate_by_vec3( m_transform.localToParent(), m_origin );
174 m_transformChanged();
176 typedef MemberCaller<Group, void(), &Group::updateTransform> UpdateTransformCaller;
177 void originChanged(){
178 m_origin = m_originKey.m_origin;
181 typedef MemberCaller<Group, void(), &Group::originChanged> OriginChangedCaller;
183 void translate( const Vector3& translation ){
184 m_origin = origin_translated( m_origin, translation );
187 void revertTransform(){
188 m_origin = m_originKey.m_origin;
190 void freezeTransform(){
191 m_originKey.m_origin = m_origin;
192 m_originKey.write( &m_entity );
194 void transformChanged(){
196 m_evaluateTransform();
199 typedef MemberCaller<Group, void(), &Group::transformChanged> TransformChangedCaller;
203 class TransformableSetTranslation
207 TransformableSetTranslation( const Translation& value ) : m_value( value ){
209 void operator()( Transformable& transformable ) const {
210 transformable.setTranslation( m_value );
214 class TransformableSetRotation
218 TransformableSetRotation( const Rotation& value ) : m_value( value ){
220 void operator()( Transformable& transformable ) const {
221 transformable.setRotation( m_value );
225 class TransformableSetScale
229 TransformableSetScale( const Scale& value ) : m_value( value ){
231 void operator()( Transformable& transformable ) const {
232 transformable.setScale( m_value );
236 class TransformableSetType
238 TransformModifierType m_value;
240 TransformableSetType( const TransformModifierType& value ) : m_value( value ){
242 void operator()( Transformable& transformable ) const {
243 transformable.setType( m_value );
247 class TransformableFreezeTransform
249 TransformModifierType m_value;
251 void operator()( Transformable& transformable ) const {
252 transformable.freezeTransform();
256 template<typename Functor>
257 inline void Scene_forEachChildTransformable( const Functor& functor, const scene::Path& path ){
258 GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply<Transformable, Functor> >( functor ), path );
262 class GroupInstance :
263 public TargetableInstance,
264 public TransformModifier,
266 public Transformable,
272 InstanceTypeCastTable m_casts;
275 m_casts = TargetableInstance::StaticTypeCasts::instance().get();
276 InstanceStaticCast<GroupInstance, Renderable>::install( m_casts );
278 InstanceStaticCast<GroupInstance, Transformable>::install( m_casts );
281 InstanceTypeCastTable& get(){
288 typedef LazyStatic<TypeCasts> StaticTypeCasts;
290 GroupInstance( const scene::Path& path, scene::Instance* parent, Group& group ) :
291 TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), group.getEntity(), *this ),
292 TransformModifier( Group::TransformChangedCaller( group ), ApplyTransformCaller( *this ) ),
293 m_contained( group ){
294 m_contained.instanceAttach( Instance::path() );
295 StaticRenderableConnectionLines::instance().attach( *this );
298 StaticRenderableConnectionLines::instance().detach( *this );
299 m_contained.instanceDetach( Instance::path() );
301 void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
302 m_contained.renderSolid( renderer, volume, Instance::localToWorld() );
304 void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
305 m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), Instance::childBounds() );
308 STRING_CONSTANT( Name, "GroupInstance" );
311 void setType( TransformModifierType type ){
312 Scene_forEachChildTransformable( TransformableSetType( type ), Instance::path() );
314 void setTranslation( const Translation& value ){
315 Scene_forEachChildTransformable( TransformableSetTranslation( value ), Instance::path() );
317 void setRotation( const Rotation& value ){
318 Scene_forEachChildTransformable( TransformableSetRotation( value ), Instance::path() );
320 void setScale( const Scale& value ){
321 Scene_forEachChildTransformable( TransformableSetScale( value ), Instance::path() );
323 void freezeTransform(){
324 Scene_forEachChildTransformable( TransformableFreezeTransform(), Instance::path() );
327 void evaluateTransform(){
331 void evaluateTransform(){
332 if ( getType() == TRANSFORM_PRIMITIVE ) {
333 m_contained.translate( getTranslation() );
336 void applyTransform(){
337 m_contained.revertTransform();
339 m_contained.freezeTransform();
341 typedef MemberCaller<GroupInstance, void(), &GroupInstance::applyTransform> ApplyTransformCaller;
345 public scene::Node::Symbiot,
346 public scene::Instantiable,
347 public scene::Cloneable,
348 public scene::Traversable::Observer
352 NodeTypeCastTable m_casts;
355 NodeStaticCast<GroupNode, scene::Instantiable>::install( m_casts );
356 NodeStaticCast<GroupNode, scene::Cloneable>::install( m_casts );
357 NodeContainedCast<GroupNode, scene::Traversable>::install( m_casts );
358 NodeContainedCast<GroupNode, TransformNode>::install( m_casts );
359 NodeContainedCast<GroupNode, Entity>::install( m_casts );
360 NodeContainedCast<GroupNode, Nameable>::install( m_casts );
361 NodeContainedCast<GroupNode, Namespaced>::install( m_casts );
363 NodeTypeCastTable& get(){
370 InstanceSet m_instances;
374 m_contained.attach( this );
377 m_contained.detach( this );
382 typedef LazyStatic<TypeCasts> StaticTypeCasts;
384 scene::Traversable& get( NullType<scene::Traversable>){
385 return m_contained.getTraversable();
387 TransformNode& get( NullType<TransformNode>){
388 return m_contained.getTransformNode();
390 Entity& get( NullType<Entity>){
391 return m_contained.getEntity();
393 Nameable& get( NullType<Nameable>){
394 return m_contained.getNameable();
396 Namespaced& get( NullType<Namespaced>){
397 return m_contained.getNamespaced();
400 GroupNode( EntityClass* eclass ) :
401 m_node( this, this, StaticTypeCasts::instance().get() ),
402 m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<GroupInstance>::Caller( m_instances ) ){
405 GroupNode( const GroupNode& other ) :
406 scene::Node::Symbiot( other ),
407 scene::Instantiable( other ),
408 scene::Cloneable( other ),
409 scene::Traversable::Observer( other ),
410 m_node( this, this, StaticTypeCasts::instance().get() ),
411 m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<GroupInstance>::Caller( m_instances ) ){
425 scene::Node& clone() const {
426 return ( new GroupNode( *this ) )->node();
429 void insert( scene::Node& child ){
430 m_instances.insert( child );
432 void erase( scene::Node& child ){
433 m_instances.erase( child );
436 scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
437 return new GroupInstance( path, parent, m_contained );
439 void forEachInstance( const scene::Instantiable::Visitor& visitor ){
440 m_instances.forEachInstance( visitor );
442 void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
443 m_instances.insert( observer, path, instance );
445 scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
446 return m_instances.erase( observer, path );
450 scene::Node& New_Group( EntityClass* eclass ){
451 return ( new GroupNode( eclass ) )->node();