1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef TrenchBroom_ClipTool
21 #define TrenchBroom_ClipTool
22 
23 #include "TrenchBroom.h"
24 #include "VecMath.h"
25 #include "Model/Hit.h"
26 #include "Model/ModelTypes.h"
27 #include "View/Tool.h"
28 #include "View/ViewTypes.h"
29 
30 namespace TrenchBroom {
31     namespace Renderer {
32         class BrushRenderer;
33         class Camera;
34         class RenderBatch;
35         class RenderContext;
36     }
37 
38     namespace Model {
39         class ModelFactory;
40         class PickResult;
41     }
42 
43     namespace View {
44         class Grid;
45         class Selection;
46 
47         class ClipTool : public Tool {
48         public:
49             static const Model::Hit::HitType PointHit;
50         private:
51             enum ClipSide {
52                 ClipSide_Front,
53                 ClipSide_Both,
54                 ClipSide_Back
55             };
56 
57             class ClipStrategy {
58             public:
59                 virtual ~ClipStrategy();
60                 void pick(const Ray3& pickRay, const Renderer::Camera& camera, Model::PickResult& pickResult) const;
61                 void render(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Model::PickResult& pickResult);
62                 void renderFeedback(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Vec3& point) const;
63 
64                 bool computeThirdPoint(Vec3& point) const;
65 
66                 bool canClip() const;
67                 bool canAddPoint(const Vec3& point) const;
68                 void addPoint(const Vec3& point, const Vec3::List& helpVectors);
69                 bool removeLastPoint();
70 
71                 bool canDragPoint(const Model::PickResult& pickResult, Vec3& initialPosition) const;
72                 void beginDragPoint(const Model::PickResult& pickResult);
73                 void beginDragLastPoint();
74                 bool dragPoint(const Vec3& newPosition, const Vec3::List& helpVectors);
75                 void endDragPoint();
76                 void cancelDragPoint();
77 
78                 bool setFace(const Model::BrushFace* face);
79                 void reset();
80                 size_t getPoints(Vec3& point1, Vec3& point2, Vec3& point3) const;
81             private:
82                 virtual void doPick(const Ray3& pickRay, const Renderer::Camera& camera, Model::PickResult& pickResult) const = 0;
83                 virtual void doRender(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Model::PickResult& pickResult) = 0;
84 
85                 virtual void doRenderFeedback(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Vec3& point) const = 0;
86 
87                 virtual bool doComputeThirdPoint(Vec3& point) const = 0;
88 
89                 virtual bool doCanClip() const = 0;
90                 virtual bool doCanAddPoint(const Vec3& point) const = 0;
91                 virtual void doAddPoint(const Vec3& point, const Vec3::List& helpVectors) = 0;
92                 virtual bool doRemoveLastPoint() = 0;
93 
94                 virtual bool doCanDragPoint(const Model::PickResult& pickResult, Vec3& initialPosition) const = 0;
95                 virtual void doBeginDragPoint(const Model::PickResult& pickResult) = 0;
96                 virtual void doBeginDragLastPoint() = 0;
97                 virtual bool doDragPoint(const Vec3& newPosition, const Vec3::List& helpVectors) = 0;
98                 virtual void doEndDragPoint() = 0;
99                 virtual void doCancelDragPoint() = 0;
100 
101                 virtual bool doSetFace(const Model::BrushFace* face) = 0;
102                 virtual void doReset() = 0;
103                 virtual size_t doGetPoints(Vec3& point1, Vec3& point2, Vec3& point3) const = 0;
104             };
105 
106             class PointClipStrategy;
107             class FaceClipStrategy;
108         private:
109             MapDocumentWPtr m_document;
110 
111             ClipSide m_clipSide;
112             ClipStrategy* m_strategy;
113 
114             Model::ParentChildrenMap m_frontBrushes;
115             Model::ParentChildrenMap m_backBrushes;
116 
117             Renderer::BrushRenderer* m_remainingBrushRenderer;
118             Renderer::BrushRenderer* m_clippedBrushRenderer;
119 
120             bool m_ignoreNotifications;
121         public:
122             ClipTool(MapDocumentWPtr document);
123             ~ClipTool();
124 
125             const Grid& grid() const;
126 
127             void toggleSide();
128             void resetSide();
129 
130             void pick(const Ray3& pickRay, const Renderer::Camera& camera, Model::PickResult& pickResult);
131 
132             void render(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Model::PickResult& pickResult);
133         private:
134             void renderBrushes(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch);
135             void renderStrategy(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Model::PickResult& pickResult);
136         public:
137             void renderFeedback(Renderer::RenderContext& renderContext, Renderer::RenderBatch& renderBatch, const Vec3& point) const;
138         public:
139             bool canClip() const;
140             void performClip();
141         private:
142             Model::ParentChildrenMap clipBrushes();
143         public:
144             Vec3 defaultClipPointPos() const;
145 
146             bool canAddPoint(const Vec3& point) const;
147             void addPoint(const Vec3& point, const Vec3::List& helpVectors);
148             bool removeLastPoint();
149 
150             bool beginDragPoint(const Model::PickResult& pickResult, Vec3& initialPosition);
151             void beginDragLastPoint();
152             bool dragPoint(const Vec3& newPosition, const Vec3::List& helpVectors);
153             void endDragPoint();
154             void cancelDragPoint();
155 
156             void setFace(const Model::BrushFace* face);
157             bool reset();
158         private:
159             void resetStrategy();
160             void update();
161 
162             void clearBrushes();
163             void updateBrushes();
164 
165             void setFaceAttributes(const Model::BrushFaceList& faces, Model::BrushFace* frontFace, Model::BrushFace* backFace) const;
166 
167             void clearRenderers();
168             void updateRenderers();
169             void addBrushesToRenderer(const Model::ParentChildrenMap& map, Renderer::BrushRenderer* renderer);
170 
171             bool keepFrontBrushes() const;
172             bool keepBackBrushes() const;
173         private:
174             bool doActivate();
175             bool doDeactivate();
176 
177             void bindObservers();
178             void unbindObservers();
179             void selectionDidChange(const Selection& selection);
180             void nodesWillChange(const Model::NodeList& nodes);
181             void nodesDidChange(const Model::NodeList& nodes);
182         private: // implement Tool interface
183             String doGetIconName() const;
184         };
185     }
186 }
187 
188 #endif /* defined(TrenchBroom_ClipTool) */
189