1 /*
2     Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com)
3 
4     This program is free software; you can redistribute it and/or
5     modify it under the terms of the GNU General Public License
6     as published by the Free Software Foundation; either version
7     3 of the License, or (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #ifndef RDIRNODE_H
19 #define RDIRNODE_H
20 
21 #include "core/sdlapp.h"
22 #include "core/bounds.h"
23 #include "core/quadtree.h"
24 #include "core/pi.h"
25 #include "core/vbo.h"
26 
27 #include "gource_settings.h"
28 
29 #include "spline.h"
30 #include "file.h"
31 #include "bloom.h"
32 
33 #include <list>
34 #include <set>
35 
36 class RFile;
37 
38 class RDirNode : public QuadItem {
39     std::string abspath;
40 
41     std::string path_token;
42     int         path_token_offset;
43 
44     RDirNode* parent;
45     std::list<RDirNode*> children;
46     std::list<RFile*> files;
47 
48     SplineEdge spline;
49 
50     vec4 col;
51 
52     vec2 spos;
53 
54     vec2 projected_pos;
55     vec2 projected_spos;
56 
57     vec2 pos;
58     vec2 vel;
59     vec2 accel, prev_accel;
60 
61     float dir_area;
62 
63     bool visible;
64     bool in_frustum;
65     bool position_initialized;
66 
67     float since_node_visible;
68     float since_last_file_change;
69     float since_last_node_change;
70 
71     float file_area;
72     float dir_radius;
73     float dir_radius_sqrt;
74     float parent_radius;
75 
76     int depth;
77 
78     int visible_count;
79 
80     vec3 screenpos;
81     vec2 node_normal;
82 
83     void calcRadius();
84     void calcColour();
85 
86     std::string commonPathPrefix(const std::string& str) const;
87 
88     void changePath(const std::string & abspath);
89 
90     void setInitialPosition();
91 
92     void drawEdge(RDirNode* child) const;
93     void updateSplinePoint(float dt);
94     void move(float dt);
95 
96     vec2 calcFileDest(int layer_no, int file_no);
97     void updateFilePositions();
98 
99     void adjustDepth();
100     void adjustPath();
101     void drawDirName(FXFont& dirfont) const;
102 public:
103     RDirNode(RDirNode* parent, const std::string & abspath);
104     ~RDirNode();
105 
106     void printFiles();
107 
108     bool empty() const;
109 
110     bool isAnchor(RDirNode* node) const;
111 
112     RDirNode* getRoot();
113 
114     void fileUpdated(bool userInitiated);
115     void nodeUpdated(bool userInitiated);
116 
117     void addVisible();
118     bool isVisible();
119 
120     float getArea() const;
121 
122     int totalDirCount() const;
123     int totalFileCount() const;
124 
125     int getTokenOffset() const;
126 
127     int dirCount() const;
128     int fileCount() const;
129     int visibleFileCount() const;
130     bool noDirs() const;
131     bool noFiles() const;
132 
133     bool prefixedBy(const std::string & path) const;
134 
135     const std::string & getPath() const;
136 
137     const vec2 & getNodeNormal() const;
138 
139     bool isParent(RDirNode* node) const;
140 
141     bool addFile(RFile* f);
142     bool removeFile(RFile* f);
143 
144     int getDepth() const;
145 
146     const std::list<RDirNode*> & getChildren() const;
147 
148     void updateQuadItemBounds();
149 
150     float getParentRadius() const;
151     float getRadius() const;
152     float getRadiusSqrt() const;
153 
getFiles()154     const std::list<RFile*>* getFiles() const { return &files; };
155     void getFilesRecursive(std::list<RFile*>& files) const;
156 
157     vec3 averageFileColour() const;
158 
159     const vec4 & getColour() const;
160 
161     RDirNode* getParent() const;
162 
163     bool isDir(const std::string& path) const;
164     void findDirs(const std::string& path, std::list<RDirNode*>& dirs);
165 
166     const vec2 & getPos() const;
167 
168     void calcEdges();
169 
170     const vec2 & getProjectedPos() const;
171     const vec2 & getSPos() const;
172 
173     void setPos(const vec2 & pos);
174 
175     void rotate(float s, float c);
176     void rotate(float s, float c, const vec2& centre);
177 
178     void setParent(RDirNode* parent);
179 
180     float distanceToParent() const;
181 
182     void addNode(RDirNode* node);
183 
184     void debug(int indent=0) const;
185 
186     void applyForceDir(RDirNode* dir);
187     void applyForces(QuadTree &quadtree);
188 
189     void logic(float dt);
190 
191     void updateEdgeVBO(quadbuf& buffer) const;
192 
193     void drawEdges() const;
194     void drawEdgeShadows() const;
195 
196     void checkFrustum(const Frustum & frustum);
197 
198     void updateFilesVBO(quadbuf& buffer, float dt) const;
199     void updateBloomVBO(bloombuf& buffer, float dt);
200 
201     void drawShadows(float dt) const;
202     void drawFiles(float dt) const;
203     void drawBloom(float dt);
204 
205     void drawNames(FXFont& dirfont);
206 
207     void calcScreenPos(GLint* viewport, GLdouble* modelview, GLdouble* projection);
208 
209     void nodeCount() const;
210 };
211 
212 class DirForceFunctor : public VisitFunctor<QuadItem>{
213   private:
214     RDirNode * this_dir;
215     std::set<RDirNode*> seen;
216     size_t loopCount;
217 
218   public:
DirForceFunctor(RDirNode * dir)219     DirForceFunctor(RDirNode * dir) : this_dir(dir), seen(), loopCount(0){}
getLoopCount()220     int getLoopCount() const{ return loopCount; }
operator()221     void operator()(QuadItem * item){
222 
223         std::set<RDirNode*>::iterator seentest;
224         RDirNode* d = (RDirNode*) (item);
225 
226         if(d==this_dir) return;
227         if(d==this_dir->getParent()) return;
228         if(d->getParent() == this_dir) return;
229         if(this_dir->isParent(d)) return;
230         if(d->isParent(this_dir)) return;
231 
232         if(d->node_count != 1) {
233             if((seentest = seen.find(d)) != seen.end())
234                 return;
235 
236             seen.insert(d);
237         }
238 
239         this_dir->applyForceDir(d);
240 
241         loopCount++;
242 
243     }
244 
245 };
246 
247 extern int gGourceDirNodeInnerLoops;
248 extern int gGourceFileInnerLoops;
249 
250 extern float gGourcePointSize;
251 extern bool  gGourceNodeDebug;
252 extern bool  gGourceGravity;
253 extern float gGourceForceGravity;
254 
255 extern std::map<std::string, RDirNode*> gGourceDirMap;
256 
257 #endif
258