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