2006-02-10 22:01:20 +00:00
|
|
|
/*
|
|
|
|
Copyright (C) 2001-2006, William Joseph.
|
|
|
|
All Rights Reserved.
|
|
|
|
|
|
|
|
This file is part of GtkRadiant.
|
|
|
|
|
|
|
|
GtkRadiant is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
GtkRadiant is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with GtkRadiant; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if !defined(INCLUDED_SELECTABLE_H)
|
|
|
|
#define INCLUDED_SELECTABLE_H
|
|
|
|
|
|
|
|
#include <cstddef>
|
|
|
|
|
2006-05-09 22:07:29 +00:00
|
|
|
#include "generic/vector.h"
|
2006-02-10 22:01:20 +00:00
|
|
|
#include "scenelib.h"
|
2006-04-09 17:15:13 +00:00
|
|
|
#include "generic/callbackfwd.h"
|
2006-02-10 22:01:20 +00:00
|
|
|
|
|
|
|
class SelectionIntersection
|
|
|
|
{
|
|
|
|
float m_depth;
|
|
|
|
float m_distance;
|
|
|
|
public:
|
|
|
|
SelectionIntersection() : m_depth(1), m_distance(2)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
SelectionIntersection(float depth, float distance) : m_depth(depth), m_distance(distance)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
bool operator<(const SelectionIntersection& other) const
|
|
|
|
{
|
|
|
|
if(m_distance != other.m_distance)
|
|
|
|
{
|
|
|
|
return m_distance < other.m_distance;
|
|
|
|
}
|
|
|
|
if(m_depth != other.m_depth)
|
|
|
|
{
|
|
|
|
return m_depth < other.m_depth;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool equalEpsilon(const SelectionIntersection& other, float distanceEpsilon, float depthEpsilon) const
|
|
|
|
{
|
|
|
|
return float_equal_epsilon(m_distance, other.m_distance, distanceEpsilon)
|
|
|
|
&& float_equal_epsilon(m_depth, other.m_depth, depthEpsilon);
|
|
|
|
}
|
|
|
|
float depth() const
|
|
|
|
{
|
|
|
|
return m_depth;
|
|
|
|
}
|
|
|
|
bool valid() const
|
|
|
|
{
|
|
|
|
return depth() < 1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// returns true if self is closer than other
|
|
|
|
inline bool SelectionIntersection_closer(const SelectionIntersection& self, const SelectionIntersection& other)
|
|
|
|
{
|
|
|
|
return self < other;
|
|
|
|
}
|
|
|
|
|
|
|
|
// assigns other to best if other is closer than best
|
|
|
|
inline void assign_if_closer(SelectionIntersection& best, const SelectionIntersection& other)
|
|
|
|
{
|
|
|
|
if(SelectionIntersection_closer(other, best))
|
|
|
|
{
|
|
|
|
best = other;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VertexPointer
|
|
|
|
{
|
|
|
|
typedef const unsigned char* byte_pointer;
|
|
|
|
public:
|
|
|
|
typedef float elem_type;
|
|
|
|
typedef const elem_type* pointer;
|
|
|
|
typedef const elem_type& reference;
|
|
|
|
|
|
|
|
class iterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
iterator() {}
|
|
|
|
iterator(byte_pointer vertices, std::size_t stride)
|
|
|
|
: m_iter(vertices), m_stride(stride) {}
|
|
|
|
|
|
|
|
bool operator==(const iterator& other) const
|
|
|
|
{
|
|
|
|
return m_iter == other.m_iter;
|
|
|
|
}
|
|
|
|
bool operator!=(const iterator& other) const
|
|
|
|
{
|
|
|
|
return !operator==(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator operator+(std::size_t i)
|
|
|
|
{
|
|
|
|
return iterator(m_iter + i * m_stride, m_stride);
|
|
|
|
}
|
|
|
|
iterator operator+=(std::size_t i)
|
|
|
|
{
|
|
|
|
m_iter += i * m_stride;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
iterator& operator++()
|
|
|
|
{
|
|
|
|
m_iter += m_stride;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
iterator operator++(int)
|
|
|
|
{
|
|
|
|
iterator tmp = *this;
|
|
|
|
m_iter += m_stride;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
reference operator*() const
|
|
|
|
{
|
|
|
|
return *reinterpret_cast<pointer>(m_iter);
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
byte_pointer m_iter;
|
|
|
|
std::size_t m_stride;
|
|
|
|
};
|
|
|
|
|
|
|
|
VertexPointer(pointer vertices, std::size_t stride)
|
|
|
|
: m_vertices(reinterpret_cast<byte_pointer>(vertices)), m_stride(stride) {}
|
|
|
|
|
|
|
|
iterator begin() const
|
|
|
|
{
|
|
|
|
return iterator(m_vertices, m_stride);
|
|
|
|
}
|
|
|
|
|
|
|
|
reference operator[](std::size_t i) const
|
|
|
|
{
|
|
|
|
return *reinterpret_cast<pointer>(m_vertices + m_stride*i);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
byte_pointer m_vertices;
|
|
|
|
std::size_t m_stride;
|
|
|
|
};
|
|
|
|
|
|
|
|
class IndexPointer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef unsigned int index_type;
|
|
|
|
typedef const index_type* pointer;
|
|
|
|
|
|
|
|
class iterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
iterator(pointer iter) : m_iter(iter) {}
|
|
|
|
|
|
|
|
bool operator==(const iterator& other) const
|
|
|
|
{
|
|
|
|
return m_iter == other.m_iter;
|
|
|
|
}
|
|
|
|
bool operator!=(const iterator& other) const
|
|
|
|
{
|
|
|
|
return !operator==(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator operator+(std::size_t i)
|
|
|
|
{
|
|
|
|
return m_iter + i;
|
|
|
|
}
|
|
|
|
iterator operator+=(std::size_t i)
|
|
|
|
{
|
|
|
|
return m_iter += i;
|
|
|
|
}
|
|
|
|
iterator operator++()
|
|
|
|
{
|
|
|
|
return ++m_iter;
|
|
|
|
}
|
|
|
|
iterator operator++(int)
|
|
|
|
{
|
|
|
|
return m_iter++;
|
|
|
|
}
|
|
|
|
const index_type& operator*() const
|
|
|
|
{
|
|
|
|
return *m_iter;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
void increment()
|
|
|
|
{
|
|
|
|
++m_iter;
|
|
|
|
}
|
|
|
|
pointer m_iter;
|
|
|
|
};
|
|
|
|
|
|
|
|
IndexPointer(pointer indices, std::size_t count)
|
|
|
|
: m_indices(indices), m_finish(indices + count) {}
|
|
|
|
|
|
|
|
iterator begin() const
|
|
|
|
{
|
|
|
|
return m_indices;
|
|
|
|
}
|
|
|
|
iterator end() const
|
|
|
|
{
|
|
|
|
return m_finish;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
pointer m_indices;
|
|
|
|
pointer m_finish;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Element> class BasicVector3;
|
|
|
|
typedef BasicVector3<float> Vector3;
|
|
|
|
class Matrix4;
|
|
|
|
class VolumeTest;
|
|
|
|
|
|
|
|
class SelectionTest
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void BeginMesh(const Matrix4& localToWorld, bool twoSided = false) = 0;
|
|
|
|
virtual const VolumeTest& getVolume() const = 0;
|
|
|
|
virtual const Vector3& getNear() const = 0;
|
|
|
|
virtual const Vector3& getFar() const = 0;
|
|
|
|
virtual void TestPoint(const Vector3& point, SelectionIntersection& best) = 0;
|
|
|
|
virtual void TestPolygon(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) = 0;
|
|
|
|
virtual void TestLineLoop(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) = 0;
|
|
|
|
virtual void TestLineStrip(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) = 0;
|
|
|
|
virtual void TestLines(const VertexPointer& vertices, std::size_t count, SelectionIntersection& best) = 0;
|
|
|
|
virtual void TestTriangles(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) = 0;
|
|
|
|
virtual void TestQuads(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) = 0;
|
|
|
|
virtual void TestQuadStrip(const VertexPointer& vertices, const IndexPointer& indices, SelectionIntersection& best) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Selectable;
|
|
|
|
|
|
|
|
class Selector
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void pushSelectable(Selectable& selectable) = 0;
|
|
|
|
virtual void popSelectable() = 0;
|
|
|
|
virtual void addIntersection(const SelectionIntersection& intersection) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline void Selector_add(Selector& selector, Selectable& selectable)
|
|
|
|
{
|
|
|
|
selector.pushSelectable(selectable);
|
|
|
|
selector.addIntersection(SelectionIntersection(0, 0));
|
|
|
|
selector.popSelectable();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void Selector_add(Selector& selector, Selectable& selectable, const SelectionIntersection& intersection)
|
|
|
|
{
|
|
|
|
selector.pushSelectable(selectable);
|
|
|
|
selector.addIntersection(intersection);
|
|
|
|
selector.popSelectable();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class VolumeTest;
|
|
|
|
class SelectionTestable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
STRING_CONSTANT(Name, "SelectionTestable");
|
|
|
|
|
|
|
|
virtual void testSelect(Selector& selector, SelectionTest& test) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline SelectionTestable* Instance_getSelectionTestable(scene::Instance& instance)
|
|
|
|
{
|
|
|
|
return InstanceTypeCast<SelectionTestable>::cast(instance);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class Plane3;
|
|
|
|
typedef Callback1<const Plane3&> PlaneCallback;
|
|
|
|
|
|
|
|
class SelectedPlanes
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual bool contains(const Plane3& plane) const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class PlaneSelectable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
STRING_CONSTANT(Name, "PlaneSelectable");
|
|
|
|
|
|
|
|
virtual void selectPlanes(Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback) = 0;
|
|
|
|
virtual void selectReversedPlanes(Selector& selector, const SelectedPlanes& selectedPlanes) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|