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