/* 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 #include "generic/vector.h" #include "scenelib.h" #include "generic/callbackfwd.h" 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(m_iter); } private: byte_pointer m_iter; std::size_t m_stride; }; VertexPointer(pointer vertices, std::size_t stride) : m_vertices(reinterpret_cast(vertices)), m_stride(stride) {} iterator begin() const { return iterator(m_vertices, m_stride); } reference operator[](std::size_t i) const { return *reinterpret_cast(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 class BasicVector3; typedef BasicVector3 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::cast(instance); } class Plane3; typedef Callback1 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