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 #include "file.h"
19 
20 float gGourceFileDiameter  = 8.0;
21 
22 std::vector<RFile*> gGourceRemovedFiles;
23 
24 FXFont file_selected_font;
25 FXFont file_font;
26 
RFile(const std::string & name,const vec3 & colour,const vec2 & pos,int tagid)27 RFile::RFile(const std::string & name, const vec3 & colour, const vec2 & pos, int tagid) : Pawn(name,pos,tagid) {
28     hidden = true;
29     size = gGourceFileDiameter * 1.05;
30     radius = size * 0.5;
31 
32     setGraphic(gGourceSettings.file_graphic);
33 
34     speed = 5.0;
35     nametime = gGourceSettings.filename_time;
36     name_interval = nametime;
37 
38     namecol     = vec3(1.0, 1.0, 1.0);
39     file_colour = colour;
40 
41     last_action    = 0.0f;
42     fade_start     = -1.0f;
43     removed_timestamp = 0;
44     expired        = false;
45     forced_removal = false;
46     removing       = false;
47 
48     shadow = true;
49 
50     distance = 0;
51 
52     setFilename(name);
53 
54     if(!file_selected_font.initialized()) {
55         file_selected_font = fontmanager.grab(gGourceSettings.font_file, 18);
56         file_selected_font.dropShadow(true);
57         file_selected_font.roundCoordinates(false);
58         file_selected_font.setColour(vec4(gGourceSettings.selection_colour, 1.0f));
59     }
60 
61     if(!file_font.initialized()) {
62         file_font = fontmanager.grab(gGourceSettings.font_file, gGourceSettings.filename_font_size);
63         file_font.dropShadow(true);
64         file_font.roundCoordinates(false);
65         file_font.setColour(vec4(gGourceSettings.filename_colour, 1.0f));
66     }
67 
68     setSelected(false);
69 
70     dir = 0;
71 }
72 
~RFile()73 RFile::~RFile() {
74 }
75 
remove(time_t removed_timestamp)76 void RFile::remove(time_t removed_timestamp) {
77     last_action = elapsed;
78     fade_start  = elapsed;
79     removing = true;
80     this->removed_timestamp = removed_timestamp;
81 }
82 
remove()83 void RFile::remove() {
84     forced_removal = true;
85     remove(0);
86 }
87 
setDir(RDirNode * dir)88 void RFile::setDir(RDirNode* dir) {
89     this->dir = dir;
90 }
91 
getDir() const92 RDirNode* RFile::getDir() const{
93     return dir;
94 }
95 
getAbsolutePos() const96 vec2 RFile::getAbsolutePos() const{
97     return pos + dir->getPos();
98 }
99 
overlaps(const vec2 & pos) const100 bool RFile::overlaps(const vec2& pos) const {
101 
102     vec2 abs_pos = getAbsolutePos();
103 
104     float halfsize_x = size * 0.5f;
105     vec2 halfsize ( halfsize_x, halfsize_x * graphic_ratio );
106 
107     Bounds2D file_bounds(abs_pos - halfsize, abs_pos + halfsize);
108 
109     return file_bounds.contains(pos);
110 }
111 
setFilename(const std::string & abs_file_path)112 void RFile::setFilename(const std::string& abs_file_path) {
113 
114     fullpath = abs_file_path;
115 
116     size_t pos = fullpath.rfind('/');
117 
118     if(pos != std::string::npos) {
119         path = name.substr(0,pos+1);
120         name = name.substr(pos+1, std::string::npos);
121     } else {
122         path = std::string("");
123         name = abs_file_path;
124     }
125 
126     //trim name to just extension
127     size_t dotsep = name.rfind(".");
128 
129     if(dotsep != std::string::npos && dotsep != name.size()-1) {
130         ext = name.substr(dotsep+1);
131     } else if(gGourceSettings.file_extension_fallback) {
132         ext = name;
133     }
134 }
135 
colourize()136 void RFile::colourize() {
137     file_colour = ext.size() ? colourHash(ext) : vec3(1.0f, 1.0f, 1.0f);
138 }
139 
getNameColour() const140 const vec3& RFile::getNameColour() const{
141     return selected ? gGourceSettings.selection_colour : namecol;
142 }
143 
setFileColour(const vec3 & colour)144 void RFile::setFileColour(const vec3 & colour) {
145     file_colour = colour;
146 }
147 
getFileColour() const148 const vec3 & RFile::getFileColour() const{
149     return file_colour;
150 }
151 
getColour() const152 vec3 RFile::getColour() const{
153     if(selected) return vec3(1.0f);
154 
155     float lc = elapsed - last_action;
156 
157     if(lc<1.0f) {
158         return touch_colour * (1.0f-lc) + file_colour * lc;
159     }
160 
161     return file_colour;
162 }
163 
getAlpha() const164 float RFile::getAlpha() const{
165     float alpha = Pawn::getAlpha();
166 
167     //user fades out if not doing anything
168     if(fade_start > 0.0f) {
169         alpha = 1.0 - glm::clamp(elapsed - fade_start, 0.0f, 1.0f);
170     }
171 
172     return alpha;
173 }
174 
logic(float dt)175 void RFile::logic(float dt) {
176     Pawn::logic(dt);
177 
178     vec2 dest_pos = dest;
179 /*
180     if(dir->getParent() != 0 && dir->noDirs()) {
181         vec2 dirnorm = dir->getNodeNormal();
182         dest_pos = dirnorm + dest;
183     }*/
184 
185     dest_pos = dest_pos * distance;
186 
187     accel = dest_pos - pos;
188 
189     // apply accel
190     vec2 accel2 = accel * speed * dt;
191 
192     if(glm::length2(accel2) > glm::length2(accel)) {
193         accel2 = accel;
194     }
195 
196     pos += accel2;
197 
198     //files have no momentum
199     accel = vec2(0.0f, 0.0f);
200 
201     if(fade_start < 0.0f && gGourceSettings.file_idle_time > 0.0f && (elapsed - last_action) > gGourceSettings.file_idle_time) {
202         fade_start = elapsed;
203     }
204 
205     // has completely faded out
206     if(fade_start > 0.0f && !expired && (elapsed - fade_start) >= 1.0) {
207 
208         expired = true;
209 
210         bool found = false;
211         for(std::vector<RFile*>::iterator it = gGourceRemovedFiles.begin(); it != gGourceRemovedFiles.end(); it++) {
212             if((*it) == this) {
213                 found = true;
214                 break;
215             }
216         }
217 
218         if(!found) {
219             gGourceRemovedFiles.push_back(this);
220             //fprintf(stderr, "expiring %s\n", fullpath.c_str());
221         }
222     }
223 
224     if(isHidden() && !forced_removal) elapsed = 0.0;
225 }
226 
touch(time_t touched_timestamp,const vec3 & colour)227 void RFile::touch(time_t touched_timestamp, const vec3 & colour) {
228     if(forced_removal || (removing && touched_timestamp < removed_timestamp)) return;
229 
230     //fprintf(stderr, "touch %s\n", fullpath.c_str());
231 
232     fade_start = -1.0f;
233     removing = false;
234     removed_timestamp = 0;
235     last_action = elapsed;
236     touch_colour = colour;
237 
238     //un expire file if touched after being removed
239     if(expired) {
240         for(std::vector<RFile*>::iterator it = gGourceRemovedFiles.begin(); it != gGourceRemovedFiles.end(); it++) {
241             if((*it) == this) {
242                 gGourceRemovedFiles.erase(it);
243                 break;
244             }
245         }
246         expired=false;
247     }
248 
249     showName();
250     setHidden(false);
251     dir->fileUpdated(true);
252 }
253 
setHidden(bool hidden)254 void RFile::setHidden(bool hidden) {
255     if(this->hidden==true && hidden==false && dir !=0) {
256         dir->addVisible();
257     }
258 
259     Pawn::setHidden(hidden);
260 }
261 
calcScreenPos(GLint * viewport,GLdouble * modelview,GLdouble * projection)262 void RFile::calcScreenPos(GLint* viewport, GLdouble* modelview, GLdouble* projection) {
263 
264     static GLdouble screen_x, screen_y, screen_z;
265 
266     vec2 text_pos = getAbsolutePos();
267     text_pos.x += 5.5f;
268 
269     if(selected)
270         text_pos.y -= 2.0f;
271     else
272         text_pos.y -= 1.0f;
273 
274     gluProject( text_pos.x, text_pos.y, 0.0f, modelview, projection, viewport, &screen_x, &screen_y, &screen_z);
275     screen_y = (float)viewport[3] - screen_y;
276 
277     screenpos.x = screen_x;
278     screenpos.y = screen_y;
279 }
280 
drawNameText(float alpha)281 void RFile::drawNameText(float alpha) {
282     if(!selected && alpha <= 0.01) return;
283 
284     float name_alpha = selected ? 1.0 : alpha;
285 
286     if(selected) {
287         file_selected_font.draw(screenpos.x, screenpos.y, name);
288     } else {
289         file_font.setAlpha(name_alpha);
290         file_font.draw(screenpos.x, screenpos.y, gGourceSettings.file_extensions ? ext : name);
291     }
292 }
293 
draw(float dt)294 void RFile::draw(float dt) {
295     Pawn::draw(dt);
296 
297     glLoadName(0);
298 }
299