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)
49 Vector3 left(-direction[1], direction[0], 0);
51 Vector3 endpoint(vector3_added(origin, vector3_scaled(direction, 32.0)));
53 Vector3 tip1(vector3_added(vector3_added(endpoint, vector3_scaled(direction, -8.0)), vector3_scaled(up, -4.0)));
54 Vector3 tip2(vector3_added(tip1, vector3_scaled(up, 8.0)));
55 Vector3 tip3(vector3_added(vector3_added(endpoint, vector3_scaled(direction, -8.0)), vector3_scaled(left, -4.0)));
56 Vector3 tip4(vector3_added(tip3, vector3_scaled(left, 8.0)));
60 glVertex3fv(vector3_to_array(origin));
61 glVertex3fv(vector3_to_array(endpoint));
63 glVertex3fv(vector3_to_array(endpoint));
64 glVertex3fv(vector3_to_array(tip1));
66 glVertex3fv(vector3_to_array(endpoint));
67 glVertex3fv(vector3_to_array(tip2));
69 glVertex3fv(vector3_to_array(endpoint));
70 glVertex3fv(vector3_to_array(tip3));
72 glVertex3fv(vector3_to_array(endpoint));
73 glVertex3fv(vector3_to_array(tip4));
75 glVertex3fv(vector3_to_array(tip1));
76 glVertex3fv(vector3_to_array(tip3));
78 glVertex3fv(vector3_to_array(tip3));
79 glVertex3fv(vector3_to_array(tip2));
81 glVertex3fv(vector3_to_array(tip2));
82 glVertex3fv(vector3_to_array(tip4));
84 glVertex3fv(vector3_to_array(tip4));
85 glVertex3fv(vector3_to_array(tip1));
90 class SelectionIntersection;
92 inline void aabb_testselect(const AABB& aabb, SelectionTest& test, SelectionIntersection& best)
94 const IndexPointer::index_type indices[24] = {
104 aabb_corners(aabb, points);
105 test.TestQuads(VertexPointer(reinterpret_cast<VertexPointer::pointer>(points), sizeof(Vector3)), IndexPointer(indices, 24), best);
108 inline void aabb_draw_wire(const Vector3 points[8])
110 typedef std::size_t index_t;
111 index_t indices[24] = {
112 0, 1, 1, 2, 2, 3, 3, 0,
113 4, 5, 5, 6, 6, 7, 7, 4,
114 0, 4, 1, 5, 2, 6, 3, 7,
117 glVertexPointer(3, GL_FLOAT, 0, points);
118 glDrawElements(GL_LINES, sizeof(indices)/sizeof(index_t), GL_UNSIGNED_INT, indices);
121 for(std::size_t i = 0; i < sizeof(indices)/sizeof(index_t); ++i)
123 glVertex3fv(points[indices[i]]);
129 inline void aabb_draw_flatshade(const Vector3 points[8])
133 glNormal3fv(vector3_to_array(aabb_normals[0]));
134 glVertex3fv(vector3_to_array(points[2]));
135 glVertex3fv(vector3_to_array(points[1]));
136 glVertex3fv(vector3_to_array(points[5]));
137 glVertex3fv(vector3_to_array(points[6]));
139 glNormal3fv(vector3_to_array(aabb_normals[1]));
140 glVertex3fv(vector3_to_array(points[1]));
141 glVertex3fv(vector3_to_array(points[0]));
142 glVertex3fv(vector3_to_array(points[4]));
143 glVertex3fv(vector3_to_array(points[5]));
145 glNormal3fv(vector3_to_array(aabb_normals[2]));
146 glVertex3fv(vector3_to_array(points[0]));
147 glVertex3fv(vector3_to_array(points[1]));
148 glVertex3fv(vector3_to_array(points[2]));
149 glVertex3fv(vector3_to_array(points[3]));
151 glNormal3fv(vector3_to_array(aabb_normals[3]));
152 glVertex3fv(vector3_to_array(points[0]));
153 glVertex3fv(vector3_to_array(points[3]));
154 glVertex3fv(vector3_to_array(points[7]));
155 glVertex3fv(vector3_to_array(points[4]));
157 glNormal3fv(vector3_to_array(aabb_normals[4]));
158 glVertex3fv(vector3_to_array(points[3]));
159 glVertex3fv(vector3_to_array(points[2]));
160 glVertex3fv(vector3_to_array(points[6]));
161 glVertex3fv(vector3_to_array(points[7]));
163 glNormal3fv(vector3_to_array(aabb_normals[5]));
164 glVertex3fv(vector3_to_array(points[7]));
165 glVertex3fv(vector3_to_array(points[6]));
166 glVertex3fv(vector3_to_array(points[5]));
167 glVertex3fv(vector3_to_array(points[4]));
172 inline void aabb_draw_wire(const AABB& aabb)
175 aabb_corners(aabb, points);
176 aabb_draw_wire(points);
179 inline void aabb_draw_flatshade(const AABB& aabb)
182 aabb_corners(aabb, points);
183 aabb_draw_flatshade(points);
186 inline void aabb_draw_textured(const AABB& aabb)
189 aabb_corners(aabb, points);
193 glNormal3fv(vector3_to_array(aabb_normals[0]));
194 glTexCoord2fv(aabb_texcoord_topleft);
195 glVertex3fv(vector3_to_array(points[2]));
196 glTexCoord2fv(aabb_texcoord_topright);
197 glVertex3fv(vector3_to_array(points[1]));
198 glTexCoord2fv(aabb_texcoord_botright);
199 glVertex3fv(vector3_to_array(points[5]));
200 glTexCoord2fv(aabb_texcoord_botleft);
201 glVertex3fv(vector3_to_array(points[6]));
203 glNormal3fv(vector3_to_array(aabb_normals[1]));
204 glTexCoord2fv(aabb_texcoord_topleft);
205 glVertex3fv(vector3_to_array(points[1]));
206 glTexCoord2fv(aabb_texcoord_topright);
207 glVertex3fv(vector3_to_array(points[0]));
208 glTexCoord2fv(aabb_texcoord_botright);
209 glVertex3fv(vector3_to_array(points[4]));
210 glTexCoord2fv(aabb_texcoord_botleft);
211 glVertex3fv(vector3_to_array(points[5]));
213 glNormal3fv(vector3_to_array(aabb_normals[2]));
214 glTexCoord2fv(aabb_texcoord_topleft);
215 glVertex3fv(vector3_to_array(points[0]));
216 glTexCoord2fv(aabb_texcoord_topright);
217 glVertex3fv(vector3_to_array(points[1]));
218 glTexCoord2fv(aabb_texcoord_botright);
219 glVertex3fv(vector3_to_array(points[2]));
220 glTexCoord2fv(aabb_texcoord_botleft);
221 glVertex3fv(vector3_to_array(points[3]));
223 glNormal3fv(vector3_to_array(aabb_normals[3]));
224 glTexCoord2fv(aabb_texcoord_topleft);
225 glVertex3fv(vector3_to_array(points[0]));
226 glTexCoord2fv(aabb_texcoord_topright);
227 glVertex3fv(vector3_to_array(points[3]));
228 glTexCoord2fv(aabb_texcoord_botright);
229 glVertex3fv(vector3_to_array(points[7]));
230 glTexCoord2fv(aabb_texcoord_botleft);
231 glVertex3fv(vector3_to_array(points[4]));
233 glNormal3fv(vector3_to_array(aabb_normals[4]));
234 glTexCoord2fv(aabb_texcoord_topleft);
235 glVertex3fv(vector3_to_array(points[3]));
236 glTexCoord2fv(aabb_texcoord_topright);
237 glVertex3fv(vector3_to_array(points[2]));
238 glTexCoord2fv(aabb_texcoord_botright);
239 glVertex3fv(vector3_to_array(points[6]));
240 glTexCoord2fv(aabb_texcoord_botleft);
241 glVertex3fv(vector3_to_array(points[7]));
243 glNormal3fv(vector3_to_array(aabb_normals[5]));
244 glTexCoord2fv(aabb_texcoord_topleft);
245 glVertex3fv(vector3_to_array(points[7]));
246 glTexCoord2fv(aabb_texcoord_topright);
247 glVertex3fv(vector3_to_array(points[6]));
248 glTexCoord2fv(aabb_texcoord_botright);
249 glVertex3fv(vector3_to_array(points[5]));
250 glTexCoord2fv(aabb_texcoord_botleft);
251 glVertex3fv(vector3_to_array(points[4]));
256 inline void aabb_draw_solid(const AABB& aabb, RenderStateFlags state)
258 if(state & RENDER_TEXTURE)
260 aabb_draw_textured(aabb);
264 aabb_draw_flatshade(aabb);
268 inline void aabb_draw(const AABB& aabb, RenderStateFlags state)
270 if(state & RENDER_FILL)
272 aabb_draw_solid(aabb, state);
276 aabb_draw_wire(aabb);
280 class RenderableSolidAABB : public OpenGLRenderable
284 RenderableSolidAABB(const AABB& aabb) : m_aabb(aabb)
287 void render(RenderStateFlags state) const
289 aabb_draw_solid(m_aabb, state);
293 class RenderableWireframeAABB : public OpenGLRenderable
297 RenderableWireframeAABB(const AABB& aabb) : m_aabb(aabb)
300 void render(RenderStateFlags state) const
302 aabb_draw_wire(m_aabb);
307 typedef Callback1<const char*> KeyObserver;
309 /// \brief A key/value pair of strings.
311 /// - Notifies observers when value changes - value changes to "" on destruction.
312 /// - Provides undo support through the global undo system.
315 typedef UnsortedSet<KeyObserver> KeyObservers;
317 std::size_t m_refcount;
318 KeyObservers m_observers;
319 CopiedString m_string;
321 ObservedUndoableObject<CopiedString> m_undo;
322 static EntityCreator::KeyValueChangedFunc m_entityKeyValueChanged;
325 KeyValue(const char* string, const char* empty)
326 : m_refcount(0), m_string(string), m_empty(empty), m_undo(m_string, UndoImportCaller(*this))
332 ASSERT_MESSAGE(m_observers.empty(), "KeyValue::~KeyValue: observers still attached");
335 static void setKeyValueChangedFunc(EntityCreator::KeyValueChangedFunc func)
337 m_entityKeyValueChanged = func;
346 if(--m_refcount == 0)
352 void instanceAttach(MapFile* map)
354 m_undo.instanceAttach(map);
356 void instanceDetach(MapFile* map)
358 m_undo.instanceDetach(map);
361 void attach(const KeyObserver& observer)
363 (*m_observers.insert(observer))(c_str());
365 void detach(const KeyObserver& observer)
368 m_observers.erase(observer);
370 const char* c_str() const
372 if(string_empty(m_string.c_str()))
376 return m_string.c_str();
378 void assign(const char* other)
380 if(!string_equal(m_string.c_str(), other))
390 m_entityKeyValueChanged();
391 KeyObservers::reverse_iterator i = m_observers.rbegin();
392 while(i != m_observers.rend())
398 void importState(const CopiedString& string)
404 typedef MemberCaller1<KeyValue, const CopiedString&, &KeyValue::importState> UndoImportCaller;
407 /// \brief An unsorted list of key/value pairs.
409 /// - Notifies observers when a pair is inserted or removed.
410 /// - Provides undo support through the global undo system.
411 /// - New keys are appended to the end of the list.
412 class EntityKeyValues : public Entity
415 typedef KeyValue Value;
420 virtual void insert(const char* key, Value& value) = 0;
421 virtual void erase(const char* key, Value& value) = 0;
424 static StringPool& getPool()
426 return Static<StringPool, KeyContext>::instance();
429 static EntityCreator::KeyValueChangedFunc m_entityKeyValueChanged;
430 static Counter* m_counter;
432 EntityClass* m_eclass;
435 typedef Static<StringPool, KeyContext> KeyPool;
436 typedef PooledString<KeyPool> Key;
437 typedef SmartPointer<KeyValue> KeyValuePtr;
438 typedef UnsortedMap<Key, KeyValuePtr> KeyValues;
439 KeyValues m_keyValues;
441 typedef UnsortedSet<Observer*> Observers;
442 Observers m_observers;
444 ObservedUndoableObject<KeyValues> m_undo;
447 bool m_observerMutex;
449 void notifyInsert(const char* key, Value& value)
451 m_observerMutex = true;
452 for(Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i)
454 (*i)->insert(key, value);
456 m_observerMutex = false;
458 void notifyErase(const char* key, Value& value)
460 m_observerMutex = true;
461 for(Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i)
463 (*i)->erase(key, value);
465 m_observerMutex = false;
467 void forEachKeyValue_notifyInsert()
469 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
471 notifyInsert((*i).first.c_str(), *(*i).second);
474 void forEachKeyValue_notifyErase()
476 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
478 notifyErase((*i).first.c_str(), *(*i).second);
482 void insert(const char* key, const KeyValuePtr& keyValue)
484 KeyValues::iterator i = m_keyValues.insert(KeyValues::value_type(key, keyValue));
485 notifyInsert(key, *(*i).second);
489 (*i).second->instanceAttach(m_undo.map());
493 void insert(const char* key, const char* value)
495 KeyValues::iterator i = m_keyValues.find(key);
496 if(i != m_keyValues.end())
498 (*i).second->assign(value);
503 insert(key, KeyValuePtr(new KeyValue(value, EntityClass_valueForKey(*m_eclass, key))));
507 void erase(KeyValues::iterator i)
511 (*i).second->instanceDetach(m_undo.map());
515 KeyValuePtr value((*i).second);
516 m_keyValues.erase(i);
517 notifyErase(key.c_str(), *value);
520 void erase(const char* key)
522 KeyValues::iterator i = m_keyValues.find(key);
523 if(i != m_keyValues.end())
533 EntityKeyValues(EntityClass* eclass) :
535 m_undo(m_keyValues, UndoImportCaller(*this)),
537 m_observerMutex(false),
538 m_isContainer(!eclass->fixedsize)
541 EntityKeyValues(const EntityKeyValues& other) :
543 m_eclass(&other.getEntityClass()),
544 m_undo(m_keyValues, UndoImportCaller(*this)),
546 m_observerMutex(false),
547 m_isContainer(other.m_isContainer)
549 for(KeyValues::const_iterator i = other.m_keyValues.begin(); i != other.m_keyValues.end(); ++i)
551 insert((*i).first.c_str(), (*i).second->c_str());
556 ASSERT_MESSAGE(m_observers.empty(), "EntityKeyValues::~EntityKeyValues: observers still attached");
559 static void setKeyValueChangedFunc(EntityCreator::KeyValueChangedFunc func)
561 m_entityKeyValueChanged = func;
562 KeyValue::setKeyValueChangedFunc(func);
564 static void setCounter(Counter* counter)
569 void importState(const KeyValues& keyValues)
571 for(KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end();)
576 for(KeyValues::const_iterator i = keyValues.begin(); i != keyValues.end(); ++i)
578 insert((*i).first.c_str(), (*i).second);
581 m_entityKeyValueChanged();
583 typedef MemberCaller1<EntityKeyValues, const KeyValues&, &EntityKeyValues::importState> UndoImportCaller;
585 void attach(Observer& observer)
587 ASSERT_MESSAGE(!m_observerMutex, "observer cannot be attached during iteration");
588 m_observers.insert(&observer);
589 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
591 observer.insert((*i).first.c_str(), *(*i).second);
594 void detach(Observer& observer)
596 ASSERT_MESSAGE(!m_observerMutex, "observer cannot be detached during iteration");
597 m_observers.erase(&observer);
598 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
600 observer.erase((*i).first.c_str(), *(*i).second);
604 void forEachKeyValue_instanceAttach(MapFile* map)
606 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
608 (*i).second->instanceAttach(map);
611 void forEachKeyValue_instanceDetach(MapFile* map)
613 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
615 (*i).second->instanceDetach(map);
619 void instanceAttach(MapFile* map)
623 m_counter->increment();
627 forEachKeyValue_instanceAttach(map);
628 m_undo.instanceAttach(map);
630 void instanceDetach(MapFile* map)
634 m_counter->decrement();
637 m_undo.instanceDetach(map);
638 forEachKeyValue_instanceDetach(map);
643 EntityClass& getEntityClass() const
647 void forEachKeyValue(Visitor& visitor) const
649 for(KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
651 visitor.visit((*i).first.c_str(), (*i).second->c_str());
654 void setKeyValue(const char* key, const char* value)
657 /*|| string_equal(EntityClass_valueForKey(*m_eclass, key), value)*/) // don't delete values equal to default
665 m_entityKeyValueChanged();
667 const char* getKeyValue(const char* key) const
669 KeyValues::const_iterator i = m_keyValues.find(key);
670 if(i != m_keyValues.end())
672 return (*i).second->c_str();
675 return EntityClass_valueForKey(*m_eclass, key);
678 bool isContainer() const
680 return m_isContainer;
684 /// \brief A Resource reference with a controlled lifetime.
685 /// \brief The resource is released when the ResourceReference is destroyed.
686 class ResourceReference
689 Resource* m_resource;
691 ResourceReference(const char* name)
696 ResourceReference(const ResourceReference& other)
697 : m_name(other.m_name)
701 ResourceReference& operator=(const ResourceReference& other)
703 ResourceReference tmp(other);
714 m_resource = GlobalReferenceCache().capture(m_name.c_str());
718 GlobalReferenceCache().release(m_name.c_str());
721 const char* getName() const
723 return m_name.c_str();
725 void setName(const char* name)
727 ResourceReference tmp(name);
731 void swap(ResourceReference& other)
733 std::swap(m_resource, other.m_resource);
734 std::swap(m_name, other.m_name);
737 void attach(ModuleObserver& observer)
739 m_resource->attach(observer);
741 void detach(ModuleObserver& observer)
743 m_resource->detach(observer);
754 /// \brief Swaps the values of \p self and \p other.
755 /// Overloads std::swap.
756 inline void swap(ResourceReference& self, ResourceReference& other)