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
22 #if !defined (INCLUDED_ENTITYLIB_H)
23 #define INCLUDED_ENTITYLIB_H
25 #include "ireference.h"
26 #include "debugging/debugging.h"
31 #include "selectable.h"
33 #include "generic/callback.h"
34 #include "math/vector.h"
35 #include "math/aabb.h"
37 #include "string/pooledstring.h"
38 #include "generic/referencecounted.h"
40 #include "container/container.h"
41 #include "eclasslib.h"
46 inline void arrow_draw(const Vector3& origin, const Vector3& direction_forward, const Vector3& direction_left, const Vector3& direction_up)
48 Vector3 endpoint(vector3_added(origin, vector3_scaled(direction_forward, 32.0)));
50 Vector3 tip1(vector3_added(vector3_added(endpoint, vector3_scaled(direction_forward, -8.0)), vector3_scaled(direction_up, -4.0)));
51 Vector3 tip2(vector3_added(tip1, vector3_scaled(direction_up, 8.0)));
52 Vector3 tip3(vector3_added(vector3_added(endpoint, vector3_scaled(direction_forward, -8.0)), vector3_scaled(direction_left, -4.0)));
53 Vector3 tip4(vector3_added(tip3, vector3_scaled(direction_left, 8.0)));
57 glVertex3fv(vector3_to_array(origin));
58 glVertex3fv(vector3_to_array(endpoint));
60 glVertex3fv(vector3_to_array(endpoint));
61 glVertex3fv(vector3_to_array(tip1));
63 glVertex3fv(vector3_to_array(endpoint));
64 glVertex3fv(vector3_to_array(tip2));
66 glVertex3fv(vector3_to_array(endpoint));
67 glVertex3fv(vector3_to_array(tip3));
69 glVertex3fv(vector3_to_array(endpoint));
70 glVertex3fv(vector3_to_array(tip4));
72 glVertex3fv(vector3_to_array(tip1));
73 glVertex3fv(vector3_to_array(tip3));
75 glVertex3fv(vector3_to_array(tip3));
76 glVertex3fv(vector3_to_array(tip2));
78 glVertex3fv(vector3_to_array(tip2));
79 glVertex3fv(vector3_to_array(tip4));
81 glVertex3fv(vector3_to_array(tip4));
82 glVertex3fv(vector3_to_array(tip1));
87 class SelectionIntersection;
89 inline void aabb_testselect(const AABB& aabb, SelectionTest& test, SelectionIntersection& best)
91 const IndexPointer::index_type indices[24] = {
101 aabb_corners(aabb, points);
102 test.TestQuads(VertexPointer(reinterpret_cast<VertexPointer::pointer>(points), sizeof(Vector3)), IndexPointer(indices, 24), best);
105 inline void aabb_draw_wire(const Vector3 points[8])
107 unsigned int indices[26] = {
108 0, 1, 1, 2, 2, 3, 3, 0,
109 4, 5, 5, 6, 6, 7, 7, 4,
110 0, 4, 1, 5, 2, 6, 3, 7,
111 // 0, 6, 1, 7, 2, 4, 3, 5 // X cross
112 1, 7 // diagonal line (connect mins to maxs corner)
115 glVertexPointer(3, GL_FLOAT, 0, points);
116 glDrawElements(GL_LINES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_INT, indices);
119 for(std::size_t i = 0; i < sizeof(indices)/sizeof(indices[0]); ++i)
121 glVertex3fv(points[indices[i]]);
127 inline void aabb_draw_flatshade(const Vector3 points[8])
131 glNormal3fv(vector3_to_array(aabb_normals[0]));
132 glVertex3fv(vector3_to_array(points[2]));
133 glVertex3fv(vector3_to_array(points[1]));
134 glVertex3fv(vector3_to_array(points[5]));
135 glVertex3fv(vector3_to_array(points[6]));
137 glNormal3fv(vector3_to_array(aabb_normals[1]));
138 glVertex3fv(vector3_to_array(points[1]));
139 glVertex3fv(vector3_to_array(points[0]));
140 glVertex3fv(vector3_to_array(points[4]));
141 glVertex3fv(vector3_to_array(points[5]));
143 glNormal3fv(vector3_to_array(aabb_normals[2]));
144 glVertex3fv(vector3_to_array(points[0]));
145 glVertex3fv(vector3_to_array(points[1]));
146 glVertex3fv(vector3_to_array(points[2]));
147 glVertex3fv(vector3_to_array(points[3]));
149 glNormal3fv(vector3_to_array(aabb_normals[3]));
150 glVertex3fv(vector3_to_array(points[0]));
151 glVertex3fv(vector3_to_array(points[3]));
152 glVertex3fv(vector3_to_array(points[7]));
153 glVertex3fv(vector3_to_array(points[4]));
155 glNormal3fv(vector3_to_array(aabb_normals[4]));
156 glVertex3fv(vector3_to_array(points[3]));
157 glVertex3fv(vector3_to_array(points[2]));
158 glVertex3fv(vector3_to_array(points[6]));
159 glVertex3fv(vector3_to_array(points[7]));
161 glNormal3fv(vector3_to_array(aabb_normals[5]));
162 glVertex3fv(vector3_to_array(points[7]));
163 glVertex3fv(vector3_to_array(points[6]));
164 glVertex3fv(vector3_to_array(points[5]));
165 glVertex3fv(vector3_to_array(points[4]));
170 inline void aabb_draw_wire(const AABB& aabb)
173 aabb_corners(aabb, points);
174 aabb_draw_wire(points);
177 inline void aabb_draw_flatshade(const AABB& aabb)
180 aabb_corners(aabb, points);
181 aabb_draw_flatshade(points);
184 inline void aabb_draw_textured(const AABB& aabb)
187 aabb_corners(aabb, points);
191 glNormal3fv(vector3_to_array(aabb_normals[0]));
192 glTexCoord2fv(aabb_texcoord_topleft);
193 glVertex3fv(vector3_to_array(points[2]));
194 glTexCoord2fv(aabb_texcoord_topright);
195 glVertex3fv(vector3_to_array(points[1]));
196 glTexCoord2fv(aabb_texcoord_botright);
197 glVertex3fv(vector3_to_array(points[5]));
198 glTexCoord2fv(aabb_texcoord_botleft);
199 glVertex3fv(vector3_to_array(points[6]));
201 glNormal3fv(vector3_to_array(aabb_normals[1]));
202 glTexCoord2fv(aabb_texcoord_topleft);
203 glVertex3fv(vector3_to_array(points[1]));
204 glTexCoord2fv(aabb_texcoord_topright);
205 glVertex3fv(vector3_to_array(points[0]));
206 glTexCoord2fv(aabb_texcoord_botright);
207 glVertex3fv(vector3_to_array(points[4]));
208 glTexCoord2fv(aabb_texcoord_botleft);
209 glVertex3fv(vector3_to_array(points[5]));
211 glNormal3fv(vector3_to_array(aabb_normals[2]));
212 glTexCoord2fv(aabb_texcoord_topleft);
213 glVertex3fv(vector3_to_array(points[0]));
214 glTexCoord2fv(aabb_texcoord_topright);
215 glVertex3fv(vector3_to_array(points[1]));
216 glTexCoord2fv(aabb_texcoord_botright);
217 glVertex3fv(vector3_to_array(points[2]));
218 glTexCoord2fv(aabb_texcoord_botleft);
219 glVertex3fv(vector3_to_array(points[3]));
221 glNormal3fv(vector3_to_array(aabb_normals[3]));
222 glTexCoord2fv(aabb_texcoord_topleft);
223 glVertex3fv(vector3_to_array(points[0]));
224 glTexCoord2fv(aabb_texcoord_topright);
225 glVertex3fv(vector3_to_array(points[3]));
226 glTexCoord2fv(aabb_texcoord_botright);
227 glVertex3fv(vector3_to_array(points[7]));
228 glTexCoord2fv(aabb_texcoord_botleft);
229 glVertex3fv(vector3_to_array(points[4]));
231 glNormal3fv(vector3_to_array(aabb_normals[4]));
232 glTexCoord2fv(aabb_texcoord_topleft);
233 glVertex3fv(vector3_to_array(points[3]));
234 glTexCoord2fv(aabb_texcoord_topright);
235 glVertex3fv(vector3_to_array(points[2]));
236 glTexCoord2fv(aabb_texcoord_botright);
237 glVertex3fv(vector3_to_array(points[6]));
238 glTexCoord2fv(aabb_texcoord_botleft);
239 glVertex3fv(vector3_to_array(points[7]));
241 glNormal3fv(vector3_to_array(aabb_normals[5]));
242 glTexCoord2fv(aabb_texcoord_topleft);
243 glVertex3fv(vector3_to_array(points[7]));
244 glTexCoord2fv(aabb_texcoord_topright);
245 glVertex3fv(vector3_to_array(points[6]));
246 glTexCoord2fv(aabb_texcoord_botright);
247 glVertex3fv(vector3_to_array(points[5]));
248 glTexCoord2fv(aabb_texcoord_botleft);
249 glVertex3fv(vector3_to_array(points[4]));
254 inline void aabb_draw_solid(const AABB& aabb, RenderStateFlags state)
256 if(state & RENDER_TEXTURE)
258 aabb_draw_textured(aabb);
262 aabb_draw_flatshade(aabb);
266 inline void aabb_draw(const AABB& aabb, RenderStateFlags state)
268 if(state & RENDER_FILL)
270 aabb_draw_solid(aabb, state);
274 aabb_draw_wire(aabb);
278 class RenderableSolidAABB : public OpenGLRenderable
282 RenderableSolidAABB(const AABB& aabb) : m_aabb(aabb)
285 void render(RenderStateFlags state) const
287 aabb_draw_solid(m_aabb, state);
291 class RenderableWireframeAABB : public OpenGLRenderable
295 RenderableWireframeAABB(const AABB& aabb) : m_aabb(aabb)
298 void render(RenderStateFlags state) const
300 aabb_draw_wire(m_aabb);
305 /// \brief A key/value pair of strings.
307 /// - Notifies observers when value changes - value changes to "" on destruction.
308 /// - Provides undo support through the global undo system.
309 class KeyValue : public EntityKeyValue
311 typedef UnsortedSet<KeyObserver> KeyObservers;
313 std::size_t m_refcount;
314 KeyObservers m_observers;
315 CopiedString m_string;
317 ObservedUndoableObject<CopiedString> m_undo;
318 static EntityCreator::KeyValueChangedFunc m_entityKeyValueChanged;
321 KeyValue(const char* string, const char* empty)
322 : m_refcount(0), m_string(string), m_empty(empty), m_undo(m_string, UndoImportCaller(*this))
328 ASSERT_MESSAGE(m_observers.empty(), "KeyValue::~KeyValue: observers still attached");
331 static void setKeyValueChangedFunc(EntityCreator::KeyValueChangedFunc func)
333 m_entityKeyValueChanged = func;
342 if(--m_refcount == 0)
348 void instanceAttach(MapFile* map)
350 m_undo.instanceAttach(map);
352 void instanceDetach(MapFile* map)
354 m_undo.instanceDetach(map);
357 void attach(const KeyObserver& observer)
359 (*m_observers.insert(observer))(c_str());
361 void detach(const KeyObserver& observer)
364 m_observers.erase(observer);
366 const char* c_str() const
368 if(string_empty(m_string.c_str()))
372 return m_string.c_str();
374 void assign(const char* other)
376 if(!string_equal(m_string.c_str(), other))
386 m_entityKeyValueChanged();
387 KeyObservers::reverse_iterator i = m_observers.rbegin();
388 while(i != m_observers.rend())
394 void importState(const CopiedString& string)
400 typedef MemberCaller1<KeyValue, const CopiedString&, &KeyValue::importState> UndoImportCaller;
403 /// \brief An unsorted list of key/value pairs.
405 /// - Notifies observers when a pair is inserted or removed.
406 /// - Provides undo support through the global undo system.
407 /// - New keys are appended to the end of the list.
408 class EntityKeyValues : public Entity
411 typedef KeyValue Value;
413 static StringPool& getPool()
415 return Static<StringPool, KeyContext>::instance();
418 static EntityCreator::KeyValueChangedFunc m_entityKeyValueChanged;
419 static Counter* m_counter;
421 EntityClass* m_eclass;
424 typedef Static<StringPool, KeyContext> KeyPool;
425 typedef PooledString<KeyPool> Key;
426 typedef SmartPointer<KeyValue> KeyValuePtr;
427 typedef UnsortedMap<Key, KeyValuePtr> KeyValues;
428 KeyValues m_keyValues;
430 typedef UnsortedSet<Observer*> Observers;
431 Observers m_observers;
433 ObservedUndoableObject<KeyValues> m_undo;
436 bool m_observerMutex;
438 void notifyInsert(const char* key, Value& value)
440 m_observerMutex = true;
441 for(Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i)
443 (*i)->insert(key, value);
445 m_observerMutex = false;
447 void notifyErase(const char* key, Value& value)
449 m_observerMutex = true;
450 for(Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i)
452 (*i)->erase(key, value);
454 m_observerMutex = false;
456 void forEachKeyValue_notifyInsert()
458 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
460 notifyInsert((*i).first.c_str(), *(*i).second);
463 void forEachKeyValue_notifyErase()
465 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
467 notifyErase((*i).first.c_str(), *(*i).second);
471 void insert(const char* key, const KeyValuePtr& keyValue)
473 KeyValues::iterator i = m_keyValues.insert(KeyValues::value_type(key, keyValue));
474 notifyInsert(key, *(*i).second);
478 (*i).second->instanceAttach(m_undo.map());
482 void insert(const char* key, const char* value)
484 KeyValues::iterator i = m_keyValues.find(key);
485 if(i != m_keyValues.end())
487 (*i).second->assign(value);
492 insert(key, KeyValuePtr(new KeyValue(value, EntityClass_valueForKey(*m_eclass, key))));
496 void erase(KeyValues::iterator i)
500 (*i).second->instanceDetach(m_undo.map());
504 KeyValuePtr value((*i).second);
505 m_keyValues.erase(i);
506 notifyErase(key.c_str(), *value);
509 void erase(const char* key)
511 KeyValues::iterator i = m_keyValues.find(key);
512 if(i != m_keyValues.end())
522 EntityKeyValues(EntityClass* eclass) :
524 m_undo(m_keyValues, UndoImportCaller(*this)),
526 m_observerMutex(false),
527 m_isContainer(!eclass->fixedsize)
530 EntityKeyValues(const EntityKeyValues& other) :
532 m_eclass(&other.getEntityClass()),
533 m_undo(m_keyValues, UndoImportCaller(*this)),
535 m_observerMutex(false),
536 m_isContainer(other.m_isContainer)
538 for(KeyValues::const_iterator i = other.m_keyValues.begin(); i != other.m_keyValues.end(); ++i)
540 insert((*i).first.c_str(), (*i).second->c_str());
545 for(Observers::iterator i = m_observers.begin(); i != m_observers.end();)
547 // post-increment to allow current element to be removed safely
550 ASSERT_MESSAGE(m_observers.empty(), "EntityKeyValues::~EntityKeyValues: observers still attached");
553 static void setKeyValueChangedFunc(EntityCreator::KeyValueChangedFunc func)
555 m_entityKeyValueChanged = func;
556 KeyValue::setKeyValueChangedFunc(func);
558 static void setCounter(Counter* counter)
563 void importState(const KeyValues& keyValues)
565 for(KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end();)
570 for(KeyValues::const_iterator i = keyValues.begin(); i != keyValues.end(); ++i)
572 insert((*i).first.c_str(), (*i).second);
575 m_entityKeyValueChanged();
577 typedef MemberCaller1<EntityKeyValues, const KeyValues&, &EntityKeyValues::importState> UndoImportCaller;
579 void attach(Observer& observer)
581 ASSERT_MESSAGE(!m_observerMutex, "observer cannot be attached during iteration");
582 m_observers.insert(&observer);
583 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
585 observer.insert((*i).first.c_str(), *(*i).second);
588 void detach(Observer& observer)
590 ASSERT_MESSAGE(!m_observerMutex, "observer cannot be detached during iteration");
591 m_observers.erase(&observer);
592 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
594 observer.erase((*i).first.c_str(), *(*i).second);
598 void forEachKeyValue_instanceAttach(MapFile* map)
600 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
602 (*i).second->instanceAttach(map);
605 void forEachKeyValue_instanceDetach(MapFile* map)
607 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
609 (*i).second->instanceDetach(map);
613 void instanceAttach(MapFile* map)
617 m_counter->increment();
621 forEachKeyValue_instanceAttach(map);
622 m_undo.instanceAttach(map);
624 void instanceDetach(MapFile* map)
628 m_counter->decrement();
631 m_undo.instanceDetach(map);
632 forEachKeyValue_instanceDetach(map);
637 EntityClass& getEntityClass() const
641 void forEachKeyValue(Visitor& visitor) const
643 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
645 visitor.visit((*i).first.c_str(), (*i).second->c_str());
648 void setKeyValue(const char* key, const char* value)
651 /*|| string_equal(EntityClass_valueForKey(*m_eclass, key), value)*/) // don't delete values equal to default
659 m_entityKeyValueChanged();
661 const char* getKeyValue(const char* key) const
663 KeyValues::const_iterator i = m_keyValues.find(key);
664 if(i != m_keyValues.end())
666 return (*i).second->c_str();
669 return EntityClass_valueForKey(*m_eclass, key);
672 bool isContainer() const
674 return m_isContainer;
678 /// \brief A Resource reference with a controlled lifetime.
679 /// \brief The resource is released when the ResourceReference is destroyed.
680 class ResourceReference
683 Resource* m_resource;
685 ResourceReference(const char* name)
690 ResourceReference(const ResourceReference& other)
691 : m_name(other.m_name)
695 ResourceReference& operator=(const ResourceReference& other)
697 ResourceReference tmp(other);
708 m_resource = GlobalReferenceCache().capture(m_name.c_str());
712 GlobalReferenceCache().release(m_name.c_str());
715 const char* getName() const
717 return m_name.c_str();
719 void setName(const char* name)
721 ResourceReference tmp(name);
725 void swap(ResourceReference& other)
727 std::swap(m_resource, other.m_resource);
728 std::swap(m_name, other.m_name);
731 void attach(ModuleObserver& observer)
733 m_resource->attach(observer);
735 void detach(ModuleObserver& observer)
737 m_resource->detach(observer);
748 /// \brief Swaps the values of \p self and \p other.
749 /// Overloads std::swap.
750 inline void swap(ResourceReference& self, ResourceReference& other)