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