BVB Source Codes

Gource Show dirnode.cpp Source code

Return Download Gource: download dirnode.cpp Source code - Download Gource Source code - Type:.cpp
  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 "dirnode.h"
  19.  
  20. float gGourceMinDirSize   = 15.0;
  21.  
  22. float gGourceForceGravity = 10.0;
  23. float gGourceDirPadding   = 1.5;
  24.  
  25. bool  gGourceNodeDebug    = false;
  26. bool  gGourceGravity      = true;
  27.  
  28. //debugging
  29. int  gGourceDirNodeInnerLoops = 0;
  30. int  gGourceFileInnerLoops = 0;
  31.  
  32. std::map<std::string, RDirNode*> gGourceDirMap;
  33.  
  34. RDirNode::RDirNode(RDirNode* parent, const std::string & abspath) {
  35.  
  36.     changePath(abspath);
  37.  
  38.     parent = 0;
  39.     setParent(parent);
  40.  
  41.     accel = spos = prev_accel = vel = vec2(0.0f);
  42.  
  43.     //NOTE: parent is always being set to 0 so this never gets called ...
  44.  
  45.     //figure out starting position
  46.     if(parent !=0) {
  47.         vec2 parentPos = parent->getPos();
  48.         vec2 offset;
  49.  
  50.         pos = parentPos;
  51.     } else {
  52.         pos = vec2(0.0f, 0.0f);
  53.     }
  54.  
  55.     float padded_file_radius  = gGourceFileDiameter * 0.5;
  56.  
  57.     file_area  = padded_file_radius * padded_file_radius * PI;
  58.  
  59.     visible_count = 0;
  60.  
  61.     visible = false;
  62.     position_initialized = false;
  63.  
  64.     since_node_visible = 0.0;
  65.     since_last_file_change = 0.0;
  66.     since_last_node_change = 0.0;
  67.  
  68.     calcRadius();
  69.     calcColour();
  70. }
  71.  
  72. void RDirNode::changePath(const std::string & abspath) {
  73.     //fix up path
  74.  
  75.     gGourceDirMap.erase(this->abspath);
  76.     this->abspath = abspath;
  77.  
  78.     if(abspath.empty() || abspath[abspath.size()-1] != '/') {
  79.         this->abspath += std::string("/");
  80.     }
  81.  
  82.     //debugLog("new dirnode %s\n", abspath.c_str());
  83.  
  84.     gGourceDirMap[this->abspath] = this;
  85. }
  86.  
  87. RDirNode::~RDirNode() {
  88.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  89.         delete (*it);
  90.     }
  91.  
  92.     gGourceDirMap.erase(abspath);
  93. }
  94.  
  95. int RDirNode::getTokenOffset() const{
  96.     return path_token_offset;
  97. }
  98.  
  99. void RDirNode::fileUpdated(bool userInitiated) {
  100.     calcRadius();
  101.  
  102.     since_last_file_change = 0.0;
  103.  
  104.     nodeUpdated(userInitiated);
  105. }
  106.  
  107. void RDirNode::nodeUpdated(bool userInitiated) {
  108.     if(userInitiated) since_last_node_change = 0.0;
  109.  
  110.     calcRadius();
  111.     updateFilePositions();
  112.     if(visible && noDirs() && noFiles()) visible = false;
  113.     if(parent !=0) parent->nodeUpdated(true);
  114. }
  115.  
  116. void RDirNode::rotate(float s, float c) {
  117.  
  118.     if(parent != 0) {
  119.         pos  = rotate_vec2(pos,  s, c);
  120.         spos = rotate_vec2(spos, s, c);
  121.     }
  122.  
  123.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  124.         RDirNode* child = (*it);
  125.         child->rotate(s, c);
  126.     }
  127. }
  128.  
  129. void RDirNode::setPos(const vec2 & pos) {
  130.     this->pos = pos;
  131. }
  132.  
  133. //returns true if supplied path prefixes the nodes path
  134. bool RDirNode::prefixedBy(const std::string & path) const {
  135.     if(path.empty()) return false;
  136.  
  137.     if(path[path.size()-1] != '/')
  138.         return abspath.find(path + std::string("/")) == 0;
  139.     else
  140.         return abspath.find(path) == 0;
  141. }
  142.  
  143. const std::string & RDirNode::getPath() const{
  144.     return abspath;
  145. }
  146.  
  147. RDirNode* RDirNode::getParent() const{
  148.     return parent;
  149. }
  150.  
  151.  
  152. bool RDirNode::isDir(const std::string& path) const {
  153.  
  154.     if(prefixedBy(path)) return true;
  155.  
  156.     if(path.find(abspath) != 0) return false;
  157.  
  158.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  159.         if((*it)->isDir(path)) return true;
  160.     }
  161.  
  162.     return false;
  163. }
  164.  
  165. //finds directories closest to the root directory prefixed by path (eg foo/ may match just foo/ or could also match foo/bar1, foo/bar2, ... if foo/ doesn't exist).
  166. void RDirNode::findDirs(const std::string& path, std::list<RDirNode*>& dirs) {
  167.  
  168.     if(prefixedBy(path)) {
  169.         dirs.push_back(this);
  170.         return;
  171.     }
  172.  
  173.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  174.         (*it)->findDirs(path, dirs);
  175.     }
  176. }
  177.  
  178. void RDirNode::getFilesRecursive(std::list<RFile*>& files) const {
  179.  
  180.     //add this dirs files
  181.     files.insert(files.begin(), this->files.begin(), this->files.end());
  182.  
  183.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  184.         (*it)->getFilesRecursive(files);
  185.     }
  186. }
  187.  
  188. int RDirNode::getDepth() const{
  189.     return depth;
  190. }
  191.  
  192. void RDirNode::adjustPath() {
  193.  
  194.     //update display path
  195.     int parent_token_offset = 0;
  196.  
  197.     path_token_offset = abspath.size();
  198.  
  199.     if(parent != 0) {
  200.         parent_token_offset  = parent->getTokenOffset();
  201.  
  202.         //debugLog("abspath.substr arguments: %d %d %s size = %d\n", parent_token_offset, abspath.size()-parent_token_offset-1, abspath.c_str(), abspath.size());
  203.  
  204.         path_token        = abspath.substr(parent_token_offset, abspath.size()-parent_token_offset-1);
  205.         path_token_offset = abspath.size();
  206.  
  207.         //debugLog("new token %s\n", path_token.c_str());
  208.     }
  209. }
  210.  
  211. void RDirNode::setParent(RDirNode* parent) {
  212.     if(parent != 0 && this->parent == parent) return;
  213.  
  214.     this->parent = parent;
  215.  
  216.     adjustPath();
  217.     adjustDepth();
  218. }
  219.  
  220. void RDirNode::adjustDepth() {
  221.  
  222.     if(parent == 0) {
  223.         depth = 1;
  224.     } else {
  225.         depth = parent->getDepth() + 1;
  226.     }
  227.  
  228.     for(RDirNode* child : children) {
  229.         child->adjustDepth();
  230.     }
  231. }
  232.  
  233. void RDirNode::addNode(RDirNode* node) {
  234.     // does this node prefix any other nodes, if so, add them to it
  235.  
  236.     std::vector<RDirNode*> matches;
  237.     std::string path = node->getPath();
  238.  
  239.     //debugLog("adding node %s to %s\n", path.c_str(), abspath.c_str());
  240.  
  241.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); ) {
  242.         RDirNode* child = (*it);
  243.  
  244.         if(child->prefixedBy(path)) {
  245.             it = children.erase(it);
  246.             node->addNode(child);
  247.         } else {
  248.             it++;
  249.         }
  250.     }
  251.  
  252.     // add to this node
  253.     children.push_back(node);
  254.     node->setParent(this);
  255.  
  256.     //debugLog("added node %s to %s\n", node->getPath().c_str(), getPath().c_str());
  257.  
  258.     nodeUpdated(false);
  259. }
  260.  
  261. RDirNode* RDirNode::getRoot() {
  262.     if(parent==0) return this;
  263.     return parent->getRoot();
  264. }
  265.  
  266. // note - you still need to delete the file yourself
  267. bool RDirNode::removeFile(RFile* f) {
  268.     //doesnt match this path at all
  269.     if(f->path.find(abspath) != 0) {
  270.         return false;
  271.     }
  272.  
  273.     //is this dir - add to this node
  274.     if(f->path.compare(abspath) == 0) {
  275.  
  276.         for(std::list<RFile*>::iterator it = files.begin(); it != files.end(); it++) {
  277.             if((*it)==f) {
  278.                 files.erase(it);
  279.                 if(!f->isHidden()) visible_count--;
  280.  
  281.                 fileUpdated(false);
  282.  
  283.                 return true;
  284.             }
  285.         }
  286.  
  287.         return false;
  288.     }
  289.  
  290.     //does this belong to one of the children ?
  291.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  292.         RDirNode* node = (*it);
  293.         bool removed = node->removeFile(f);
  294.  
  295.         if(removed) {
  296.             //fprintf(stderr, "%s file removed from a child. child file count=%d, dir count =%d\n", getPath().c_str(), node->fileCount(), node->dirCount());
  297.             //node->printFiles();
  298.  
  299.             //node is now empty, reap!
  300.             if(node->noFiles() && node->noDirs()) {
  301.                 children.erase(it);
  302.                 //fprintf(stderr, "deleting node %s from %s\n", node->getPath().c_str(), getPath().c_str());
  303.                 delete node;
  304.                 nodeUpdated(false);
  305.             }
  306.  
  307.             return true;
  308.         }
  309.     }
  310.  
  311.     return false;
  312. }
  313.  
  314.  
  315. void RDirNode::printFiles() {
  316.     for(std::list<RFile*>::iterator it = files.begin(); it != files.end(); it++) {
  317.         RFile* file = (*it);
  318.         fprintf(stderr, "%s: %s %s\n", getPath().c_str(), file->fullpath.c_str() , file->isHidden() ? "hidden " : "");
  319.     }
  320. }
  321.  
  322.  
  323. void RDirNode::addVisible() {
  324.     visible_count++;
  325.     visible = true;
  326. }
  327.  
  328. bool RDirNode::isVisible() {
  329.  
  330.     if(visible) return true;
  331.  
  332.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  333.         if((*it)->isVisible()) {
  334.             visible = true;
  335.             return true;
  336.         }
  337.     }
  338.  
  339.     return false;
  340. }
  341.  
  342. int RDirNode::visibleFileCount() const{
  343.     return visible_count;
  344. }
  345.  
  346. int RDirNode::fileCount() const{
  347.     return files.size();
  348. }
  349.  
  350. bool RDirNode::noFiles() const{
  351.     return files.empty();
  352. }
  353.  
  354. std::string RDirNode::commonPathPrefix(const std::string & str) const{
  355.     size_t c = 0;
  356.     int slash = -1;
  357.  
  358.     while(c<abspath.size() && c<str.size() && abspath[c] == str[c]) {
  359.         if(abspath[c] == '/') {
  360.             slash = c;
  361.         }
  362.         c++;
  363.     }
  364.  
  365.     if(slash==-1) return "";
  366.     return str.substr(0,slash+1);
  367. }
  368.  
  369. bool RDirNode::addFile(RFile* f) {
  370.  
  371.     //doesnt match this path at all
  372.     if(f->path.find(abspath) != 0) {
  373.  
  374.         if(parent != 0) return false;
  375.  
  376.         //if this is the root node (ie no parent), we fork it
  377.         //if we encounter a file with a non matching path to the
  378.         //current root path. the calling process then checks if
  379.         //the root now has a parent node, and changes the pointer.
  380.  
  381.         RDirNode* newparent;
  382.  
  383.         std::string common = commonPathPrefix(f->path);
  384.         if(common.size()==0) common = "/";
  385.  
  386.         newparent = new RDirNode(0, common);
  387.         newparent->addNode(this);
  388.         return newparent->addFile(f);
  389.     }
  390.  
  391.     //simply change path of node and add this to it
  392.     if(   parent==0 && abspath == "/"
  393.        && f->path.compare(abspath) != 0 && noFiles() && noDirs()) {
  394.         debugLog("modifying root path to %s", f->path.c_str());
  395.         changePath(f->path);
  396.     }
  397.  
  398.     //is this dir - add to this node
  399.     if(f->path.compare(abspath) == 0) {
  400.         //debugLog("addFile %s to %s\n", f->fullpath.c_str(), abspath.c_str());
  401.  
  402.         files.push_back(f);
  403.         if(!f->isHidden()) visible_count++;
  404.         f->setDir(this);
  405.  
  406.         fileUpdated(false);
  407.  
  408.         return true;
  409.     }
  410.  
  411.     bool added = false;
  412.  
  413.     //does this belong to one of the children ?
  414.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  415.         RDirNode* child =  (*it);
  416.  
  417.         added = child->addFile(f);
  418.  
  419.         if(added) break;
  420.     }
  421.  
  422.     if(added && parent != 0) return true;
  423.  
  424.     //do we have a file in this directory thats fullpath is a prefix of this file, if so
  425.     //that file is actually a directory - the file should be removed, and a directory with that path added
  426.     //if this is the root node we do this regardless of if the file was added to a child node
  427.  
  428.     for(std::list<RFile*>::const_iterator it = files.begin(); it != files.end(); it++) {
  429.         RFile* file = (*it);
  430.  
  431.         if(f->path.find(file->fullpath) == 0) {
  432.             //fprintf(stderr, "removing %s as is actually the directory of %s\n", file->fullpath.c_str(), f->fullpath.c_str());
  433.             file->remove(true);
  434.             break;
  435.         }
  436.     }
  437.  
  438.     if(added) return true;
  439.  
  440.     //add new child, add it to that
  441.     //if commonpath is longer than abspath, add intermediate node, else just add at the files path
  442.     RDirNode* node = new RDirNode(this, f->path);
  443.  
  444.     node->addFile(f);
  445.  
  446.     addNode(node);
  447.  
  448.     // do we have dir nodes, with a common path element greater than abspath,
  449.     // if so create another node, and move those nodes there
  450.  
  451.      std::string commonpath;
  452.      vec2 commonPos;
  453.      for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  454.          RDirNode* child =  (*it);
  455.  
  456.          std::string common = child->commonPathPrefix(f->path);
  457.          if(common.size() > abspath.size() && common != f->path) {
  458.             commonpath = common;
  459.             commonPos = child->getPos();
  460.             break;
  461.          }
  462.      }
  463.  
  464.     // redistribute to new common node
  465.     if(commonpath.size() > abspath.size()) {
  466.         //debugLog("common path %s\n", commonpath.c_str());
  467.  
  468.         RDirNode* cnode = new RDirNode(this, commonpath);
  469.         cnode->setPos(commonPos);
  470.  
  471.         for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end();) {
  472.             RDirNode* child =  (*it);
  473.  
  474.             if(child->prefixedBy(commonpath)) {
  475.                 //debugLog("this path = %s, commonpath = %s, path = %s\n", abspath.c_str(), commonpath.c_str(), child->getPath().c_str());
  476.                 it = children.erase(it);
  477.                 cnode->addNode(child);
  478.                 continue;
  479.             }
  480.  
  481.             it++;
  482.         }
  483.  
  484.         addNode(cnode);
  485.     }
  486.  
  487.     return true;
  488. }
  489.  
  490. float RDirNode::getParentRadius() const{
  491.     return parent_radius;
  492. }
  493.  
  494. float RDirNode::getRadius() const{
  495.     return dir_radius;
  496. }
  497.  
  498. float RDirNode::getRadiusSqrt() const{
  499.     return dir_radius_sqrt;
  500. }
  501.  
  502. vec3 RDirNode::averageFileColour() const{
  503.  
  504.     vec3 av;
  505.     int count = 0;
  506.  
  507.     for(std::list<RFile*>::const_iterator it = files.begin(); it != files.end(); it++) {
  508.         RFile* file = (*it);
  509.  
  510.         if(file->isHidden()) continue;
  511.  
  512.         av += file->getColour();
  513.  
  514.         count++;
  515.     }
  516.  
  517.     if(count>0) av *= (1.0f/(float)count);
  518.  
  519.     count = 0;
  520.  
  521.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end();it++) {
  522.             RDirNode* child =  (*it);
  523.  
  524.             av += child->averageFileColour();
  525.             count++;
  526.     }
  527.  
  528.     if(count>0) av *= (1.0f/(float)count);
  529.  
  530.     return av;
  531. }
  532.  
  533. const vec4 & RDirNode::getColour() const{
  534.     return col;
  535. }
  536.  
  537. void RDirNode::calcColour() {
  538.  
  539.     // make branch brighter if recently accessed
  540.     float brightness = std::max(0.6f, 1.0f - std::min(1.0f, since_last_node_change / 3.0f));
  541.  
  542.     col = vec4(brightness, brightness, brightness, 1.0);
  543.  
  544.     int fcount = 0;
  545.  
  546.     for(std::list<RFile*>::iterator it = files.begin(); it != files.end(); it++) {
  547.         RFile* file = (*it);
  548.  
  549.         if(file->isHidden()) continue;;
  550.  
  551.         vec3 filecol = file->getColour() * brightness;
  552.         float a       = file->getAlpha();
  553.  
  554.         col += vec4(filecol.x, filecol.y, filecol.z, a);
  555.  
  556.         fcount++;
  557.     }
  558.  
  559.     this->col /= (float) fcount + 1.0;
  560. }
  561.  
  562. float RDirNode::getArea() const{
  563.     return dir_area;
  564. }
  565.  
  566. void RDirNode::calcRadius() {
  567.  
  568.     float total_file_area = file_area * visible_count;
  569.  
  570.     dir_area = total_file_area;
  571.  
  572.     //float parent_circ        = 0.0;
  573.  
  574.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  575.         RDirNode* node = (*it);
  576.  
  577.         dir_area += node->getArea();
  578.     //    parent_circ += node->getRadiusSqrt();
  579.     }
  580.  
  581.     this->dir_radius = std::max(1.0f, (float)sqrt(dir_area)) * gGourceDirPadding;
  582.     //this->dir_radius_sqrt = sqrt(dir_radius); //dir_radius_sqrt is not used
  583.  
  584. //    this->parent_radius = std::max(1.0, parent_circ / PI);
  585.     this->parent_radius = std::max(1.0f, (float) sqrt(total_file_area) * gGourceDirPadding);
  586. }
  587.  
  588. float RDirNode::distanceToParent() const{
  589.  
  590.     float posd     = glm::length(parent->getPos() - pos);
  591.     float distance = posd - (dir_radius + parent->getParentRadius());
  592.  
  593.     return distance;
  594. }
  595.  
  596. void RDirNode::applyForceDir(RDirNode* node) {
  597.     if(node == this) return;
  598.  
  599.     vec2 dir = node->getPos() - pos;
  600.  
  601.     float posd2       = glm::length2(dir);
  602.     float myradius    = getRadius();
  603.     float your_radius = node->getRadius();
  604.  
  605.     float sumradius = (myradius + your_radius);
  606.  
  607.     float distance2 = posd2 - sumradius*sumradius;
  608.  
  609.     if(distance2>0.0) return;
  610.  
  611.     float posd = sqrt(posd2);
  612.  
  613.     float distance = posd - myradius - your_radius;
  614.  
  615.     //resolve overlap
  616.     if(posd < 0.00001) {
  617.         accel += normalise(vec2( (rand() % 100) - 50, (rand() % 100) - 50));
  618.         return;
  619.     }
  620.  
  621.     accel += distance * normalise(dir);
  622. }
  623.  
  624. const vec2 & RDirNode::getPos() const{
  625.     return pos;
  626. }
  627.  
  628. bool RDirNode::isParent(RDirNode* node) const {
  629.     if(node==parent) return true;
  630.     if(parent==0) return false;
  631.  
  632.     return parent->isParent(node);
  633. }
  634.  
  635. bool RDirNode::empty() const{
  636.     return (visible_count==0 && noDirs()) ? true : false;
  637. }
  638.  
  639. void RDirNode::applyForces(QuadTree & quadtree) {
  640.  
  641.     //child nodes
  642.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  643.         RDirNode* node = (*it);
  644.  
  645.         node->applyForces(quadtree);
  646.     }
  647.  
  648.     if(parent == 0) return;
  649.  
  650.     DirForceFunctor dff(this);
  651.     quadtree.visitItemsInBounds(quadItemBounds, dff);
  652.     gGourceDirNodeInnerLoops += dff.getLoopCount();
  653.  
  654.     //always call on parent no matter how far away
  655.     applyForceDir(parent);
  656.  
  657.     //pull towards parent
  658.     float parent_dist = distanceToParent();
  659.  
  660.     //  * dirs should attract to sit on the radius of the parent dir ie:
  661.     //    should attract to distance_to_parent * normal_to_parent
  662.  
  663.  
  664.  
  665.     accel += gGourceForceGravity * parent_dist * normalise(parent->getPos() - pos);
  666.  
  667.     //  * dirs should be pushed along the parent_parent to parent normal by a force smaller than the parent radius force
  668.     RDirNode* pparent = parent->getParent();
  669.  
  670.     if(pparent != 0) {
  671.         vec2 parent_edge = (parent->getPos() - pparent->getPos());
  672.         vec2 parent_edge_normal = normalise(parent_edge);
  673.  
  674.         vec2 dest = (parent->getPos() + (parent->getRadius() + getRadius()) * parent_edge_normal) - pos;
  675.  
  676.         accel += dest;
  677.     }
  678.  
  679.     //  * dirs should repulse from other dirs of this parent
  680.     const std::list<RDirNode*> & siblings = parent->getChildren();
  681.     if(!siblings.empty()) {
  682.         vec2 sib_accel;
  683.  
  684.         int visible = 1;
  685.  
  686.         for(std::list<RDirNode*>::const_iterator it = siblings.begin(); it != siblings.end(); it++) {
  687.             RDirNode* node = (*it);
  688.  
  689.             if(node == this) continue;
  690.             if(!node->isVisible()) continue;
  691.  
  692.             visible++;
  693.  
  694.             sib_accel -= normalise(node->getPos() - pos);
  695.         }
  696.  
  697.         //parent circumfrence divided by the number of visible child nodes
  698.         if(visible>1) {
  699.             float slice_size = (parent->getRadius() * PI) / (float) (visible+1);
  700.             sib_accel *= slice_size;
  701.  
  702.             accel += sib_accel;
  703.         }
  704.     }
  705.  
  706. }
  707.  
  708. void RDirNode::debug(int indent) const{
  709.     std::string indentstr;
  710.     while(indentstr.size() < indent) indentstr += " ";
  711.  
  712.     debugLog("%s%s", indentstr.c_str(), abspath.c_str());
  713.  
  714.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  715.         RDirNode* node = (*it);
  716.         node->debug(indent+1);
  717.     }
  718. }
  719.  
  720. int RDirNode::totalFileCount() const{
  721.     int total = visibleFileCount();
  722.  
  723.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  724.         RDirNode* node = (*it);
  725.         total += node->visibleFileCount();
  726.     }
  727.  
  728.     return total;
  729. }
  730.  
  731. int RDirNode::totalDirCount() const{
  732.     int total = 1;
  733.  
  734.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  735.         RDirNode* node = (*it);
  736.         total += node->totalDirCount();
  737.     }
  738.  
  739.     return total;
  740. }
  741.  
  742. int RDirNode::dirCount() const{
  743.     return children.size();
  744. }
  745.  
  746. bool RDirNode::noDirs() const{
  747.     return children.empty();
  748. }
  749.  
  750. const std::list<RDirNode*> & RDirNode::getChildren() const{
  751.     return children;
  752. }
  753.  
  754. void RDirNode::updateSplinePoint(float dt) {
  755.     if(parent == 0) return;
  756.  
  757.     //update the spline point
  758.     vec2 td = (parent->getPos() - pos) * 0.5f;
  759.  
  760.     vec2 mid = pos + td;// - td.perpendicular() * pos.normal();// * 10.0;
  761.  
  762.     vec2 delta = (mid - spos);
  763.  
  764.     //dont let spos get more than half the length of the distance behind
  765.     if(glm::length2(delta) > glm::length2(td)) {
  766.         spos += normalise(delta) * (glm::length(delta) - glm::length(td));
  767.     }
  768.  
  769.     spos += delta * std::min(1.0f, dt * 2.0f);
  770. }
  771.  
  772. void RDirNode::setInitialPosition() {
  773.     RDirNode* parentP = parent->getParent();
  774.  
  775.     pos = parent->getPos();
  776.  
  777.     //offset position by some pseudo-randomness
  778.     if(parentP != 0) {
  779.         //pos += ((parent->getPos() - parentP->getPos()).normal() * 2.0 + vec2Hash(abspath)).normal();
  780.         pos += normalise(normalise(parent->getPos() - parentP->getPos()) * 2.0f + vec2Hash(abspath));
  781.  
  782.     }  else {
  783.         pos += vec2Hash(abspath);
  784.     }
  785.  
  786.     //the spline point
  787.     spos = pos - (parent->getPos() - pos) * 0.5f;
  788.     position_initialized=true;
  789. }
  790.  
  791. void RDirNode::move(float dt) {
  792.  
  793.     //the root node is the centre of the world
  794.     if(parent == 0) {
  795.         pos = vec2(0.0f);
  796.         return;
  797.     }
  798.  
  799.     //initial position
  800.     if(!empty() && !position_initialized) {
  801.         setInitialPosition();
  802.     }
  803.  
  804.     pos += accel * dt;
  805.  
  806.     if(gGourceSettings.elasticity>0.0) {
  807.         vec2 diff = (accel - prev_accel);
  808.  
  809.         float m = dt * gGourceSettings.elasticity;
  810.  
  811.         vec2 accel3 = prev_accel * (1.0f-m) + diff * m;
  812.         pos += accel3;
  813.         prev_accel = accel3;
  814.     }
  815.  
  816.     //accel = accel * std::max(0.0f, (1.0f - dt*10.0f));
  817.     accel = vec2(0.0, 0.0);
  818. }
  819.  
  820. const vec2 & RDirNode::getNodeNormal() const{
  821.     return node_normal;
  822. }
  823.  
  824. vec2 RDirNode::calcFileDest(int max_files, int file_no) {
  825.  
  826.     float arc   = 1.0/(float)max_files;
  827.  
  828.     float frac = arc * 0.5 + arc * file_no;
  829.  
  830.     vec2 dest = vec2(sinf(frac*PI*2.0), cosf(frac*PI*2.0));
  831.  
  832.     return dest;
  833. }
  834.  
  835. void RDirNode::updateFilePositions() {
  836.  
  837.     int max_files = 1;
  838.     int diameter  = 1;
  839.     int file_no   = 0;
  840.     float d = 0.0;
  841.  
  842.     int files_left = visible_count;
  843.  
  844.     for(std::list<RFile*>::iterator it = files.begin(); it!=files.end(); it++) {
  845.         RFile* f = *it;
  846.  
  847.         if(f->isHidden()) {
  848.             f->setDest(vec2(0.0,0.0));
  849.             f->setDistance(0.0f);
  850.             continue;
  851.         }
  852.  
  853.         vec2 dest = calcFileDest(max_files, file_no);
  854.  
  855.         f->setDest(dest);
  856.         f->setDistance(d);
  857.  
  858.         files_left--;
  859.         file_no++;
  860.  
  861.         if(file_no>=max_files) {
  862.             diameter++;
  863.             d += gGourceFileDiameter;
  864.             max_files = (int) std::max(1.0, diameter*PI);
  865.  
  866.             if(files_left<max_files) {
  867.                 max_files = files_left;
  868.             }
  869.  
  870.             file_no=0;
  871.         }
  872.     }
  873. }
  874.  
  875. void RDirNode::calcEdges() {
  876.  
  877.     if(parent != 0) {
  878.         spline.update(parent->getProjectedPos(), parent->getColour(), projected_pos, col, projected_spos);
  879.     }
  880.  
  881.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  882.         RDirNode* child = *it;
  883.  
  884.         child->calcEdges();
  885.     }
  886. }
  887.  
  888. void RDirNode::logic(float dt) {
  889.  
  890.     //move
  891.     move(dt);
  892.     updateSplinePoint(dt);
  893.  
  894.     //update node normal
  895.     if(parent != 0) {
  896.         node_normal = normalise(pos - parent->getPos());
  897.     }
  898.  
  899.     //update files
  900.      for(std::list<RFile*>::iterator it = files.begin(); it!=files.end(); it++) {
  901.          RFile* f = *it;
  902.  
  903.          f->logic(dt);
  904.      }
  905.  
  906.     //update child nodes
  907.     for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) {
  908.         RDirNode* node = (*it);
  909.  
  910.         node->logic(dt);
  911.     }
  912.  
  913.     //update colour
  914.     calcColour();
  915.  
  916.     //update tickers
  917.     if(visible) since_node_visible += dt;
  918.  
  919.     since_last_file_change += dt;
  920.     since_last_node_change += dt;
  921. }
  922.  
  923. void RDirNode::drawDirName(FXFont& dirfont) const{
  924.     if(parent==0) return;
  925.     if(gGourceSettings.hide_dirnames) return;
  926.     if(gGourceSettings.dir_name_depth > 0 && gGourceSettings.dir_name_depth < (depth-1)) return;
  927.  
  928.     if(!gGourceSettings.highlight_dirs && since_last_node_change > 5.0) return;
  929.  
  930.     float alpha = gGourceSettings.highlight_dirs ? 1.0 : std::max(0.0f, 5.0f - since_last_node_change) / 5.0f;
  931.  
  932.     vec2 mid = spline.getMidPoint();
  933.  
  934.     dirfont.setAlpha(alpha);
  935.     dirfont.draw(mid.x, mid.y, path_token);
  936. }
  937.  
  938. void RDirNode::calcScreenPos(GLint* viewport, GLdouble* modelview, GLdouble* projection) {
  939.  
  940.     static GLdouble screen_x, screen_y, screen_z;
  941.  
  942.     gluProject( pos.x, pos.y, 0.0f, modelview, projection, viewport, &screen_x, &screen_y, &screen_z);
  943.     screen_y = (float)viewport[3] - screen_y;
  944.     projected_pos.x = screen_x;
  945.     projected_pos.y = screen_y;
  946.  
  947.     gluProject( spos.x, spos.y, 0.0f, modelview, projection, viewport, &screen_x, &screen_y, &screen_z);
  948.     screen_y = (float)viewport[3] - screen_y;
  949.     projected_spos.x = screen_x;
  950.     projected_spos.y = screen_y;
  951.  
  952.     static vec2 selected_offset(5.5f, -2.0f);
  953.     static vec2 unselected_offset(5.5f, -1.0f);
  954.  
  955.     if(!gGourceSettings.hide_filenames) {
  956.  
  957.         //first pass - calculate positions of names
  958.         for(std::list<RFile*>::const_iterator it = files.begin(); it!=files.end(); it++) {
  959.             RFile* f = *it;
  960.             f->calcScreenPos(viewport, modelview, projection);
  961.         }
  962.     }
  963.  
  964.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  965.         RDirNode* node = (*it);
  966.         node->calcScreenPos(viewport, modelview, projection);
  967.     }
  968. }
  969.  
  970. void RDirNode::drawNames(FXFont& dirfont) {
  971.  
  972.     if(!gGourceSettings.hide_dirnames && isVisible()) {
  973.         drawDirName(dirfont);
  974.     }
  975.  
  976.     if(!gGourceSettings.hide_filenames) {
  977.  
  978.         if(!(gGourceSettings.hide_filenames || gGourceSettings.hide_files) && in_frustum) {
  979.             for(std::list<RFile*>::const_iterator it = files.begin(); it!=files.end(); it++) {
  980.                 RFile* f = *it;
  981.                 if(!f->isSelected()) f->drawName();
  982.             }
  983.         }
  984.  
  985.     }
  986.  
  987.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  988.         RDirNode* node = (*it);
  989.         node->drawNames(dirfont);
  990.     }
  991. }
  992.  
  993. void RDirNode::checkFrustum(const Frustum& frustum) {
  994.  
  995.     in_frustum = frustum.intersects(quadItemBounds);
  996.  
  997.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  998.         RDirNode* node = (*it);
  999.         node->checkFrustum(frustum);
  1000.     }
  1001. }
  1002.  
  1003. void RDirNode::drawShadows(float dt) const{
  1004.  
  1005.     if(in_frustum) {
  1006.  
  1007.         glPushMatrix();
  1008.         glTranslatef(pos.x, pos.y, 0.0);
  1009.  
  1010.         //draw files
  1011.         for(std::list<RFile*>::const_iterator it = files.begin(); it!=files.end(); it++) {
  1012.             RFile* f = *it;
  1013.             if(f->isHidden()) continue;
  1014.  
  1015.             f->drawShadow(dt);
  1016.         }
  1017.  
  1018.         glPopMatrix();
  1019.     }
  1020.  
  1021.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  1022.         RDirNode* node = (*it);
  1023.         node->drawShadows(dt);
  1024.     }
  1025. }
  1026.  
  1027. void RDirNode::updateFilesVBO(quadbuf& buffer, float dt) const{
  1028.  
  1029.     if(in_frustum) {
  1030.  
  1031.         for(std::list<RFile*>::const_iterator it = files.begin(); it!=files.end(); it++) {
  1032.             RFile* f = *it;
  1033.  
  1034.             if(f->isHidden()) continue;
  1035.  
  1036.             vec3 col   = f->getColour();
  1037.             float alpha = f->getAlpha();
  1038.  
  1039.             buffer.add(f->graphic->textureid, f->getAbsolutePos() - f->dims*0.5f, f->dims, vec4(col.x, col.y, col.z, alpha));
  1040.         }
  1041.     }
  1042.  
  1043.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  1044.         RDirNode* node = (*it);
  1045.         node->updateFilesVBO(buffer,dt);
  1046.     }
  1047. }
  1048.  
  1049. void RDirNode::updateBloomVBO(bloombuf& buffer, float dt) {
  1050.  
  1051.     if(in_frustum && isVisible()) {
  1052.  
  1053.         float bloom_radius   = dir_radius * 2.0 * gGourceSettings.bloom_multiplier;
  1054.         float bloom_diameter = bloom_radius * 2.0;
  1055.         vec4 bloom_col      = col * gGourceSettings.bloom_intensity;
  1056.  
  1057.         vec4 bloom_texcoords(bloom_radius, pos.x, pos.y, 0.0f);
  1058.  
  1059.         vec2 bloom_dims(bloom_diameter, bloom_diameter);
  1060.  
  1061.         buffer.add(0, pos - bloom_dims*0.5f,bloom_dims, vec4(bloom_col.x, bloom_col.y, bloom_col.z, 1.0f), bloom_texcoords);
  1062.     }
  1063.  
  1064.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  1065.         RDirNode* node = (*it);
  1066.         node->updateBloomVBO(buffer,dt);
  1067.     }
  1068. }
  1069.  
  1070. void RDirNode::drawFiles(float dt) const{
  1071.  
  1072.     if(in_frustum) {
  1073.         glPushMatrix();
  1074.             glTranslatef(pos.x, pos.y, 0.0);
  1075.  
  1076.             //draw files
  1077.  
  1078.             for(std::list<RFile*>::const_iterator it = files.begin(); it!=files.end(); it++) {
  1079.                 RFile* f = *it;
  1080.                 if(f->isHidden()) continue;
  1081.  
  1082.                 f->draw(dt);
  1083.             }
  1084.  
  1085.         glPopMatrix();
  1086.     }
  1087.  
  1088.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  1089.         RDirNode* node = (*it);
  1090.         node->drawFiles(dt);
  1091.     }
  1092. }
  1093.  
  1094. const vec2 & RDirNode::getSPos() const{
  1095.     return projected_spos;
  1096. }
  1097.  
  1098. const vec2 & RDirNode::getProjectedPos() const{
  1099.     return projected_pos;
  1100. }
  1101.  
  1102. void RDirNode::updateEdgeVBO(quadbuf& buffer) const {
  1103.  
  1104.     if(parent!=0 && (!gGourceSettings.hide_root || parent->parent !=0)) spline.drawToVBO(buffer);
  1105.  
  1106.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  1107.         RDirNode* child = (*it);
  1108.  
  1109.         if(child->isVisible()) {
  1110.             child->updateEdgeVBO(buffer);
  1111.         }
  1112.     }
  1113. }
  1114.  
  1115. void RDirNode::drawEdgeShadows() const{
  1116.  
  1117.     if(parent!=0 && (!gGourceSettings.hide_root || parent->parent !=0)) spline.drawShadow();
  1118.  
  1119.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  1120.         RDirNode* child = (*it);
  1121.  
  1122.         //draw edge - assumes calcEdges() called before hand so spline will exist
  1123.         if(child->isVisible()) {
  1124.            child->drawEdgeShadows();
  1125.         }
  1126.     }
  1127. }
  1128.  
  1129. void RDirNode::drawEdges() const{
  1130.  
  1131.    if(parent!=0 && (!gGourceSettings.hide_root || parent->parent !=0)) spline.draw();
  1132.  
  1133.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  1134.         RDirNode* child = (*it);
  1135.  
  1136.         //draw edge - assumes calcEdges() called before hand so spline will exist
  1137.         if(child->isVisible()) {
  1138.            child->drawEdges();
  1139.         }
  1140.     }
  1141. }
  1142.  
  1143. void RDirNode::drawBloom(float dt){
  1144.  
  1145.     if(in_frustum && isVisible()) {
  1146.  
  1147.         float bloom_radius = dir_radius * 2.0 * gGourceSettings.bloom_multiplier;
  1148.  
  1149.         vec4 bloom_col = col * gGourceSettings.bloom_intensity;
  1150.  
  1151.         glColor4f(bloom_col.x, bloom_col.y, bloom_col.z, 1.0);
  1152.  
  1153.         glPushMatrix();
  1154.             glTranslatef(pos.x, pos.y, 0.0);
  1155.  
  1156.             glBegin(GL_QUADS);
  1157.                 glTexCoord2f(1.0f, 1.0f);
  1158.                 glVertex2f(bloom_radius,bloom_radius);
  1159.                 glTexCoord2f(1.0f, 0.0f);
  1160.                 glVertex2f(bloom_radius,-bloom_radius);
  1161.                 glTexCoord2f(0.0f, 0.0f);
  1162.                 glVertex2f(-bloom_radius,-bloom_radius);
  1163.                 glTexCoord2f(0.0f, 1.0f);
  1164.                 glVertex2f(-bloom_radius,bloom_radius);
  1165.             glEnd();
  1166.         glPopMatrix();
  1167.     }
  1168.  
  1169.     for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) {
  1170.         RDirNode* node = (*it);
  1171.         node->drawBloom(dt);
  1172.     }
  1173. }
  1174.  
  1175. void RDirNode::updateQuadItemBounds() {
  1176.     float radius = getRadius();
  1177.  
  1178.     vec2 radoffset(radius, radius);
  1179.  
  1180.     //set bounds
  1181.     quadItemBounds.set(pos - radoffset, pos + radoffset);
  1182. }
  1183.  
  1184.  
downloaddirnode.cpp Source code - Download Gource Source code
Related Source Codes/Software:
FDFullscreenPopGesture - A UINavigationController's category to enable full... 2017-01-10
node-style-guide - A guide for styling your node.js / JavaScript code... 2017-01-09
ImageOptim - GUI image optimizer for Mac htt... 2017-01-09
falcon - Falcon is a low-level, high-performance Python fra... 2017-01-09
prerender - Node server that uses phantomjs to render a javasc... 2017-01-09
che - Eclipse Che: Next-generation Eclipse IDE. Open sou... 2017-01-10
notepad-plus-plus - Notepad++ official repository h... 2017-01-10
waterline - An adapter-based ORM for Node.js with support for ... 2017-01-10
Workerman - An asynchronous event driven PHP framework for eas... 2017-01-10
structor - An advanced visual editor for React components ... 2017-01-10
vimr - Project VimR - Refined Neovim experience for macOS... 2017-02-19
vue-admin - Vue Admin Panel Framework, Powered by Vue 2.0 and ... 2017-02-19
dev-setup - Mac OS X development environment setup: Easy-to-un... 2017-02-19
CMPopTipView - Custom UIView for iOS that pops up an animated "bu... 2017-02-19
git-recipes - Git for recipes in Chinese. The high quality of Gi... 2017-02-19
CLNDR - 2017-02-19
OptiKey - OptiKey - Full computer control and speech with yo... 2017-02-19
MRProgress - Collection of iOS drop-in components to visualize ... 2017-02-19
BGARefreshLayout-Android - On a variety of drop-down refresh effect, loading ... 2017-02-19
angular-http-auth - 2017-02-19

 Back to top