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:
SelectionIntersection()36 SelectionIntersection() : m_depth( 1 ), m_distance( 2 ){
37 }
SelectionIntersection(float depth,float distance)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 }
equalEpsilon(const SelectionIntersection & other,float distanceEpsilon,float depthEpsilon)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 }
depth()53 float depth() const {
54 	return m_depth;
55 }
valid()56 bool valid() const {
57 	return depth() < 1;
58 }
59 };
60 
61 // returns true if self is closer than other
SelectionIntersection_closer(const SelectionIntersection & self,const SelectionIntersection & 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
assign_if_closer(SelectionIntersection & best,const SelectionIntersection & other)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:
iterator()87 iterator() {}
iterator(byte_pointer vertices,std::size_t stride)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 
VertexPointer(pointer vertices,std::size_t stride)122 VertexPointer( pointer vertices, std::size_t stride )
123 	: m_vertices( reinterpret_cast<byte_pointer>( vertices ) ), m_stride( stride ) {}
124 
begin()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:
iterator(pointer iter)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:
increment()172 void increment(){
173 	++m_iter;
174 }
175 pointer m_iter;
176 };
177 
IndexPointer(pointer indices,std::size_t count)178 IndexPointer( pointer indices, std::size_t count )
179 	: m_indices( indices ), m_finish( indices + count ) {}
180 
begin()181 iterator begin() const {
182 	return m_indices;
183 }
end()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 
Selector_add(Selector & selector,Selectable & selectable)225 inline void Selector_add( Selector& selector, Selectable& selectable ){
226 	selector.pushSelectable( selectable );
227 	selector.addIntersection( SelectionIntersection( 0, 0 ) );
228 	selector.popSelectable();
229 }
230 
Selector_add(Selector & selector,Selectable & selectable,const SelectionIntersection & intersection)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 
Instance_getSelectionTestable(scene::Instance & instance)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
273