]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/entity/group.cpp
Merge branch 'master' into divVerent/farplanedist-sky-fix
[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 {
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         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& transformChanged, const Callback& evaluateTransform ) :
80         m_entity( eclass ),
81         m_filter( m_entity, node ),
82         m_named( m_entity ),
83         m_nameKeys( m_entity ),
84         m_originKey( OriginChangedCaller( *this ) ),
85         m_origin( ORIGINKEY_IDENTITY ),
86         m_renderName( m_named, m_name_origin ),
87         m_name_origin( g_vector3_identity ),
88         m_transformChanged( transformChanged ),
89         m_evaluateTransform( evaluateTransform ){
90         construct();
91 }
92 Group( const Group& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform ) :
93         m_entity( other.m_entity ),
94         m_filter( m_entity, node ),
95         m_named( m_entity ),
96         m_nameKeys( m_entity ),
97         m_originKey( OriginChangedCaller( *this ) ),
98         m_origin( ORIGINKEY_IDENTITY ),
99         m_renderName( m_named, g_vector3_identity ),
100         m_transformChanged( transformChanged ),
101         m_evaluateTransform( evaluateTransform ){
102         construct();
103 }
104
105 InstanceCounter m_instanceCounter;
106 void instanceAttach( const scene::Path& path ){
107         if ( ++m_instanceCounter.m_count == 1 ) {
108                 m_filter.instanceAttach();
109                 m_entity.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
110                 m_traverse.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
111                 m_entity.attach( m_keyObservers );
112         }
113 }
114 void instanceDetach( const scene::Path& path ){
115         if ( --m_instanceCounter.m_count == 0 ) {
116                 m_entity.detach( m_keyObservers );
117                 m_traverse.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
118                 m_entity.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
119                 m_filter.instanceDetach();
120         }
121 }
122
123 EntityKeyValues& getEntity(){
124         return m_entity;
125 }
126 const EntityKeyValues& getEntity() const {
127         return m_entity;
128 }
129
130 scene::Traversable& getTraversable(){
131         return m_traverse;
132 }
133 Namespaced& getNamespaced(){
134         return m_nameKeys;
135 }
136 Nameable& getNameable(){
137         return m_named;
138 }
139 TransformNode& getTransformNode(){
140         return m_transform;
141 }
142
143 void attach( scene::Traversable::Observer* observer ){
144         m_traverse.attach( observer );
145 }
146 void detach( scene::Traversable::Observer* observer ){
147         m_traverse.detach( observer );
148 }
149
150 void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const {
151         renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly );
152 }
153
154 void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, const AABB& childBounds ) const {
155         renderSolid( renderer, volume, localToWorld );
156
157         if ( g_showNames ) {
158                 // don't draw the name for worldspawn
159                 if ( !strcmp( m_entity.getEntityClass().name(), "worldspawn" ) ) {
160                         return;
161                 }
162
163                 // place name in the middle of the "children cloud"
164                 m_name_origin = childBounds.origin;
165
166                 renderer.addRenderable( m_renderName, localToWorld );
167         }
168 }
169
170 void updateTransform(){
171         m_transform.localToParent() = g_matrix4_identity;
172         matrix4_translate_by_vec3( m_transform.localToParent(), m_origin );
173         m_transformChanged();
174 }
175 typedef MemberCaller<Group, &Group::updateTransform> UpdateTransformCaller;
176 void originChanged(){
177         m_origin = m_originKey.m_origin;
178         updateTransform();
179 }
180 typedef MemberCaller<Group, &Group::originChanged> OriginChangedCaller;
181
182 void translate( const Vector3& translation ){
183         m_origin = origin_translated( m_origin, translation );
184 }
185
186 void revertTransform(){
187         m_origin = m_originKey.m_origin;
188 }
189 void freezeTransform(){
190         m_originKey.m_origin = m_origin;
191         m_originKey.write( &m_entity );
192 }
193 void transformChanged(){
194         revertTransform();
195         m_evaluateTransform();
196         updateTransform();
197 }
198 typedef MemberCaller<Group, &Group::transformChanged> TransformChangedCaller;
199 };
200
201 #if 0
202 class TransformableSetTranslation
203 {
204 Translation m_value;
205 public:
206 TransformableSetTranslation( const Translation& value ) : m_value( value ){
207 }
208 void operator()( Transformable& transformable ) const {
209         transformable.setTranslation( m_value );
210 }
211 };
212
213 class TransformableSetRotation
214 {
215 Rotation m_value;
216 public:
217 TransformableSetRotation( const Rotation& value ) : m_value( value ){
218 }
219 void operator()( Transformable& transformable ) const {
220         transformable.setRotation( m_value );
221 }
222 };
223
224 class TransformableSetScale
225 {
226 Scale m_value;
227 public:
228 TransformableSetScale( const Scale& value ) : m_value( value ){
229 }
230 void operator()( Transformable& transformable ) const {
231         transformable.setScale( m_value );
232 }
233 };
234
235 class TransformableSetType
236 {
237 TransformModifierType m_value;
238 public:
239 TransformableSetType( const TransformModifierType& value ) : m_value( value ){
240 }
241 void operator()( Transformable& transformable ) const {
242         transformable.setType( m_value );
243 }
244 };
245
246 class TransformableFreezeTransform
247 {
248 TransformModifierType m_value;
249 public:
250 void operator()( Transformable& transformable ) const {
251         transformable.freezeTransform();
252 }
253 };
254
255 template<typename Functor>
256 inline void Scene_forEachChildTransformable( const Functor& functor, const scene::Path& path ){
257         GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply<Transformable, Functor> >( functor ), path );
258 }
259 #endif
260
261 class GroupInstance :
262         public TargetableInstance,
263         public TransformModifier,
264 #if 0
265         public Transformable,
266 #endif
267         public Renderable
268 {
269 class TypeCasts
270 {
271 InstanceTypeCastTable m_casts;
272 public:
273 TypeCasts(){
274         m_casts = TargetableInstance::StaticTypeCasts::instance().get();
275         InstanceStaticCast<GroupInstance, Renderable>::install( m_casts );
276 #if 0
277         InstanceStaticCast<GroupInstance, Transformable>::install( m_casts );
278 #endif
279 }
280 InstanceTypeCastTable& get(){
281         return m_casts;
282 }
283 };
284
285 Group& m_contained;
286 public:
287 typedef LazyStatic<TypeCasts> StaticTypeCasts;
288
289 GroupInstance( const scene::Path& path, scene::Instance* parent, Group& group ) :
290         TargetableInstance( path, parent, this, StaticTypeCasts::instance().get(), group.getEntity(), *this ),
291         TransformModifier( Group::TransformChangedCaller( group ), ApplyTransformCaller( *this ) ),
292         m_contained( group ){
293         m_contained.instanceAttach( Instance::path() );
294         StaticRenderableConnectionLines::instance().attach( *this );
295 }
296 ~GroupInstance(){
297         StaticRenderableConnectionLines::instance().detach( *this );
298         m_contained.instanceDetach( Instance::path() );
299 }
300 void renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
301         m_contained.renderSolid( renderer, volume, Instance::localToWorld() );
302 }
303 void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const {
304         m_contained.renderWireframe( renderer, volume, Instance::localToWorld(), Instance::childBounds() );
305 }
306
307 STRING_CONSTANT( Name, "GroupInstance" );
308
309 #if 0
310 void setType( TransformModifierType type ){
311         Scene_forEachChildTransformable( TransformableSetType( type ), Instance::path() );
312 }
313 void setTranslation( const Translation& value ){
314         Scene_forEachChildTransformable( TransformableSetTranslation( value ), Instance::path() );
315 }
316 void setRotation( const Rotation& value ){
317         Scene_forEachChildTransformable( TransformableSetRotation( value ), Instance::path() );
318 }
319 void setScale( const Scale& value ){
320         Scene_forEachChildTransformable( TransformableSetScale( value ), Instance::path() );
321 }
322 void freezeTransform(){
323         Scene_forEachChildTransformable( TransformableFreezeTransform(), Instance::path() );
324 }
325
326 void evaluateTransform(){
327 }
328 #endif
329
330 void evaluateTransform(){
331         if ( getType() == TRANSFORM_PRIMITIVE ) {
332                 m_contained.translate( getTranslation() );
333         }
334 }
335 void applyTransform(){
336         m_contained.revertTransform();
337         evaluateTransform();
338         m_contained.freezeTransform();
339 }
340 typedef MemberCaller<GroupInstance, &GroupInstance::applyTransform> ApplyTransformCaller;
341 };
342
343 class GroupNode :
344         public scene::Node::Symbiot,
345         public scene::Instantiable,
346         public scene::Cloneable,
347         public scene::Traversable::Observer
348 {
349 class TypeCasts
350 {
351 NodeTypeCastTable m_casts;
352 public:
353 TypeCasts(){
354         NodeStaticCast<GroupNode, scene::Instantiable>::install( m_casts );
355         NodeStaticCast<GroupNode, scene::Cloneable>::install( m_casts );
356         NodeContainedCast<GroupNode, scene::Traversable>::install( m_casts );
357         NodeContainedCast<GroupNode, TransformNode>::install( m_casts );
358         NodeContainedCast<GroupNode, Entity>::install( m_casts );
359         NodeContainedCast<GroupNode, Nameable>::install( m_casts );
360         NodeContainedCast<GroupNode, Namespaced>::install( m_casts );
361 }
362 NodeTypeCastTable& get(){
363         return m_casts;
364 }
365 };
366
367
368 scene::Node m_node;
369 InstanceSet m_instances;
370 Group m_contained;
371
372 void construct(){
373         m_contained.attach( this );
374 }
375 void destroy(){
376         m_contained.detach( this );
377 }
378
379 public:
380
381 typedef LazyStatic<TypeCasts> StaticTypeCasts;
382
383 scene::Traversable& get( NullType<scene::Traversable>){
384         return m_contained.getTraversable();
385 }
386 TransformNode& get( NullType<TransformNode>){
387         return m_contained.getTransformNode();
388 }
389 Entity& get( NullType<Entity>){
390         return m_contained.getEntity();
391 }
392 Nameable& get( NullType<Nameable>){
393         return m_contained.getNameable();
394 }
395 Namespaced& get( NullType<Namespaced>){
396         return m_contained.getNamespaced();
397 }
398
399 GroupNode( EntityClass* eclass ) :
400         m_node( this, this, StaticTypeCasts::instance().get() ),
401         m_contained( eclass, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<GroupInstance>::Caller( m_instances ) ){
402         construct();
403 }
404 GroupNode( const GroupNode& other ) :
405         scene::Node::Symbiot( other ),
406         scene::Instantiable( other ),
407         scene::Cloneable( other ),
408         scene::Traversable::Observer( other ),
409         m_node( this, this, StaticTypeCasts::instance().get() ),
410         m_contained( other.m_contained, m_node, InstanceSet::TransformChangedCaller( m_instances ), InstanceSetEvaluateTransform<GroupInstance>::Caller( m_instances ) ){
411         construct();
412 }
413 ~GroupNode(){
414         destroy();
415 }
416
417 void release(){
418         delete this;
419 }
420 scene::Node& node(){
421         return m_node;
422 }
423
424 scene::Node& clone() const {
425         return ( new GroupNode( *this ) )->node();
426 }
427
428 void insert( scene::Node& child ){
429         m_instances.insert( child );
430 }
431 void erase( scene::Node& child ){
432         m_instances.erase( child );
433 }
434
435 scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
436         return new GroupInstance( path, parent, m_contained );
437 }
438 void forEachInstance( const scene::Instantiable::Visitor& visitor ){
439         m_instances.forEachInstance( visitor );
440 }
441 void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
442         m_instances.insert( observer, path, instance );
443 }
444 scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
445         return m_instances.erase( observer, path );
446 }
447 };
448
449 scene::Node& New_Group( EntityClass* eclass ){
450         return ( new GroupNode( eclass ) )->node();
451 }