refactored plugin api; refactored callback library; added signals library
[xonotic/netradiant.git] / include / selectable.h
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 #if !defined(INCLUDED_SELECTABLE_H)
23 #define INCLUDED_SELECTABLE_H
24
25 #include <cstddef>
26
27 #include "math/vector.h"
28 #include "scenelib.h"
29 #include "generic/callbackfwd.h"
30
31 class SelectionIntersection
32 {
33   float m_depth;
34   float m_distance;
35 public:
36   SelectionIntersection() : m_depth(1), m_distance(2)
37   {
38   }
39   SelectionIntersection(float depth, float distance) : m_depth(depth), m_distance(distance)
40   {
41   }
42   bool operator<(const SelectionIntersection& other) const
43   {
44     if(m_distance != other.m_distance)
45     {
46       return m_distance < other.m_distance;
47     }
48     if(m_depth != other.m_depth)
49     {
50       return m_depth < other.m_depth;
51     }
52     return false;
53   }
54   bool equalEpsilon(const SelectionIntersection& other, float distanceEpsilon, float depthEpsilon) const
55   {
56     return float_equal_epsilon(m_distance, other.m_distance, distanceEpsilon)
57       && float_equal_epsilon(m_depth, other.m_depth, depthEpsilon);
58   }
59   float depth() const
60   {
61     return m_depth;
62   }
63   bool valid() const
64   {
65     return depth() < 1;
66   }
67 };
68
69 // returns true if self is closer than other
70 inline bool SelectionIntersection_closer(const SelectionIntersection& self, const SelectionIntersection& other)
71 {
72   return self < other;
73 }
74
75 // assigns other to best if other is closer than best
76 inline void assign_if_closer(SelectionIntersection& best, const SelectionIntersection& other)
77 {
78   if(SelectionIntersection_closer(other, best))
79   {
80     best = other;
81   }
82 }
83
84
85
86
87 class VertexPointer
88 {
89   typedef const unsigned char* byte_pointer;
90 public:
91   typedef float elem_type;
92   typedef const elem_type* pointer;
93   typedef const elem_type& reference;
94
95   class iterator
96   {
97   public:
98     iterator() {}
99     iterator(byte_pointer vertices, std::size_t stride)
100       : m_iter(vertices), m_stride(stride) {}
101
102     bool operator==(const iterator& other) const
103     {
104       return m_iter == other.m_iter;
105     }
106     bool operator!=(const iterator& other) const
107     {
108       return !operator==(other);
109     }
110
111     iterator operator+(std::size_t i)
112     {
113       return iterator(m_iter + i * m_stride, m_stride);
114     }
115     iterator operator+=(std::size_t i)
116     {
117       m_iter += i * m_stride;
118       return *this;
119     }
120     iterator& operator++()
121     {
122       m_iter += m_stride;
123       return *this;
124     }
125     iterator operator++(int)
126     {
127       iterator tmp = *this;
128       m_iter += m_stride;
129       return tmp;
130     }
131     reference operator*() const
132     {
133       return *reinterpret_cast<pointer>(m_iter);
134     }
135   private:
136     byte_pointer m_iter;
137     std::size_t m_stride;
138   };
139
140   VertexPointer(pointer vertices, std::size_t stride)
141     : m_vertices(reinterpret_cast<byte_pointer>(vertices)), m_stride(stride) {}
142
143   iterator begin() const
144   {
145     return iterator(m_vertices, m_stride);
146   }
147
148   reference operator[](std::size_t i) const
149   {
150     return *reinterpret_cast<pointer>(m_vertices + m_stride*i);
151   }
152
153 private:
154   byte_pointer m_vertices;
155   std::size_t m_stride;
156 };
157
158 class IndexPointer
159 {
160 public:
161   typedef unsigned int index_type;
162   typedef const index_type* pointer;
163
164   class iterator
165   {
166   public:
167     iterator(pointer iter) : m_iter(iter) {}
168
169     bool operator==(const iterator& other) const
170     {
171       return m_iter == other.m_iter;
172     }
173     bool operator!=(const iterator& other) const
174     {
175       return !operator==(other);
176     }
177
178     iterator operator+(std::size_t i)
179     {
180       return m_iter + i;
181     }
182     iterator operator+=(std::size_t i)
183     {
184       return m_iter += i;
185     }
186     iterator operator++()
187     {
188       return ++m_iter;
189     }
190     iterator operator++(int)
191     {
192       return m_iter++;
193     }
194     const index_type& operator*() const
195     {
196       return *m_iter;
197     }
198   private:
199     void increment()
200     {
201       ++m_iter;
202     }
203     pointer m_iter;
204   };
205
206   IndexPointer(pointer indices, std::size_t count)
207     : m_indices(indices), m_finish(indices + count) {}
208
209   iterator begin() const
210   {
211     return m_indices;
212   }
213   iterator end() const
214   {
215     return m_finish;
216   }
217
218 private:
219   pointer m_indices;
220   pointer m_finish;
221 };
222
223 template<typename Element> class BasicVector3;
224 typedef BasicVector3<float> Vector3;
225 class Matrix4;
226 class VolumeTest;
227
228 class SelectionTest
229 {
230 public:
231   virtual void BeginMesh(const Matrix4& localToWorld, bool twoSided = false) = 0;
232   virtual const VolumeTest& getVolume() const = 0;
233   virtual const Vector3& getNear() const = 0;
234   virtual const Vector3& getFar() const = 0;
235   virtual void TestPoint(const Vector3& point, SelectionIntersection& best) = 0;
236   virtual void TestPolygon(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) = 0;
237   virtual void TestLineLoop(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) = 0;
238   virtual void TestLineStrip(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) = 0;
239   virtual void TestLines(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) = 0;
240   virtual void TestTriangles(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) = 0; 
241   virtual void TestQuads(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) = 0; 
242   virtual void TestQuadStrip(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) = 0; 
243 };
244
245 class Selectable;
246
247 class Selector
248 {
249 public:
250   virtual void pushSelectable(Selectable& selectable) = 0;
251   virtual void popSelectable() = 0;
252   virtual void addIntersection(const SelectionIntersection& intersection) = 0;
253 };
254
255 inline void Selector_add(Selector& selector, Selectable& selectable)
256 {
257   selector.pushSelectable(selectable);
258   selector.addIntersection(SelectionIntersection(0, 0));
259   selector.popSelectable();
260 }
261
262 inline void Selector_add(Selector& selector, Selectable& selectable, const SelectionIntersection& intersection)
263 {
264   selector.pushSelectable(selectable);
265   selector.addIntersection(intersection);
266   selector.popSelectable();
267 }
268
269
270 class VolumeTest;
271 class SelectionTestable
272 {
273 public:
274   STRING_CONSTANT(Name, "SelectionTestable");
275
276   virtual void testSelect(Selector& selector, SelectionTest& test) = 0;
277 };
278
279 inline SelectionTestable* Instance_getSelectionTestable(scene::Instance& instance)
280 {
281   return InstanceTypeCast<SelectionTestable>::cast(instance);
282 }
283
284
285 class Plane3;
286 typedef Callback1<const Plane3&> PlaneCallback;
287
288 class SelectedPlanes
289 {
290 public:
291   virtual bool contains(const Plane3& plane) const = 0;
292 };
293
294 class PlaneSelectable
295 {
296 public:
297   STRING_CONSTANT(Name, "PlaneSelectable");
298
299   virtual void selectPlanes(Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback) = 0;
300   virtual void selectReversedPlanes(Selector& selector, const SelectedPlanes& selectedPlanes) = 0;
301 };
302
303
304
305 #endif