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[32] = {
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
114 glVertexPointer(3, GL_FLOAT, 0, points);
115 glDrawElements(GL_LINES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_INT, indices);
118 for(std::size_t i = 0; i < sizeof(indices)/sizeof(indices[0]); ++i)
120 glVertex3fv(points[indices[i]]);
126 inline void aabb_draw_flatshade(const Vector3 points[8])
130 glNormal3fv(vector3_to_array(aabb_normals[0]));
131 glVertex3fv(vector3_to_array(points[2]));
132 glVertex3fv(vector3_to_array(points[1]));
133 glVertex3fv(vector3_to_array(points[5]));
134 glVertex3fv(vector3_to_array(points[6]));
136 glNormal3fv(vector3_to_array(aabb_normals[1]));
137 glVertex3fv(vector3_to_array(points[1]));
138 glVertex3fv(vector3_to_array(points[0]));
139 glVertex3fv(vector3_to_array(points[4]));
140 glVertex3fv(vector3_to_array(points[5]));
142 glNormal3fv(vector3_to_array(aabb_normals[2]));
143 glVertex3fv(vector3_to_array(points[0]));
144 glVertex3fv(vector3_to_array(points[1]));
145 glVertex3fv(vector3_to_array(points[2]));
146 glVertex3fv(vector3_to_array(points[3]));
148 glNormal3fv(vector3_to_array(aabb_normals[3]));
149 glVertex3fv(vector3_to_array(points[0]));
150 glVertex3fv(vector3_to_array(points[3]));
151 glVertex3fv(vector3_to_array(points[7]));
152 glVertex3fv(vector3_to_array(points[4]));
154 glNormal3fv(vector3_to_array(aabb_normals[4]));
155 glVertex3fv(vector3_to_array(points[3]));
156 glVertex3fv(vector3_to_array(points[2]));
157 glVertex3fv(vector3_to_array(points[6]));
158 glVertex3fv(vector3_to_array(points[7]));
160 glNormal3fv(vector3_to_array(aabb_normals[5]));
161 glVertex3fv(vector3_to_array(points[7]));
162 glVertex3fv(vector3_to_array(points[6]));
163 glVertex3fv(vector3_to_array(points[5]));
164 glVertex3fv(vector3_to_array(points[4]));
169 inline void aabb_draw_wire(const AABB& aabb)
172 aabb_corners(aabb, points);
173 aabb_draw_wire(points);
176 inline void aabb_draw_flatshade(const AABB& aabb)
179 aabb_corners(aabb, points);
180 aabb_draw_flatshade(points);
183 inline void aabb_draw_textured(const AABB& aabb)
186 aabb_corners(aabb, points);
190 glNormal3fv(vector3_to_array(aabb_normals[0]));
191 glTexCoord2fv(aabb_texcoord_topleft);
192 glVertex3fv(vector3_to_array(points[2]));
193 glTexCoord2fv(aabb_texcoord_topright);
194 glVertex3fv(vector3_to_array(points[1]));
195 glTexCoord2fv(aabb_texcoord_botright);
196 glVertex3fv(vector3_to_array(points[5]));
197 glTexCoord2fv(aabb_texcoord_botleft);
198 glVertex3fv(vector3_to_array(points[6]));
200 glNormal3fv(vector3_to_array(aabb_normals[1]));
201 glTexCoord2fv(aabb_texcoord_topleft);
202 glVertex3fv(vector3_to_array(points[1]));
203 glTexCoord2fv(aabb_texcoord_topright);
204 glVertex3fv(vector3_to_array(points[0]));
205 glTexCoord2fv(aabb_texcoord_botright);
206 glVertex3fv(vector3_to_array(points[4]));
207 glTexCoord2fv(aabb_texcoord_botleft);
208 glVertex3fv(vector3_to_array(points[5]));
210 glNormal3fv(vector3_to_array(aabb_normals[2]));
211 glTexCoord2fv(aabb_texcoord_topleft);
212 glVertex3fv(vector3_to_array(points[0]));
213 glTexCoord2fv(aabb_texcoord_topright);
214 glVertex3fv(vector3_to_array(points[1]));
215 glTexCoord2fv(aabb_texcoord_botright);
216 glVertex3fv(vector3_to_array(points[2]));
217 glTexCoord2fv(aabb_texcoord_botleft);
218 glVertex3fv(vector3_to_array(points[3]));
220 glNormal3fv(vector3_to_array(aabb_normals[3]));
221 glTexCoord2fv(aabb_texcoord_topleft);
222 glVertex3fv(vector3_to_array(points[0]));
223 glTexCoord2fv(aabb_texcoord_topright);
224 glVertex3fv(vector3_to_array(points[3]));
225 glTexCoord2fv(aabb_texcoord_botright);
226 glVertex3fv(vector3_to_array(points[7]));
227 glTexCoord2fv(aabb_texcoord_botleft);
228 glVertex3fv(vector3_to_array(points[4]));
230 glNormal3fv(vector3_to_array(aabb_normals[4]));
231 glTexCoord2fv(aabb_texcoord_topleft);
232 glVertex3fv(vector3_to_array(points[3]));
233 glTexCoord2fv(aabb_texcoord_topright);
234 glVertex3fv(vector3_to_array(points[2]));
235 glTexCoord2fv(aabb_texcoord_botright);
236 glVertex3fv(vector3_to_array(points[6]));
237 glTexCoord2fv(aabb_texcoord_botleft);
238 glVertex3fv(vector3_to_array(points[7]));
240 glNormal3fv(vector3_to_array(aabb_normals[5]));
241 glTexCoord2fv(aabb_texcoord_topleft);
242 glVertex3fv(vector3_to_array(points[7]));
243 glTexCoord2fv(aabb_texcoord_topright);
244 glVertex3fv(vector3_to_array(points[6]));
245 glTexCoord2fv(aabb_texcoord_botright);
246 glVertex3fv(vector3_to_array(points[5]));
247 glTexCoord2fv(aabb_texcoord_botleft);
248 glVertex3fv(vector3_to_array(points[4]));
253 inline void aabb_draw_solid(const AABB& aabb, RenderStateFlags state)
255 if(state & RENDER_TEXTURE)
257 aabb_draw_textured(aabb);
261 aabb_draw_flatshade(aabb);
265 inline void aabb_draw(const AABB& aabb, RenderStateFlags state)
267 if(state & RENDER_FILL)
269 aabb_draw_solid(aabb, state);
273 aabb_draw_wire(aabb);
277 class RenderableSolidAABB : public OpenGLRenderable
281 RenderableSolidAABB(const AABB& aabb) : m_aabb(aabb)
284 void render(RenderStateFlags state) const
286 aabb_draw_solid(m_aabb, state);
290 class RenderableWireframeAABB : public OpenGLRenderable
294 RenderableWireframeAABB(const AABB& aabb) : m_aabb(aabb)
297 void render(RenderStateFlags state) const
299 aabb_draw_wire(m_aabb);
304 /// \brief A key/value pair of strings.
306 /// - Notifies observers when value changes - value changes to "" on destruction.
307 /// - Provides undo support through the global undo system.
308 class KeyValue : public EntityKeyValue
310 typedef UnsortedSet<KeyObserver> KeyObservers;
312 std::size_t m_refcount;
313 KeyObservers m_observers;
314 CopiedString m_string;
316 ObservedUndoableObject<CopiedString> m_undo;
317 static EntityCreator::KeyValueChangedFunc m_entityKeyValueChanged;
320 KeyValue(const char* string, const char* empty)
321 : m_refcount(0), m_string(string), m_empty(empty), m_undo(m_string, UndoImportCaller(*this))
327 ASSERT_MESSAGE(m_observers.empty(), "KeyValue::~KeyValue: observers still attached");
330 static void setKeyValueChangedFunc(EntityCreator::KeyValueChangedFunc func)
332 m_entityKeyValueChanged = func;
341 if(--m_refcount == 0)
347 void instanceAttach(MapFile* map)
349 m_undo.instanceAttach(map);
351 void instanceDetach(MapFile* map)
353 m_undo.instanceDetach(map);
356 void attach(const KeyObserver& observer)
358 (*m_observers.insert(observer))(c_str());
360 void detach(const KeyObserver& observer)
363 m_observers.erase(observer);
365 const char* c_str() const
367 if(string_empty(m_string.c_str()))
371 return m_string.c_str();
373 void assign(const char* other)
375 if(!string_equal(m_string.c_str(), other))
385 m_entityKeyValueChanged();
386 KeyObservers::reverse_iterator i = m_observers.rbegin();
387 while(i != m_observers.rend())
393 void importState(const CopiedString& string)
399 typedef MemberCaller1<KeyValue, const CopiedString&, &KeyValue::importState> UndoImportCaller;
402 /// \brief An unsorted list of key/value pairs.
404 /// - Notifies observers when a pair is inserted or removed.
405 /// - Provides undo support through the global undo system.
406 /// - New keys are appended to the end of the list.
407 class EntityKeyValues : public Entity
410 typedef KeyValue Value;
412 static StringPool& getPool()
414 return Static<StringPool, KeyContext>::instance();
417 static EntityCreator::KeyValueChangedFunc m_entityKeyValueChanged;
418 static Counter* m_counter;
420 EntityClass* m_eclass;
423 typedef Static<StringPool, KeyContext> KeyPool;
424 typedef PooledString<KeyPool> Key;
425 typedef SmartPointer<KeyValue> KeyValuePtr;
426 typedef UnsortedMap<Key, KeyValuePtr> KeyValues;
427 KeyValues m_keyValues;
429 typedef UnsortedSet<Observer*> Observers;
430 Observers m_observers;
432 ObservedUndoableObject<KeyValues> m_undo;
435 bool m_observerMutex;
437 void notifyInsert(const char* key, Value& value)
439 m_observerMutex = true;
440 for(Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i)
442 (*i)->insert(key, value);
444 m_observerMutex = false;
446 void notifyErase(const char* key, Value& value)
448 m_observerMutex = true;
449 for(Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i)
451 (*i)->erase(key, value);
453 m_observerMutex = false;
455 void forEachKeyValue_notifyInsert()
457 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
459 notifyInsert((*i).first.c_str(), *(*i).second);
462 void forEachKeyValue_notifyErase()
464 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
466 notifyErase((*i).first.c_str(), *(*i).second);
470 void insert(const char* key, const KeyValuePtr& keyValue)
472 KeyValues::iterator i = m_keyValues.insert(KeyValues::value_type(key, keyValue));
473 notifyInsert(key, *(*i).second);
477 (*i).second->instanceAttach(m_undo.map());
481 void insert(const char* key, const char* value)
483 KeyValues::iterator i = m_keyValues.find(key);
484 if(i != m_keyValues.end())
486 (*i).second->assign(value);
491 insert(key, KeyValuePtr(new KeyValue(value, EntityClass_valueForKey(*m_eclass, key))));
495 void erase(KeyValues::iterator i)
499 (*i).second->instanceDetach(m_undo.map());
503 KeyValuePtr value((*i).second);
504 m_keyValues.erase(i);
505 notifyErase(key.c_str(), *value);
508 void erase(const char* key)
510 KeyValues::iterator i = m_keyValues.find(key);
511 if(i != m_keyValues.end())
521 EntityKeyValues(EntityClass* eclass) :
523 m_undo(m_keyValues, UndoImportCaller(*this)),
525 m_observerMutex(false),
526 m_isContainer(!eclass->fixedsize)
529 EntityKeyValues(const EntityKeyValues& other) :
531 m_eclass(&other.getEntityClass()),
532 m_undo(m_keyValues, UndoImportCaller(*this)),
534 m_observerMutex(false),
535 m_isContainer(other.m_isContainer)
537 for(KeyValues::const_iterator i = other.m_keyValues.begin(); i != other.m_keyValues.end(); ++i)
539 insert((*i).first.c_str(), (*i).second->c_str());
544 for(Observers::iterator i = m_observers.begin(); i != m_observers.end();)
546 // post-increment to allow current element to be removed safely
549 ASSERT_MESSAGE(m_observers.empty(), "EntityKeyValues::~EntityKeyValues: observers still attached");
552 static void setKeyValueChangedFunc(EntityCreator::KeyValueChangedFunc func)
554 m_entityKeyValueChanged = func;
555 KeyValue::setKeyValueChangedFunc(func);
557 static void setCounter(Counter* counter)
562 void importState(const KeyValues& keyValues)
564 for(KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end();)
569 for(KeyValues::const_iterator i = keyValues.begin(); i != keyValues.end(); ++i)
571 insert((*i).first.c_str(), (*i).second);
574 m_entityKeyValueChanged();
576 typedef MemberCaller1<EntityKeyValues, const KeyValues&, &EntityKeyValues::importState> UndoImportCaller;
578 void attach(Observer& observer)
580 ASSERT_MESSAGE(!m_observerMutex, "observer cannot be attached during iteration");
581 m_observers.insert(&observer);
582 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
584 observer.insert((*i).first.c_str(), *(*i).second);
587 void detach(Observer& observer)
589 ASSERT_MESSAGE(!m_observerMutex, "observer cannot be detached during iteration");
590 m_observers.erase(&observer);
591 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
593 observer.erase((*i).first.c_str(), *(*i).second);
597 void forEachKeyValue_instanceAttach(MapFile* map)
599 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
601 (*i).second->instanceAttach(map);
604 void forEachKeyValue_instanceDetach(MapFile* map)
606 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
608 (*i).second->instanceDetach(map);
612 void instanceAttach(MapFile* map)
616 m_counter->increment();
620 forEachKeyValue_instanceAttach(map);
621 m_undo.instanceAttach(map);
623 void instanceDetach(MapFile* map)
627 m_counter->decrement();
630 m_undo.instanceDetach(map);
631 forEachKeyValue_instanceDetach(map);
636 EntityClass& getEntityClass() const
640 void forEachKeyValue(Visitor& visitor) const
642 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
644 visitor.visit((*i).first.c_str(), (*i).second->c_str());
647 void setKeyValue(const char* key, const char* value)
650 /*|| string_equal(EntityClass_valueForKey(*m_eclass, key), value)*/) // don't delete values equal to default
658 m_entityKeyValueChanged();
660 const char* getKeyValue(const char* key) const
662 KeyValues::const_iterator i = m_keyValues.find(key);
663 if(i != m_keyValues.end())
665 return (*i).second->c_str();
668 return EntityClass_valueForKey(*m_eclass, key);
671 bool isContainer() const
673 return m_isContainer;
677 /// \brief A Resource reference with a controlled lifetime.
678 /// \brief The resource is released when the ResourceReference is destroyed.
679 class ResourceReference
682 Resource* m_resource;
684 ResourceReference(const char* name)
689 ResourceReference(const ResourceReference& other)
690 : m_name(other.m_name)
694 ResourceReference& operator=(const ResourceReference& other)
696 ResourceReference tmp(other);
707 m_resource = GlobalReferenceCache().capture(m_name.c_str());
711 GlobalReferenceCache().release(m_name.c_str());
714 const char* getName() const
716 return m_name.c_str();
718 void setName(const char* name)
720 ResourceReference tmp(name);
724 void swap(ResourceReference& other)
726 std::swap(m_resource, other.m_resource);
727 std::swap(m_name, other.m_name);
730 void attach(ModuleObserver& observer)
732 m_resource->attach(observer);
734 void detach(ModuleObserver& observer)
736 m_resource->detach(observer);
747 /// \brief Swaps the values of \p self and \p other.
748 /// Overloads std::swap.
749 inline void swap(ResourceReference& self, ResourceReference& other)