From 62204f576a134dcb695bc6e6fd7e1a9593a3558e Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 1 Oct 2014 14:08:51 +0200 Subject: [PATCH 01/54] Create an empty tmplog file and set up the necessary folders. --- src/MainScreen.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/MainScreen.lua b/src/MainScreen.lua index cdb0db7..14733c0 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -41,6 +41,10 @@ function MainScreen.new() end function self:init() + -- Create empty file to also set up the löve save folder. + love.filesystem.newFile('tmplog.txt', 'w'):close(); + + -- Write the git log to the tmp file. writeLog(); log = FileHandler.loadFile('tmplog.txt'); From 22679510c1fb8cc4b30e090b94602645d82aa9e8 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 1 Oct 2014 14:14:14 +0200 Subject: [PATCH 02/54] Exclude date and author information from being displayed as a file. --- src/MainScreen.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/MainScreen.lua b/src/MainScreen.lua index 14733c0..08de2f5 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -35,8 +35,11 @@ function MainScreen.new() curCommit = curCommit + 1; for i = 1, #commits[curCommit] do local line = commits[curCommit][i]; - files[line] = files[line] or 1; - files[line] = files[line] + 1; + + if not line:find('author') and not line:find('date') then + files[line] = files[line] or 1; + files[line] = files[line] + 1; + end end end From 9cbb6a4c7d97d8614ad575bb8757bbd8cd41d8c2 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 1 Oct 2014 14:16:49 +0200 Subject: [PATCH 03/54] Show date and time of the commit currently added to the display. --- src/MainScreen.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/MainScreen.lua b/src/MainScreen.lua index 08de2f5..41c3886 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -18,12 +18,13 @@ function MainScreen.new() local commits; local curCommit = 0; local files = {}; + local curDate = ''; local function writeLog() -- Write the git log to love's save directory. os.execute([[ cd love - git log --reverse --date=short --pretty=format:'author: %an%ndate: %ad%n' --name-only > /Users/Robert//Library/Application\ Support/LOVE/rmcode_LoGiVi/tmpLog.txt + git log --reverse --date=iso --pretty=format:'author: %an%ndate: %ad%n' --name-only > /Users/Robert//Library/Application\ Support/LOVE/rmcode_LoGiVi/tmpLog.txt ]]); end @@ -36,6 +37,9 @@ function MainScreen.new() for i = 1, #commits[curCommit] do local line = commits[curCommit][i]; + if line:find('date') then + curDate = line; + end if not line:find('author') and not line:find('date') then files[line] = files[line] or 1; files[line] = files[line] + 1; @@ -56,6 +60,7 @@ function MainScreen.new() local posX, posY; function self:draw() + love.graphics.print(curDate, 20, 20); posX, posY = 40, 40; for i, v in pairs(files) do posX, posY = posX + 40, posY + 40; From 1c86b323cb744ac89db04fc9f1712aa83bbd87e4 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 1 Oct 2014 14:29:06 +0200 Subject: [PATCH 04/54] Load repository from the love save folder. --- src/MainScreen.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MainScreen.lua b/src/MainScreen.lua index 41c3886..bf0ab3b 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -23,9 +23,9 @@ function MainScreen.new() local function writeLog() -- Write the git log to love's save directory. os.execute([[ - cd love - git log --reverse --date=iso --pretty=format:'author: %an%ndate: %ad%n' --name-only > /Users/Robert//Library/Application\ Support/LOVE/rmcode_LoGiVi/tmpLog.txt - ]]); + cd /Users/Robert//Library/Application\ Support/LOVE/rmcode_LoGiVi/ + git log --reverse --date=iso --pretty=format:'author: %an%ndate: %ad%n' --name-only > /Users/Robert//Library/Application\ Support/LOVE/rmcode_LoGiVi/tmpLog.txt + ]]); end local function nextCommit() From 0a6a2f2f380187f5f8894b04b0b9af9bd75a896e Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 1 Oct 2014 14:43:26 +0200 Subject: [PATCH 05/54] Files are handled as separate objects. Right now they are simply listed on the screen. We use a real .png image instead of love.graphics.circle(...) to draw them. --- res/fileNode.png | Bin 0 -> 1271 bytes src/FileObject.lua | 42 ++++++++++++++++++++++++++++++++++++++++++ src/MainScreen.lua | 26 +++++++++++++++++--------- 3 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 res/fileNode.png create mode 100644 src/FileObject.lua diff --git a/res/fileNode.png b/res/fileNode.png new file mode 100644 index 0000000000000000000000000000000000000000..5b456d3d541eb2d8578d94fd609d561892f8730b GIT binary patch literal 1271 zcmV4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER0001vNklbqHBc70RTX%MY)SyO=SQ8002ovPDHLkV1kdQQZfJl literal 0 HcmV?d00001 diff --git a/src/FileObject.lua b/src/FileObject.lua new file mode 100644 index 0000000..0301ae8 --- /dev/null +++ b/src/FileObject.lua @@ -0,0 +1,42 @@ +-- ------------------------------------------------ +-- Module +-- ------------------------------------------------ + +local FileObject = {}; + +-- ------------------------------------------------ +-- Local Variables +-- ------------------------------------------------ + +local img = love.graphics.newImage('res/fileNode.png'); + +-- ------------------------------------------------ +-- Constructor +-- ------------------------------------------------ + +function FileObject.new(name, x, y) + local self = {}; + + local posX, posY = x, y; + + function self:draw() + love.graphics.draw(img, posX, posY); + -- love.graphics.rectangle('line', posX, posY, 16, 16); + love.graphics.print(name, posX + 20, posY); + end + + function self:update(dt) + end + + return self; +end + +-- ------------------------------------------------ +-- Return Module +-- ------------------------------------------------ + +return FileObject; + +--================================================================================================== +-- Created 01.10.14 - 14:41 = +--================================================================================================== \ No newline at end of file diff --git a/src/MainScreen.lua b/src/MainScreen.lua index bf0ab3b..db7ac33 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -1,5 +1,6 @@ local Screen = require('lib/Screen'); local FileHandler = require('src/FileHandler'); +local FileObject = require('src/FileObject'); -- ------------------------------------------------ -- Module @@ -19,6 +20,7 @@ function MainScreen.new() local curCommit = 0; local files = {}; local curDate = ''; + local ww, wh = love.window.getDimensions(); local function writeLog() -- Write the git log to love's save directory. @@ -28,6 +30,8 @@ function MainScreen.new() ]]); end + local spawnX = 20; + local spawnY = 40; local function nextCommit() if curCommit == #commits then return; @@ -40,9 +44,13 @@ function MainScreen.new() if line:find('date') then curDate = line; end - if not line:find('author') and not line:find('date') then - files[line] = files[line] or 1; - files[line] = files[line] + 1; + if not line:find('author') and not line:find('date') and not files[line] then + spawnY = spawnY + 15; + if spawnY > wh - 30 then + spawnY = 55; + spawnX = spawnX + 400; + end + files[line] = FileObject.new(line, spawnX, spawnY); end end end @@ -58,14 +66,10 @@ function MainScreen.new() commits = FileHandler.splitCommits(log); end - local posX, posY; function self:draw() love.graphics.print(curDate, 20, 20); - posX, posY = 40, 40; - for i, v in pairs(files) do - posX, posY = posX + 40, posY + 40; - love.graphics.circle('fill', posX, posY, v * 5); - love.graphics.print(i, posX + 200, posY); + for _, file in pairs(files) do + file:draw() end end @@ -76,6 +80,10 @@ function MainScreen.new() nextCommit(); timer = 0; end + + for _, file in pairs(files) do + file:update(dt) + end end return self; From 469509d290849d5c50999ed5ac92eb092743eaca Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 2 Oct 2014 16:39:18 +0200 Subject: [PATCH 06/54] Instead of generating a git log. We use one created by the user for now. --- src/FileHandler.lua | 10 ++++++---- src/MainScreen.lua | 17 +---------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/FileHandler.lua b/src/FileHandler.lua index 0599d00..e3b2f51 100644 --- a/src/FileHandler.lua +++ b/src/FileHandler.lua @@ -28,12 +28,14 @@ function FileHandler.splitCommits(log) local line = log[i]; -- New commit. - if line:find('author') then + if line:find('commit') then index = index + 1; commits[index] = {}; - end - - if line:len() ~= 0 then + elseif line:find('author') then + commits[index].author = line; + elseif line:find('date') then + commits[index].date = line; + elseif line:len() ~= 0 then commits[index][#commits[index] + 1] = line; end end diff --git a/src/MainScreen.lua b/src/MainScreen.lua index db7ac33..3b14730 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -15,21 +15,12 @@ local MainScreen = {}; function MainScreen.new() local self = Screen.new(); - local log; local commits; local curCommit = 0; local files = {}; local curDate = ''; local ww, wh = love.window.getDimensions(); - local function writeLog() - -- Write the git log to love's save directory. - os.execute([[ - cd /Users/Robert//Library/Application\ Support/LOVE/rmcode_LoGiVi/ - git log --reverse --date=iso --pretty=format:'author: %an%ndate: %ad%n' --name-only > /Users/Robert//Library/Application\ Support/LOVE/rmcode_LoGiVi/tmpLog.txt - ]]); - end - local spawnX = 20; local spawnY = 40; local function nextCommit() @@ -56,13 +47,7 @@ function MainScreen.new() end function self:init() - -- Create empty file to also set up the löve save folder. - love.filesystem.newFile('tmplog.txt', 'w'):close(); - - -- Write the git log to the tmp file. - writeLog(); - - log = FileHandler.loadFile('tmplog.txt'); + local log = FileHandler.loadFile('tmplog.txt'); commits = FileHandler.splitCommits(log); end From 8c9f321a0dab79e5093032fbb8713906abfa6e16 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 2 Oct 2014 17:28:15 +0200 Subject: [PATCH 07/54] Split up file modifiers and the actual filenames and paths. --- src/FileHandler.lua | 13 ++++++++++++- src/MainScreen.lua | 6 +++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/FileHandler.lua b/src/FileHandler.lua index e3b2f51..8ec9678 100644 --- a/src/FileHandler.lua +++ b/src/FileHandler.lua @@ -4,6 +4,14 @@ local FileHandler = {}; +--- +-- Remove leading and trailing whitespace. +-- @param str +-- +local function trim(str) + return str:match("^%s*(.-)%s*$"); +end + --- -- Loads the file and stores it line for line in a lua table. -- @param name @@ -36,7 +44,10 @@ function FileHandler.splitCommits(log) elseif line:find('date') then commits[index].date = line; elseif line:len() ~= 0 then - commits[index][#commits[index] + 1] = line; + local modifier = line:sub(1, 1); + local path = line:sub(2); + path = trim(path); + commits[index][#commits[index] + 1] = { mod = modifier, path = path }; end end diff --git a/src/MainScreen.lua b/src/MainScreen.lua index 3b14730..10e6a8c 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -32,16 +32,16 @@ function MainScreen.new() for i = 1, #commits[curCommit] do local line = commits[curCommit][i]; - if line:find('date') then + if line.path:find('date') then curDate = line; end - if not line:find('author') and not line:find('date') and not files[line] then + if not line.path:find('author') and not line.path:find('date') and not files[line.path] then spawnY = spawnY + 15; if spawnY > wh - 30 then spawnY = 55; spawnX = spawnX + 400; end - files[line] = FileObject.new(line, spawnX, spawnY); + files[line.path] = FileObject.new(line.path, spawnX, spawnY); end end end From 581632cfed8cf58bb2963e8d77e110f56b9961ca Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 2 Oct 2014 16:51:31 +0200 Subject: [PATCH 08/54] From now on the system will use nodes for folders and files. --- res/folderNode.png | Bin 0 -> 1271 bytes src/FileHandler.lua | 3 ++ src/{FileObject.lua => FileNode.lua} | 6 ++-- src/FolderNode.lua | 47 +++++++++++++++++++++++++++ src/MainScreen.lua | 46 +++++++++++++------------- 5 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 res/folderNode.png rename src/{FileObject.lua => FileNode.lua} (93%) create mode 100644 src/FolderNode.lua diff --git a/res/folderNode.png b/res/folderNode.png new file mode 100644 index 0000000000000000000000000000000000000000..3d4422fe610662ce3733f7e7063be279d07bbfda GIT binary patch literal 1271 zcmV4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER0001vNklHJ5QnjCh85t$ETV+g`D z9^d@~rUpz~x^jSNbc0X~0BJ_oh++zm12PEN5V!%vXoeYvYzWu@QZ%C*!UPi_mu4i# zc9>-#uTboQfj3|f!~!ftNr?@NghYxV$eKa=;7J+T5D*(ZPk=On0CGM6@i7bl34#E~ hOAr=>MArzD0{|THMOX+vUJL*L002ovPDHLkV1n_!QUw42 literal 0 HcmV?d00001 diff --git a/src/FileHandler.lua b/src/FileHandler.lua index 8ec9678..e94f526 100644 --- a/src/FileHandler.lua +++ b/src/FileHandler.lua @@ -44,6 +44,9 @@ function FileHandler.splitCommits(log) elseif line:find('date') then commits[index].date = line; elseif line:len() ~= 0 then + -- Split the file information into the modifier, which determines + -- what has happened to the file since the last commit and the actual + -- filepath / name. local modifier = line:sub(1, 1); local path = line:sub(2); path = trim(path); diff --git a/src/FileObject.lua b/src/FileNode.lua similarity index 93% rename from src/FileObject.lua rename to src/FileNode.lua index 0301ae8..8d2de79 100644 --- a/src/FileObject.lua +++ b/src/FileNode.lua @@ -2,7 +2,7 @@ -- Module -- ------------------------------------------------ -local FileObject = {}; +local FileNode = {}; -- ------------------------------------------------ -- Local Variables @@ -14,7 +14,7 @@ local img = love.graphics.newImage('res/fileNode.png'); -- Constructor -- ------------------------------------------------ -function FileObject.new(name, x, y) +function FileNode.new(name, x, y) local self = {}; local posX, posY = x, y; @@ -35,7 +35,7 @@ end -- Return Module -- ------------------------------------------------ -return FileObject; +return FileNode; --================================================================================================== -- Created 01.10.14 - 14:41 = diff --git a/src/FolderNode.lua b/src/FolderNode.lua new file mode 100644 index 0000000..b4ce195 --- /dev/null +++ b/src/FolderNode.lua @@ -0,0 +1,47 @@ +-- ------------------------------------------------ +-- Module +-- ------------------------------------------------ + +local FolderNode = {}; + +-- ------------------------------------------------ +-- Constructor +-- ------------------------------------------------ + +function FolderNode.new() + local self = {}; + + local children = {}; + + function self:draw() + for _, node in pairs(children) do + node:draw(); + end + end + + function self:update(dt) + for _, node in pairs(children) do + node:update(dt); + end + end + + function self:getNode(name) + return children[name]; + end + + function self:append(name, node) + children[name] = node; + end + + return self; +end + +-- ------------------------------------------------ +-- Return Module +-- ------------------------------------------------ + +return FolderNode; + +--================================================================================================== +-- Created 02.10.14 - 16:49 = +--================================================================================================== \ No newline at end of file diff --git a/src/MainScreen.lua b/src/MainScreen.lua index 10e6a8c..a5efbcd 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -1,6 +1,7 @@ local Screen = require('lib/Screen'); local FileHandler = require('src/FileHandler'); -local FileObject = require('src/FileObject'); +local FolderNode = require('src/FolderNode'); +local FileNode = require('src/FileNode'); -- ------------------------------------------------ -- Module @@ -16,32 +17,36 @@ function MainScreen.new() local self = Screen.new(); local commits; - local curCommit = 0; - local files = {}; - local curDate = ''; - local ww, wh = love.window.getDimensions(); + local index = 0; + local root = FolderNode.new(); + local author = ''; + local date = ''; local spawnX = 20; local spawnY = 40; + local function nextCommit() - if curCommit == #commits then + if index == #commits then return; end + index = index + 1; - curCommit = curCommit + 1; - for i = 1, #commits[curCommit] do - local line = commits[curCommit][i]; + author = commits[index].author; + date = commits[index].date; - if line.path:find('date') then - curDate = line; - end - if not line.path:find('author') and not line.path:find('date') and not files[line.path] then + print('==============================================='); + print(author .. '-' .. date); + for i = 1, #commits[index] do + local change = commits[index][i]; + + print(change.mod .. " - " .. change.path); + if not root:getNode(change.path) then spawnY = spawnY + 15; - if spawnY > wh - 30 then + if spawnY > love.graphics.getHeight() - 30 then spawnY = 55; spawnX = spawnX + 400; end - files[line.path] = FileObject.new(line.path, spawnX, spawnY); + root:append(change.path, FileNode.new(change.path, spawnX, spawnY)); end end end @@ -52,10 +57,9 @@ function MainScreen.new() end function self:draw() - love.graphics.print(curDate, 20, 20); - for _, file in pairs(files) do - file:draw() - end + love.graphics.print(date, 20, 20); + love.graphics.print(author, 400, 20); + root:draw(); end local timer = 0; @@ -66,9 +70,7 @@ function MainScreen.new() timer = 0; end - for _, file in pairs(files) do - file:update(dt) - end + root:update(dt); end return self; From 2f0c7b57a04e06c3c4eb5909000c3760cae4a899 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 2 Oct 2014 18:03:42 +0200 Subject: [PATCH 09/54] Split the path in subfolders and create new nodes for those folders. This means that each subfolder is a new node in a tree, starting with the root (the main node in which all folders are contained) and with the lowest folder as the last node. Files are separate node which are appended to the last node of their file path. --- src/FolderNode.lua | 4 ++- src/MainScreen.lua | 73 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/src/FolderNode.lua b/src/FolderNode.lua index b4ce195..a13a5de 100644 --- a/src/FolderNode.lua +++ b/src/FolderNode.lua @@ -30,7 +30,9 @@ function FolderNode.new() end function self:append(name, node) - children[name] = node; + if not children[name] then + children[name] = node; + end end return self; diff --git a/src/MainScreen.lua b/src/MainScreen.lua index a5efbcd..c6de804 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -25,6 +25,57 @@ function MainScreen.new() local spawnX = 20; local spawnY = 40; + --- + -- @param path + -- + local function splitFilePath(path) + local subfolders = {}; + while path:find('/') do + local pos = path:find('/'); + + -- Store the subfolder name. + subfolders[#subfolders + 1] = path:sub(1, pos - 1); + print(subfolders[#subfolders]); + + -- Restart the loop with the path minus the previous folder. + path = path:sub(pos + 1); + end + print(path); + return subfolders, path; + end + + --- + -- @param target + -- @param subfolders + -- + local function createSubFolders(target, subfolders) + for i = 1, #subfolders do + -- Append a new folder node to the parent if there isn't a node + -- for that folder yet. + target:append(subfolders[i], FolderNode.new()); + + -- Make the newly added node the new target. + target = target:getNode(subfolders[i]); + end + -- Return the last node in the tree. + return target; + end + + --- + -- @param target + -- @param file + -- + local function createFileNode(target, file) + if not target:getNode(file) then + spawnY = spawnY + 15; + if spawnY > love.graphics.getHeight() - 30 then + spawnY = 55; + spawnX = spawnX + 400; + end + target:append(file, FileNode.new(file, spawnX, spawnY)); + end + end + local function nextCommit() if index == #commits then return; @@ -37,17 +88,21 @@ function MainScreen.new() print('==============================================='); print(author .. '-' .. date); for i = 1, #commits[index] do - local change = commits[index][i]; + print('-----------------------------------------------'); + local change = commits[index][i]; print(change.mod .. " - " .. change.path); - if not root:getNode(change.path) then - spawnY = spawnY + 15; - if spawnY > love.graphics.getHeight() - 30 then - spawnY = 55; - spawnX = spawnX + 400; - end - root:append(change.path, FileNode.new(change.path, spawnX, spawnY)); - end + + -- Split up the file path into subfolders. + local subfolders, file = splitFilePath(change.path); + + -- Create sub folders if necessary and return the bottom + -- most node of that file path, to which we will append the + -- actual file. + local target = createSubFolders(root, subfolders); + + -- Create the file node at the bottom of the current path tree. + createFileNode(target, file); end end From a4b65fe4f95cad620a31b2452701c21aa1d6c91b Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 2 Oct 2014 18:23:14 +0200 Subject: [PATCH 10/54] Add files based on modifier and not based on wether they already exist. They can't exist if the modifier is 'A' since that's literally the first time the file CAN exist. --- src/FileHandler.lua | 2 +- src/MainScreen.lua | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/FileHandler.lua b/src/FileHandler.lua index e94f526..d324854 100644 --- a/src/FileHandler.lua +++ b/src/FileHandler.lua @@ -50,7 +50,7 @@ function FileHandler.splitCommits(log) local modifier = line:sub(1, 1); local path = line:sub(2); path = trim(path); - commits[index][#commits[index] + 1] = { mod = modifier, path = path }; + commits[index][#commits[index] + 1] = { modifier = modifier, path = path }; end end diff --git a/src/MainScreen.lua b/src/MainScreen.lua index c6de804..6c37ad7 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -63,16 +63,16 @@ function MainScreen.new() --- -- @param target - -- @param file + -- @param fileName -- - local function createFileNode(target, file) - if not target:getNode(file) then + local function modifyFileNodes(target, fileName, modifier) + if modifier == 'A' then -- Add file spawnY = spawnY + 15; if spawnY > love.graphics.getHeight() - 30 then spawnY = 55; spawnX = spawnX + 400; end - target:append(file, FileNode.new(file, spawnX, spawnY)); + target:append(fileName, FileNode.new(fileName, spawnX, spawnY)); end end @@ -91,7 +91,7 @@ function MainScreen.new() print('-----------------------------------------------'); local change = commits[index][i]; - print(change.mod .. " - " .. change.path); + print(change.modifier .. " - " .. change.path); -- Split up the file path into subfolders. local subfolders, file = splitFilePath(change.path); @@ -102,7 +102,7 @@ function MainScreen.new() local target = createSubFolders(root, subfolders); -- Create the file node at the bottom of the current path tree. - createFileNode(target, file); + modifyFileNodes(target, file, change.modifier); end end From c06837918c3e8bb5fdcfc4c6794e85bab6426870 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 3 Oct 2014 02:35:43 +0200 Subject: [PATCH 11/54] Improve visualization of file and folder nodes. File nodes are placed on a circle around their parent nodes. Folder nodes are connected to their parents via lines. --- src/FileNode.lua | 23 ++++++++++++++++------ src/FolderNode.lua | 48 ++++++++++++++++++++++++++++++++++++++++++++-- src/MainScreen.lua | 25 ++++++------------------ 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/src/FileNode.lua b/src/FileNode.lua index 8d2de79..68be7a7 100644 --- a/src/FileNode.lua +++ b/src/FileNode.lua @@ -14,18 +14,29 @@ local img = love.graphics.newImage('res/fileNode.png'); -- Constructor -- ------------------------------------------------ -function FileNode.new(name, x, y) +function FileNode.new(name) local self = {}; - local posX, posY = x, y; + local x, y; + local r; function self:draw() - love.graphics.draw(img, posX, posY); - -- love.graphics.rectangle('line', posX, posY, 16, 16); - love.graphics.print(name, posX + 20, posY); + if x and y then + love.graphics.draw(img, x - 8, y - 8); + -- love.graphics.rectangle('line', posX, posY, 16, 16); + -- love.graphics.print(name, x, y); + end end - function self:update(dt) + function self:update(dt) end + + function self:setPosition(px, py, r, an) + x = px + r * math.cos(math.rad(an)); + y = py + r * math.sin(math.rad(an)); + end + + function self:getType() + return 'file'; end return self; diff --git a/src/FolderNode.lua b/src/FolderNode.lua index a13a5de..135008b 100644 --- a/src/FolderNode.lua +++ b/src/FolderNode.lua @@ -4,19 +4,36 @@ local FolderNode = {}; +-- ------------------------------------------------ +-- Local Variables +-- ------------------------------------------------ + +local img = love.graphics.newImage('res/folderNode.png'); + -- ------------------------------------------------ -- Constructor -- ------------------------------------------------ -function FolderNode.new() +function FolderNode.new(name) local self = {}; + local x, y = love.math.random(60, 1200), love.math.random(60, 700); local children = {}; + local amountOfChildren = 0; function self:draw() + love.graphics.circle('line', x, y, 40); + -- love.graphics.print(name, x + 20, y); + for _, node in pairs(children) do - node:draw(); + if node:getType() == 'folder' then + love.graphics.line(x, y, node:getX(), node:getY()); + node:draw(); + else + node:draw(); + end end + love.graphics.draw(img, x - 8, y - 8); end function self:update(dt) @@ -32,9 +49,36 @@ function FolderNode.new() function self:append(name, node) if not children[name] then children[name] = node; + if children[name]:getType() == 'file' then + children[name]:setPosition(x, y, 40, amountOfChildren * 40); + else + children[name]:setPosition(x, y, 200, amountOfChildren * 40); + end + amountOfChildren = amountOfChildren + 1; + end + end + + function self:getType() + return 'folder'; + end + + function self:setPosition(px, py, r, an) + if not r and not an then + x, y = px, py; + else + x = px + r * math.cos(math.rad(an)); + y = py + r * math.sin(math.rad(an)); end end + function self:getX() + return x; + end + + function self:getY() + return y; + end + return self; end diff --git a/src/MainScreen.lua b/src/MainScreen.lua index 6c37ad7..fc87393 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -18,13 +18,10 @@ function MainScreen.new() local commits; local index = 0; - local root = FolderNode.new(); + local root = FolderNode.new('root'); local author = ''; local date = ''; - local spawnX = 20; - local spawnY = 40; - --- -- @param path -- @@ -35,12 +32,10 @@ function MainScreen.new() -- Store the subfolder name. subfolders[#subfolders + 1] = path:sub(1, pos - 1); - print(subfolders[#subfolders]); -- Restart the loop with the path minus the previous folder. path = path:sub(pos + 1); end - print(path); return subfolders, path; end @@ -52,7 +47,7 @@ function MainScreen.new() for i = 1, #subfolders do -- Append a new folder node to the parent if there isn't a node -- for that folder yet. - target:append(subfolders[i], FolderNode.new()); + target:append(subfolders[i], FolderNode.new(subfolders[i])); -- Make the newly added node the new target. target = target:getNode(subfolders[i]); @@ -67,12 +62,7 @@ function MainScreen.new() -- local function modifyFileNodes(target, fileName, modifier) if modifier == 'A' then -- Add file - spawnY = spawnY + 15; - if spawnY > love.graphics.getHeight() - 30 then - spawnY = 55; - spawnX = spawnX + 400; - end - target:append(fileName, FileNode.new(fileName, spawnX, spawnY)); + target:append(fileName, FileNode.new(fileName)); end end @@ -85,13 +75,8 @@ function MainScreen.new() author = commits[index].author; date = commits[index].date; - print('==============================================='); - print(author .. '-' .. date); for i = 1, #commits[index] do - print('-----------------------------------------------'); - local change = commits[index][i]; - print(change.modifier .. " - " .. change.path); -- Split up the file path into subfolders. local subfolders, file = splitFilePath(change.path); @@ -109,6 +94,8 @@ function MainScreen.new() function self:init() local log = FileHandler.loadFile('tmplog.txt'); commits = FileHandler.splitCommits(log); + + root:setPosition(love.graphics.getWidth() * 0.5, love.graphics.getHeight() * 0.5); end function self:draw() @@ -120,7 +107,7 @@ function MainScreen.new() local timer = 0; function self:update(dt) timer = timer + dt; - if timer > 0.5 then + if timer > 0.0 then nextCommit(); timer = 0; end From f0d96179ce256a11f2e6a5dda64df86318562fc9 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 3 Oct 2014 14:21:34 +0200 Subject: [PATCH 12/54] Move nodes to a subfolder. --- src/MainScreen.lua | 4 ++-- src/{ => nodes}/FileNode.lua | 0 src/{ => nodes}/FolderNode.lua | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/{ => nodes}/FileNode.lua (100%) rename src/{ => nodes}/FolderNode.lua (100%) diff --git a/src/MainScreen.lua b/src/MainScreen.lua index fc87393..6cfa3b0 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -1,7 +1,7 @@ local Screen = require('lib/Screen'); local FileHandler = require('src/FileHandler'); -local FolderNode = require('src/FolderNode'); -local FileNode = require('src/FileNode'); +local FolderNode = require('src/nodes/FolderNode'); +local FileNode = require('src/nodes/FileNode'); -- ------------------------------------------------ -- Module diff --git a/src/FileNode.lua b/src/nodes/FileNode.lua similarity index 100% rename from src/FileNode.lua rename to src/nodes/FileNode.lua diff --git a/src/FolderNode.lua b/src/nodes/FolderNode.lua similarity index 100% rename from src/FolderNode.lua rename to src/nodes/FolderNode.lua From bfe6c2033f0d42df91041147e8019ada19a6976e Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 3 Oct 2014 14:27:43 +0200 Subject: [PATCH 13/54] Draw file and folder names and connect files to their parent node. Also removed the debug circle around file nodes. --- src/nodes/FileNode.lua | 10 ++++++++-- src/nodes/FolderNode.lua | 14 ++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/nodes/FileNode.lua b/src/nodes/FileNode.lua index 68be7a7..b6b609e 100644 --- a/src/nodes/FileNode.lua +++ b/src/nodes/FileNode.lua @@ -23,8 +23,7 @@ function FileNode.new(name) function self:draw() if x and y then love.graphics.draw(img, x - 8, y - 8); - -- love.graphics.rectangle('line', posX, posY, 16, 16); - -- love.graphics.print(name, x, y); + love.graphics.print(name, x + 10, y); end end @@ -38,6 +37,13 @@ function FileNode.new(name) function self:getType() return 'file'; end + function self:getX() + return x; + end + + function self:getY() + return y; + end return self; end diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 135008b..dc08a09 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -22,17 +22,11 @@ function FolderNode.new(name) local amountOfChildren = 0; function self:draw() - love.graphics.circle('line', x, y, 40); - -- love.graphics.print(name, x + 20, y); - for _, node in pairs(children) do - if node:getType() == 'folder' then - love.graphics.line(x, y, node:getX(), node:getY()); - node:draw(); - else - node:draw(); - end + love.graphics.line(x, y, node:getX(), node:getY()); + node:draw(); end + love.graphics.print(name, x + 10, y); love.graphics.draw(img, x - 8, y - 8); end @@ -50,7 +44,7 @@ function FolderNode.new(name) if not children[name] then children[name] = node; if children[name]:getType() == 'file' then - children[name]:setPosition(x, y, 40, amountOfChildren * 40); + children[name]:setPosition(x, y, 80, amountOfChildren * 40); else children[name]:setPosition(x, y, 200, amountOfChildren * 40); end From e7d7ee386a6140da593feb8abb885776cc813265 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 3 Oct 2014 14:46:58 +0200 Subject: [PATCH 14/54] Remove file from the tree based on the modifier specified in the commit. --- src/MainScreen.lua | 4 +++- src/nodes/FolderNode.lua | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/MainScreen.lua b/src/MainScreen.lua index 6cfa3b0..f0f2f44 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -63,6 +63,8 @@ function MainScreen.new() local function modifyFileNodes(target, fileName, modifier) if modifier == 'A' then -- Add file target:append(fileName, FileNode.new(fileName)); + elseif modifier == 'D' then + target:remove(fileName); end end @@ -107,7 +109,7 @@ function MainScreen.new() local timer = 0; function self:update(dt) timer = timer + dt; - if timer > 0.0 then + if timer > 0.2 then nextCommit(); timer = 0; end diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index dc08a09..c915573 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -52,6 +52,10 @@ function FolderNode.new(name) end end + function self:remove(name) + children[name] = nil; + end + function self:getType() return 'folder'; end From e243ceb463dc9a04e0f4c4ffa87c6d526fdb39cd Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 16 Oct 2014 11:36:21 +0200 Subject: [PATCH 15/54] Distribute files evenly on a circle around their parent node. --- src/nodes/FileNode.lua | 8 +++---- src/nodes/FolderNode.lua | 45 +++++++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/nodes/FileNode.lua b/src/nodes/FileNode.lua index b6b609e..9c6e0b2 100644 --- a/src/nodes/FileNode.lua +++ b/src/nodes/FileNode.lua @@ -23,20 +23,20 @@ function FileNode.new(name) function self:draw() if x and y then love.graphics.draw(img, x - 8, y - 8); - love.graphics.print(name, x + 10, y); + -- love.graphics.print(name, x + 10, y); end end function self:update(dt) end - function self:setPosition(px, py, r, an) - x = px + r * math.cos(math.rad(an)); - y = py + r * math.sin(math.rad(an)); + function self:setPosition(nx, ny) + x, y = nx, ny; end function self:getType() return 'file'; end + function self:getX() return x; end diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index c915573..05b6503 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -17,17 +17,33 @@ local img = love.graphics.newImage('res/folderNode.png'); function FolderNode.new(name) local self = {}; - local x, y = love.math.random(60, 1200), love.math.random(60, 700); + local px, py = love.math.random(60, 1200), love.math.random(60, 700); local children = {}; - local amountOfChildren = 0; + + local function plotCircle(children, radius) + local count = 0; + for _, _ in pairs(children) do + count = count + 1; + end + + local angle = 360 / count; + + count = 0; + for i, node in pairs(children) do + count = count + 1; + local x = (radius * math.cos((angle * (count - 1)) * (math.pi / 180))); + local y = (radius * math.sin((angle * (count - 1)) * (math.pi / 180))); + node:setPosition(x + px , y + py); + end + end function self:draw() for _, node in pairs(children) do - love.graphics.line(x, y, node:getX(), node:getY()); + love.graphics.line(px, py, node:getX(), node:getY()); node:draw(); end - love.graphics.print(name, x + 10, y); - love.graphics.draw(img, x - 8, y - 8); + love.graphics.print(name, px + 10, py); + love.graphics.draw(img, px - 8, py - 8); end function self:update(dt) @@ -43,12 +59,7 @@ function FolderNode.new(name) function self:append(name, node) if not children[name] then children[name] = node; - if children[name]:getType() == 'file' then - children[name]:setPosition(x, y, 80, amountOfChildren * 40); - else - children[name]:setPosition(x, y, 200, amountOfChildren * 40); - end - amountOfChildren = amountOfChildren + 1; + plotCircle(children, 50); end end @@ -60,21 +71,21 @@ function FolderNode.new(name) return 'folder'; end - function self:setPosition(px, py, r, an) + function self:setPosition(nx, ny, r, an) if not r and not an then - x, y = px, py; + px, py = px, py; else - x = px + r * math.cos(math.rad(an)); - y = py + r * math.sin(math.rad(an)); + px = px + r * math.cos(math.rad(an)); + py = py + r * math.sin(math.rad(an)); end end function self:getX() - return x; + return px; end function self:getY() - return y; + return py; end return self; From bb33781fa8d48c9ffb717438b3cfa063015b25d8 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 16 Oct 2014 16:30:10 +0200 Subject: [PATCH 16/54] Folders are are excluded from being placed around their parent node. Also added a node class from which the file and folder nodes inherit. --- src/nodes/FileNode.lua | 30 +++------------- src/nodes/FolderNode.lua | 77 +++++++++++++++++++++------------------- src/nodes/Node.lua | 51 ++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 62 deletions(-) create mode 100644 src/nodes/Node.lua diff --git a/src/nodes/FileNode.lua b/src/nodes/FileNode.lua index 9c6e0b2..dbaf82c 100644 --- a/src/nodes/FileNode.lua +++ b/src/nodes/FileNode.lua @@ -1,3 +1,5 @@ +local Node = require('src/nodes/Node'); + -- ------------------------------------------------ -- Module -- ------------------------------------------------ @@ -15,34 +17,10 @@ local img = love.graphics.newImage('res/fileNode.png'); -- ------------------------------------------------ function FileNode.new(name) - local self = {}; - - local x, y; - local r; + local self = Node.new('file', name); function self:draw() - if x and y then - love.graphics.draw(img, x - 8, y - 8); - -- love.graphics.print(name, x + 10, y); - end - end - - function self:update(dt) end - - function self:setPosition(nx, ny) - x, y = nx, ny; - end - - function self:getType() - return 'file'; - end - - function self:getX() - return x; - end - - function self:getY() - return y; + love.graphics.draw(img, self:getX() - 8, self:getY() - 8); end return self; diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 05b6503..c504f87 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -1,3 +1,5 @@ +local Node = require('src/nodes/Node'); + -- ------------------------------------------------ -- Module -- ------------------------------------------------ @@ -15,35 +17,59 @@ local img = love.graphics.newImage('res/folderNode.png'); -- ------------------------------------------------ function FolderNode.new(name) - local self = {}; + local self = Node.new('folder', name); - local px, py = love.math.random(60, 1200), love.math.random(60, 700); local children = {}; - local function plotCircle(children, radius) + --- + -- Counts the amount of children nodes that represent files. + -- + -- @param children + -- + local function countFileNodes(children) local count = 0; - for _, _ in pairs(children) do - count = count + 1; + for _, node in pairs(children) do + if node:getType() == 'file' then + count = count + 1; + end end + return count; + end - local angle = 360 / count; + --- + -- Distributes files nodes evenly on a circle around the parent node. + -- @param children + -- @param radius + -- + -- TODO radius based on amount of files? + -- TODO multiple circles if they get too big + local function plotCircle(children, radius) + local angle = 360 / countFileNodes(children); - count = 0; - for i, node in pairs(children) do - count = count + 1; - local x = (radius * math.cos((angle * (count - 1)) * (math.pi / 180))); - local y = (radius * math.sin((angle * (count - 1)) * (math.pi / 180))); - node:setPosition(x + px , y + py); + local count = 0; + for _, node in pairs(children) do + if node:getType() == 'file' then + count = count + 1; + local x = (radius * math.cos((angle * (count - 1)) * (math.pi / 180))); + local y = (radius * math.sin((angle * (count - 1)) * (math.pi / 180))); + node:setPosition(x + self:getX(), y + self:getY()); + elseif not node:getX() or not node:getY() then + node:setPosition(love.math.random(60, 1200), love.math.random(60, 700)); + end end end function self:draw() for _, node in pairs(children) do - love.graphics.line(px, py, node:getX(), node:getY()); + if node:getType() == 'folder' then + love.graphics.setColor(50, 50, 50); + love.graphics.line(self:getX(), self:getY(), node:getX(), node:getY()); + love.graphics.setColor(255, 255, 255); + end node:draw(); end - love.graphics.print(name, px + 10, py); - love.graphics.draw(img, px - 8, py - 8); + love.graphics.print(name, self:getX() + 10, self:getY()); + love.graphics.draw(img, self:getX() - 8, self:getY() - 8); end function self:update(dt) @@ -67,27 +93,6 @@ function FolderNode.new(name) children[name] = nil; end - function self:getType() - return 'folder'; - end - - function self:setPosition(nx, ny, r, an) - if not r and not an then - px, py = px, py; - else - px = px + r * math.cos(math.rad(an)); - py = py + r * math.sin(math.rad(an)); - end - end - - function self:getX() - return px; - end - - function self:getY() - return py; - end - return self; end diff --git a/src/nodes/Node.lua b/src/nodes/Node.lua new file mode 100644 index 0000000..99bfed1 --- /dev/null +++ b/src/nodes/Node.lua @@ -0,0 +1,51 @@ +-- ------------------------------------------------ +-- Module +-- ------------------------------------------------ + +local Node = {}; + +-- ------------------------------------------------ +-- Constructor +-- ------------------------------------------------ + +function Node.new(type, name, x, y) + local self = {}; + + local x, y = x, y; + + function self:update(dt) end + + function self:draw() end + + function self:setPosition(nx, ny) + x, y = nx, ny; + end + + function self:getX() + return x; + end + + function self:getY() + return y; + end + + function self:getName() + return name; + end + + function self:getType() + return type; + end + + return self; +end + +-- ------------------------------------------------ +-- Return Module +-- ------------------------------------------------ + +return Node; + +--================================================================================================== +-- Created 16.10.14 - 14:47 = +--================================================================================================== \ No newline at end of file From 8ca8dda5a1daabc2bcb3851e923016eb1820c464 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 17 Oct 2014 13:13:16 +0200 Subject: [PATCH 17/54] Increase dist to parent node when the dist between nodes gets to small. --- src/nodes/FolderNode.lua | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index c504f87..14cf2d4 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -36,6 +36,10 @@ function FolderNode.new(name) return count; end + local function calcArc(radius, angle) + return math.pi * radius * (angle / 180); + end + --- -- Distributes files nodes evenly on a circle around the parent node. -- @param children @@ -43,10 +47,18 @@ function FolderNode.new(name) -- -- TODO radius based on amount of files? -- TODO multiple circles if they get too big - local function plotCircle(children, radius) + local function plotCircle(children) local angle = 360 / countFileNodes(children); local count = 0; + local radius = 15; + local arc = calcArc(radius, angle); + + while arc < 20 do + radius = radius * 2; + arc = calcArc(radius, angle); + end + for _, node in pairs(children) do if node:getType() == 'file' then count = count + 1; @@ -85,7 +97,7 @@ function FolderNode.new(name) function self:append(name, node) if not children[name] then children[name] = node; - plotCircle(children, 50); + plotCircle(children); end end From 4c28463c4668bfce624eff2ffb72d582a18c8d60 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sat, 18 Oct 2014 16:08:36 +0200 Subject: [PATCH 18/54] Add debug information (FPS, frametime, memory). --- main.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.lua b/main.lua index 28bbca8..c746cff 100644 --- a/main.lua +++ b/main.lua @@ -7,6 +7,10 @@ end function love.draw() ScreenManager.draw(); + + love.graphics.print(string.format("FT: %.3f ms", 1000 * love.timer.getAverageDelta()), 10, love.window.getHeight() - 60); + love.graphics.print(string.format("FPS: %.3f fps", love.timer.getFPS()), 10, love.window.getHeight() - 40); + love.graphics.print(string.format("MEM: %.3f kb", collectgarbage("count")), 10, love.window.getHeight() - 20); end function love.update(dt) From 6008ef3b0bc46c544e1b21d48481dc6580cc616c Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sat, 18 Oct 2014 17:47:49 +0200 Subject: [PATCH 19/54] Remove empty folders from graph. --- src/nodes/FolderNode.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 14cf2d4..4ec1d4f 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -85,7 +85,10 @@ function FolderNode.new(name) end function self:update(dt) - for _, node in pairs(children) do + for name, node in pairs(children) do + if node:getType() == 'folder' and node:getChildrenCount() == 0 then + children[name] = nil; + end node:update(dt); end end @@ -105,6 +108,14 @@ function FolderNode.new(name) children[name] = nil; end + function self:getChildrenCount() + local count = 0; + for _, _ in pairs(children) do + count = count + 1; + end + return count; + end + return self; end From 5858b46632194518bd486f09080194c77f05ad24 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sat, 18 Oct 2014 15:41:05 +0200 Subject: [PATCH 20/54] Folder nodes are now affected by physics. Folder nodes collide with and repel each other. There are still issues with the placement especially when a rope joint prevents a node from moving farther away, but it still gets pushed by other nodes. --- src/MainScreen.lua | 14 +++++--- src/nodes/FolderNode.lua | 76 +++++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/MainScreen.lua b/src/MainScreen.lua index f0f2f44..0cd017c 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -17,10 +17,11 @@ function MainScreen.new() local self = Screen.new(); local commits; + local root; local index = 0; - local root = FolderNode.new('root'); local author = ''; local date = ''; + local world; --- -- @param path @@ -47,7 +48,7 @@ function MainScreen.new() for i = 1, #subfolders do -- Append a new folder node to the parent if there isn't a node -- for that folder yet. - target:append(subfolders[i], FolderNode.new(subfolders[i])); + target:append(subfolders[i], FolderNode.new(subfolders[i], world, false, target)); -- Make the newly added node the new target. target = target:getNode(subfolders[i]); @@ -94,10 +95,13 @@ function MainScreen.new() end function self:init() - local log = FileHandler.loadFile('tmplog.txt'); + local log = FileHandler.loadFile('foo.txt'); commits = FileHandler.splitCommits(log); - root:setPosition(love.graphics.getWidth() * 0.5, love.graphics.getHeight() * 0.5); + world = love.physics.newWorld(0.0, 0.0, true); + love.physics.setMeter(8); -- In our world 1m == 8px + + root = FolderNode.new('root', world, true); end function self:draw() @@ -108,6 +112,8 @@ function MainScreen.new() local timer = 0; function self:update(dt) + world:update(dt) --this puts the world into motion + timer = timer + dt; if timer > 0.2 then nextCommit(); diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 4ec1d4f..16f0070 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -16,10 +16,26 @@ local img = love.graphics.newImage('res/folderNode.png'); -- Constructor -- ------------------------------------------------ -function FolderNode.new(name) +function FolderNode.new(name, world, static, parent) local self = Node.new('folder', name); local children = {}; + local radius = 8; + local collider = {} + if parent then + local parentBody = parent:getColliderBody(); + collider.body = love.physics.newBody(world, parentBody:getX() + love.math.random(-10, 10), parentBody:getY() + love.math.random(-10, 10), static and 'static' or 'dynamic'); + else + collider.body = love.physics.newBody(world, love.graphics.getWidth() * 0.5, love.graphics.getHeight() * 0.5, static and 'static' or 'dynamic'); + end + collider.shape = love.physics.newCircleShape(radius); + collider.fixture = love.physics.newFixture(collider.body, collider.shape, 1); + collider.body:setMass(1.0); + if parent then + local parentBody = parent:getColliderBody(); + love.physics.newRopeJoint(parentBody, collider.body, parentBody:getX(), parentBody:getY(), collider.body:getX(), collider.body:getY(), 150, true); + end + --- -- Counts the amount of children nodes that represent files. @@ -51,40 +67,70 @@ function FolderNode.new(name) local angle = 360 / countFileNodes(children); local count = 0; - local radius = 15; - local arc = calcArc(radius, angle); + local r = 15; + local arc = calcArc(r, angle); while arc < 20 do - radius = radius * 2; - arc = calcArc(radius, angle); + r = r * 2; + arc = calcArc(r, angle); end + -- Only update the position of the file nodes based on the position of their parent folder node. for _, node in pairs(children) do if node:getType() == 'file' then count = count + 1; - local x = (radius * math.cos((angle * (count - 1)) * (math.pi / 180))); - local y = (radius * math.sin((angle * (count - 1)) * (math.pi / 180))); - node:setPosition(x + self:getX(), y + self:getY()); - elseif not node:getX() or not node:getY() then - node:setPosition(love.math.random(60, 1200), love.math.random(60, 700)); + local x = (r * math.cos((angle * (count - 1)) * (math.pi / 180))); + local y = (r * math.sin((angle * (count - 1)) * (math.pi / 180))); + node:setPosition(x + collider.body:getX(), y + collider.body:getY()); + end + end + + if r ~= radius then + collider.shape = love.physics.newCircleShape(r); + collider.fixture = love.physics.newFixture(collider.body, collider.shape, 1); + collider.body:setMass(1.0); + radius = r; + end + end + + local function repel() + local mass = 2; + + for _, node in pairs(children) do + if node:getType() == 'folder' then + local body = node:getColliderBody(); + + local dx = body:getX() - collider.body:getX(); + local dy = body:getY() - collider.body:getY(); + local len = math.sqrt(dx * dx + dy * dy); + local force = 400 * mass * mass / (len * len); + + collider.body:applyForce(-force * dx, -force * dy); + body:applyForce(force * dx, force * dy); end end end function self:draw() + love.graphics.setColor(0, 200, 0, 100); + love.graphics.circle("fill", collider.body:getX(), collider.body:getY(), collider.shape:getRadius()); + love.graphics.setColor(255, 255, 255); + for _, node in pairs(children) do if node:getType() == 'folder' then love.graphics.setColor(50, 50, 50); - love.graphics.line(self:getX(), self:getY(), node:getX(), node:getY()); + love.graphics.line(collider.body:getX(), collider.body:getY(), node:getColliderBody():getX(), node:getColliderBody():getY()); love.graphics.setColor(255, 255, 255); end node:draw(); end - love.graphics.print(name, self:getX() + 10, self:getY()); - love.graphics.draw(img, self:getX() - 8, self:getY() - 8); + love.graphics.print(name, collider.body:getX() + 10, collider.body:getY()); + love.graphics.draw(img, collider.body:getX() - 8, collider.body:getY() - 8); end function self:update(dt) + plotCircle(children); + repel(); for name, node in pairs(children) do if node:getType() == 'folder' and node:getChildrenCount() == 0 then children[name] = nil; @@ -108,6 +154,10 @@ function FolderNode.new(name) children[name] = nil; end + function self:getColliderBody() + return collider.body; + end + function self:getChildrenCount() local count = 0; for _, _ in pairs(children) do From 0c91f600d4afe99ea19e25fed8220d2d75f76ece Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 31 Dec 2014 15:21:11 +0100 Subject: [PATCH 21/54] FileHandler searches for the correct commit separator. Also moved the tag-strings to the top of the file as constants. --- src/FileHandler.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/FileHandler.lua b/src/FileHandler.lua index d324854..302b9a3 100644 --- a/src/FileHandler.lua +++ b/src/FileHandler.lua @@ -1,3 +1,11 @@ +-- ------------------------------------------------ +-- Constants +-- ------------------------------------------------ + +local TAG_SEPARATOR = 'logivi_commit'; +local TAG_AUTHOR = 'author'; +local TAG_DATE = 'date'; + -- ------------------------------------------------ -- Module -- ------------------------------------------------ @@ -35,13 +43,12 @@ function FileHandler.splitCommits(log) for i = 1, #log do local line = log[i]; - -- New commit. - if line:find('commit') then + if line:find(TAG_SEPARATOR) then -- Commit separator. index = index + 1; commits[index] = {}; - elseif line:find('author') then + elseif line:find(TAG_AUTHOR) then commits[index].author = line; - elseif line:find('date') then + elseif line:find(TAG_DATE) then commits[index].date = line; elseif line:len() ~= 0 then -- Split the file information into the modifier, which determines From 464babebce1954289e7e16b00d575501a3eeda73 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 31 Dec 2014 15:23:02 +0100 Subject: [PATCH 22/54] LoGiVi will look for a log.txt file to read from. Also moved all modifier tags to the top of the file as constants. --- src/MainScreen.lua | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/MainScreen.lua b/src/MainScreen.lua index 0cd017c..780a603 100644 --- a/src/MainScreen.lua +++ b/src/MainScreen.lua @@ -3,6 +3,21 @@ local FileHandler = require('src/FileHandler'); local FolderNode = require('src/nodes/FolderNode'); local FileNode = require('src/nodes/FileNode'); +-- ------------------------------------------------ +-- Constants +-- ------------------------------------------------ + +local LOG_FILE = 'log.txt'; +local MODIFIER_ADD = 'A'; +local MODIFIER_COPY = 'C'; +local MODIFIER_DELETE = 'D'; +local MODIFIER_MODIFY = 'M'; +local MODIFIER_RENAME = 'R'; +local MODIFIER_CHANGE = 'T'; +local MODIFIER_UNMERGE = 'U'; +local MODIFIER_UNKNOWN = 'X'; +local MODIFIER_BROKEN_PAIRING = 'B'; + -- ------------------------------------------------ -- Module -- ------------------------------------------------ @@ -62,9 +77,9 @@ function MainScreen.new() -- @param fileName -- local function modifyFileNodes(target, fileName, modifier) - if modifier == 'A' then -- Add file + if modifier == MODIFIER_ADD then -- Add file target:append(fileName, FileNode.new(fileName)); - elseif modifier == 'D' then + elseif modifier == MODIFIER_DELETE then target:remove(fileName); end end @@ -95,7 +110,7 @@ function MainScreen.new() end function self:init() - local log = FileHandler.loadFile('foo.txt'); + local log = FileHandler.loadFile(LOG_FILE); commits = FileHandler.splitCommits(log); world = love.physics.newWorld(0.0, 0.0, true); From f510ced28e03aa7f8edd1b4bfcef40e1d87e2d38 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 31 Dec 2014 14:58:13 +0100 Subject: [PATCH 23/54] Update readme with instructions about the usage of LoGiVi. --- Readme.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index b7c0948..84ce90f 100644 --- a/Readme.md +++ b/Readme.md @@ -1 +1,21 @@ -# LoveGit \ No newline at end of file +# LoGiVi + +LoGiVi is a git repository visualisation tool inspired by [Gource](https://code.google.com/p/gource/). + +## Instructions +LoGiVi (LÖVE Git Viewer) can't read from a .git repository directly. Instead you will have to create a git-log which needs to have a specific format. Please use this command to create the file: + + git log --reverse --date=iso --pretty=format:'logivi_commit%nauthor: %an%ndate: %ad%n' --name-status > log.txt + +This will create a log file in the same directory as the .git repository (of course you can write the log to any other location if you want to). + +Now you have to move this file to a folder from which it can be read by the LÖVE framework. Depending on your operating system this can be one of the following locations: + +- Windows XP: C:\Documents and Settings\user\Application Data\LOVE\rmcode_logivi +- Windows Vista and 7: C:\Users\user\AppData\Roaming\LOVE\rmcode_logivi +- Linux: $XDG_DATA_HOME/love/ or ~/.local/share/love/rmcode_logivi +- Mac: /Users/user/Library/Application Support/LOVE/rmcode_logivi + +For more information check the [LÖVE wiki](https://love2d.org/wiki/love.filesystem). + +As soon as the file is at the correct folder you can start LoGiVi and watch as it creates a visual representation of your git repository. \ No newline at end of file From 3e1ac007825d7e44a32879bc795564e7364c3216 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 31 Dec 2014 18:17:08 +0100 Subject: [PATCH 24/54] Place files more intelligently around folder nodes. Files are being distributed on different layers around the folder node. We start by placing files directly around the node. We make sure that the nodes don't overlap by calculating the arc between each file. If the arc becomes too small we create a new layer and start placing the file nodes there. This is repeated until all files are placed down. --- src/nodes/FolderNode.lua | 67 +++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 16f0070..d06e742 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -36,7 +36,6 @@ function FolderNode.new(name, world, static, parent) love.physics.newRopeJoint(parentBody, collider.body, parentBody:getX(), parentBody:getY(), collider.body:getX(), collider.body:getY(), 150, true); end - --- -- Counts the amount of children nodes that represent files. -- @@ -58,38 +57,66 @@ function FolderNode.new(name, world, static, parent) --- -- Distributes files nodes evenly on a circle around the parent node. + -- -- @param children - -- @param radius - -- - -- TODO radius based on amount of files? - -- TODO multiple circles if they get too big local function plotCircle(children) - local angle = 360 / countFileNodes(children); + local MIN_ARC_SIZE = 15; - local count = 0; - local r = 15; - local arc = calcArc(r, angle); + -- Calculate the radius of each circle around the folder node. + -- Increase the radius if the arc between files becomes too small. + local noNodes = 0; + local layer_radius = 15; -- Radius of the circle around the folder node. + local layers = { { r = layer_radius, n = noNodes } }; - while arc < 20 do - r = r * 2; - arc = calcArc(r, angle); + local arc; + local angle; + + for _, node in pairs(children) do + if node:getType() == 'file' then + noNodes = noNodes + 1; + + -- Calculate the arc between nodes. + angle = 360 / noNodes; + arc = calcArc(layers[#layers].r, angle); + + -- If arc is smaller than the minimum arc size we store the radius + -- of that circle and the number of nodes on that circle. + if arc < MIN_ARC_SIZE then + layers[#layers + 1] = { r = layer_radius, n = noNodes - 1}; + noNodes = 0; + layer_radius = layer_radius + 15; + else + layers[#layers].n = noNodes; + end + end end -- Only update the position of the file nodes based on the position of their parent folder node. + local count = 0; + local layer = 1; for _, node in pairs(children) do if node:getType() == 'file' then count = count + 1; - local x = (r * math.cos((angle * (count - 1)) * (math.pi / 180))); - local y = (r * math.sin((angle * (count - 1)) * (math.pi / 180))); - node:setPosition(x + collider.body:getX(), y + collider.body:getY()); + + if count <= layers[layer].n then + angle = 360 / layers[layer].n; + + local x = (layers[layer].r * math.cos((angle * (count - 1)) * (math.pi / 180))); + local y = (layers[layer].r * math.sin((angle * (count - 1)) * (math.pi / 180))); + node:setPosition(x + collider.body:getX(), y + collider.body:getY()); + else + layer = layer + 1; + count = 0; + end end end - if r ~= radius then - collider.shape = love.physics.newCircleShape(r); + -- Adjust box2d collision body. + if layers[#layers].r ~= radius then + collider.shape = love.physics.newCircleShape(layers[#layers].r); collider.fixture = love.physics.newFixture(collider.body, collider.shape, 1); collider.body:setMass(1.0); - radius = r; + radius = layers[#layers].r; end end @@ -174,7 +201,3 @@ end -- ------------------------------------------------ return FolderNode; - ---================================================================================================== --- Created 02.10.14 - 16:49 = ---================================================================================================== \ No newline at end of file From d2691695731332d59647718881910fa791ef3fb5 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 1 Jan 2015 16:58:21 +0100 Subject: [PATCH 25/54] Re-organize code and clean it up a bit. --- src/nodes/FolderNode.lua | 79 +++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index d06e742..7f81015 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -51,58 +51,79 @@ function FolderNode.new(name, world, static, parent) return count; end + --- + -- Calculates the arc for a certain angle. + -- @param radius + -- @param angle + -- local function calcArc(radius, angle) return math.pi * radius * (angle / 180); end --- - -- Distributes files nodes evenly on a circle around the parent node. - -- - -- @param children - local function plotCircle(children) + -- Calculates how many layers we need and how many file nodes + -- can be placed on each layer. + -- + local function createOnionLayers() local MIN_ARC_SIZE = 15; - -- Calculate the radius of each circle around the folder node. - -- Increase the radius if the arc between files becomes too small. - local noNodes = 0; - local layer_radius = 15; -- Radius of the circle around the folder node. - local layers = { { r = layer_radius, n = noNodes } }; - - local arc; - local angle; + local amount = 0; + local radius = 15; -- Radius of the circle around the folder node. + local layers = { + { radius = radius, amount = amount } + }; + local angle, arc; + -- Go through all child nodes of type 'file'. for _, node in pairs(children) do if node:getType() == 'file' then - noNodes = noNodes + 1; + amount = amount + 1; - -- Calculate the arc between nodes. - angle = 360 / noNodes; - arc = calcArc(layers[#layers].r, angle); + -- Calculate the arc between the file nodes on the current layer. + -- The more files are on it the smaller it gets. + angle = 360 / amount; + arc = calcArc(layers[#layers].radius, angle); - -- If arc is smaller than the minimum arc size we store the radius - -- of that circle and the number of nodes on that circle. + -- If the arc is smaller than the minimum arc size we store the radius + -- of the current layer and the number of nodes that can be placed + -- on that layer. if arc < MIN_ARC_SIZE then - layers[#layers + 1] = { r = layer_radius, n = noNodes - 1}; - noNodes = 0; - layer_radius = layer_radius + 15; + layers[#layers + 1] = { radius = radius, amount = amount - 1}; + amount = 0; + radius = radius + 15; else - layers[#layers].n = noNodes; + layers[#layers].amount = amount; end end end - -- Only update the position of the file nodes based on the position of their parent folder node. + return layers; + end + + --- + -- Distributes files nodes evenly on a circle around the parent node. + -- + -- @param children + -- + local function plotCircle(children) + -- Determine how the file nodes need to be distributed amongst different layers. + local layers = createOnionLayers(); + + -- Update the position of the file nodes based on the onion-layers. local count = 0; local layer = 1; for _, node in pairs(children) do if node:getType() == 'file' then count = count + 1; - if count <= layers[layer].n then - angle = 360 / layers[layer].n; + -- As long as the amount of nodes on the current layer is smaller or + -- the calculated amount we keep adding them to this layer. + -- If we pass this threshold we add a new layer and reset the counter. + if count <= layers[layer].amount then + local angle = 360 / layers[layer].amount; - local x = (layers[layer].r * math.cos((angle * (count - 1)) * (math.pi / 180))); - local y = (layers[layer].r * math.sin((angle * (count - 1)) * (math.pi / 180))); + local x = (layers[layer].radius * math.cos((angle * (count - 1)) * (math.pi / 180))); + local y = (layers[layer].radius * math.sin((angle * (count - 1)) * (math.pi / 180))); node:setPosition(x + collider.body:getX(), y + collider.body:getY()); else layer = layer + 1; @@ -112,11 +133,11 @@ function FolderNode.new(name, world, static, parent) end -- Adjust box2d collision body. - if layers[#layers].r ~= radius then + if layers[#layers].radius ~= radius then collider.shape = love.physics.newCircleShape(layers[#layers].r); collider.fixture = love.physics.newFixture(collider.body, collider.shape, 1); collider.body:setMass(1.0); - radius = layers[#layers].r; + radius = layers[#layers].radius; end end From de45768a8f7e776b5c46133670a625884a3b4080 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 1 Jan 2015 17:01:36 +0100 Subject: [PATCH 26/54] Fix key name. --- src/nodes/FolderNode.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 7f81015..c184e08 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -134,7 +134,7 @@ function FolderNode.new(name, world, static, parent) -- Adjust box2d collision body. if layers[#layers].radius ~= radius then - collider.shape = love.physics.newCircleShape(layers[#layers].r); + collider.shape = love.physics.newCircleShape(layers[#layers].radius); collider.fixture = love.physics.newFixture(collider.body, collider.shape, 1); collider.body:setMass(1.0); radius = layers[#layers].radius; From bff59e25853cfc5d60cedef0c2fff40c790c9b3e Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 1 Jan 2015 17:03:41 +0100 Subject: [PATCH 27/54] Deactivate collision between folder nodes but keep rope joints. --- src/nodes/FolderNode.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index c184e08..859991f 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -30,6 +30,7 @@ function FolderNode.new(name, world, static, parent) end collider.shape = love.physics.newCircleShape(radius); collider.fixture = love.physics.newFixture(collider.body, collider.shape, 1); + collider.fixture:setGroupIndex(-1); collider.body:setMass(1.0); if parent then local parentBody = parent:getColliderBody(); @@ -136,6 +137,7 @@ function FolderNode.new(name, world, static, parent) if layers[#layers].radius ~= radius then collider.shape = love.physics.newCircleShape(layers[#layers].radius); collider.fixture = love.physics.newFixture(collider.body, collider.shape, 1); + collider.fixture:setGroupIndex(-1); collider.body:setMass(1.0); radius = layers[#layers].radius; end From b67b8f79617ea5e9642f4895ec5a6c4bd9ed91fb Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 1 Jan 2015 20:44:37 +0100 Subject: [PATCH 28/54] Use updated screen manager library. --- lib/Screen.lua | 24 +++++++-- lib/ScreenManager.lua | 84 +++++++++++++++++++++++++------- main.lua | 7 ++- src/{ => screens}/MainScreen.lua | 0 4 files changed, 92 insertions(+), 23 deletions(-) rename src/{ => screens}/MainScreen.lua (100%) diff --git a/lib/Screen.lua b/lib/Screen.lua index 22b9de9..090f952 100644 --- a/lib/Screen.lua +++ b/lib/Screen.lua @@ -1,6 +1,24 @@ ---================================================================================================== --- Copyright (C) 2014 by Robert Machmer = ---================================================================================================== +--===============================================================================-- +-- -- +-- Copyright (c) 2014 Robert Machmer -- +-- -- +-- This software is provided 'as-is', without any express or implied -- +-- warranty. In no event will the authors be held liable for any damages -- +-- arising from the use of this software. -- +-- -- +-- Permission is granted to anyone to use this software for any purpose, -- +-- including commercial applications, and to alter it and redistribute it -- +-- freely, subject to the following restrictions: -- +-- -- +-- 1. The origin of this software must not be misrepresented; you must not -- +-- claim that you wrote the original software. If you use this software -- +-- in a product, an acknowledgment in the product documentation would be -- +-- appreciated but is not required. -- +-- 2. Altered source versions must be plainly marked as such, and must not be -- +-- misrepresented as being the original software. -- +-- 3. This notice may not be removed or altered from any source distribution. -- +-- -- +--===============================================================================-- local Screen = {}; diff --git a/lib/ScreenManager.lua b/lib/ScreenManager.lua index c81d869..a038587 100644 --- a/lib/ScreenManager.lua +++ b/lib/ScreenManager.lua @@ -1,21 +1,47 @@ ---================================================================================================== --- Copyright (C) 2014 by Robert Machmer = ---================================================================================================== +--===============================================================================-- +-- -- +-- Copyright (c) 2014 Robert Machmer -- +-- -- +-- This software is provided 'as-is', without any express or implied -- +-- warranty. In no event will the authors be held liable for any damages -- +-- arising from the use of this software. -- +-- -- +-- Permission is granted to anyone to use this software for any purpose, -- +-- including commercial applications, and to alter it and redistribute it -- +-- freely, subject to the following restrictions: -- +-- -- +-- 1. The origin of this software must not be misrepresented; you must not -- +-- claim that you wrote the original software. If you use this software -- +-- in a product, an acknowledgment in the product documentation would be -- +-- appreciated but is not required. -- +-- 2. Altered source versions must be plainly marked as such, and must not be -- +-- misrepresented as being the original software. -- +-- 3. This notice may not be removed or altered from any source distribution. -- +-- -- +--===============================================================================-- local ScreenManager = {}; +-- ------------------------------------------------ +-- Local Variables +-- ------------------------------------------------ + local stack = {}; +local screens = {}; -- ------------------------------------------------ -- Module Functions -- ------------------------------------------------ --- --- Initialise the ScreenManager and --- @param screen +-- Initialise the ScreenManager. This pushes the first +-- screen to the stack. +-- @param nscreens - The list of possible screens. +-- @param screen - The first screen to push to the stack. -- -function ScreenManager.init(screen) +function ScreenManager.init(nscreens, screen) stack = {}; + ScreenManager.setScreens(nscreens); ScreenManager.push(screen); end @@ -35,19 +61,28 @@ end -- it will overlay all the other screens. -- Screens below the this new screen will be set inactive. -- --- @param nscreen +-- @param screen - The name of the screen to push on the stack. -- -function ScreenManager.push(nscreen) +function ScreenManager.push(screen) -- Deactivate the previous screen if there is one. if ScreenManager.peek() then ScreenManager.peek():setActive(false); end -- Push the new screen onto the stack. - stack[#stack + 1] = nscreen; + if screens[screen] then + stack[#stack + 1] = screens[screen].new(); + else + local str = "{"; + for i, v in pairs(screens) do + str = str .. i .. ', '; + end + str = str .. "}"; + error('"' .. screen .. '" is not a valid screen. You will have to add a new one to your screen list or use one of the existing screens: ' .. str); + end -- Create the new screen and initialise it. - nscreen:init(); + stack[#stack]:init(); end --- @@ -58,7 +93,7 @@ function ScreenManager.peek() end --- --- Removes the topmost screen of the stack +-- Removes the topmost screen of the stack. -- function ScreenManager.pop() if #stack > 1 then @@ -74,7 +109,7 @@ function ScreenManager.pop() -- Activate next screen on the stack. ScreenManager.peek():setActive(true); else - error("Can't close the last screen. Use switch() to clear the screen manager and add a new screen"); + error("Can't close the last screen. Use switch() to clear the screen manager and add a new screen."); end end @@ -121,21 +156,21 @@ end --- -- Update all screens on the stack whenever the game window gains or -- loses focus. --- @param dfocus +-- @param nfocus -- -function ScreenManager.focus(dfocus) +function ScreenManager.focus(nfocus) for i = 1, #stack do - stack[i]:focus(dfocus); + stack[i]:focus(nfocus); end end --- -- Update all screens on the stack whenever the game window is minimized. --- @param dvisible +-- @param nvisible -- -function ScreenManager.visible(dvisible) +function ScreenManager.visible(nvisible) for i = 1, #stack do - stack[i]:visible(dvisible); + stack[i]:visible(nvisible); end end @@ -193,6 +228,19 @@ function ScreenManager.mousefocus(focus) ScreenManager.peek():mousefocus(focus); end +-- ------------------------------------------------ +-- Setters +-- ------------------------------------------------ + +--- +-- Set a new table of screens from which to pick a new screen when +-- pushing / switching. +-- @param nscreens +-- +function ScreenManager.setScreens(nscreens) + screens = nscreens; +end + -- ------------------------------------------------ -- Return Module -- ------------------------------------------------ diff --git a/main.lua b/main.lua index c746cff..56dc933 100644 --- a/main.lua +++ b/main.lua @@ -1,8 +1,11 @@ local ScreenManager = require('lib/ScreenManager'); -local MainScreen = require('src/MainScreen'); function love.load() - ScreenManager.init(MainScreen.new()); + local screens = { + main = require('src/screens/MainScreen'); + }; + + ScreenManager.init(screens, 'main'); end function love.draw() diff --git a/src/MainScreen.lua b/src/screens/MainScreen.lua similarity index 100% rename from src/MainScreen.lua rename to src/screens/MainScreen.lua From 2d2394d5445fe5cb733a9c20b350d54e709e6c56 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Thu, 1 Jan 2015 17:21:43 +0100 Subject: [PATCH 29/54] Add a camera that automatically tries to focus on the graph's center. I approach this by going through all displayed folder nodes and pick those that define the minimum / maximum x and y values of the graph. With these coordinates a rectangle is built and by bisecting its sides we can get the mid point of the graph which is then tracked by the camera. --- lib/Camera.lua | 113 +++++++++++++++++++++++++++++++++++++ src/nodes/FolderNode.lua | 7 +++ src/nodes/Node.lua | 6 +- src/screens/MainScreen.lua | 12 +++- 4 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 lib/Camera.lua diff --git a/lib/Camera.lua b/lib/Camera.lua new file mode 100644 index 0000000..52cddbc --- /dev/null +++ b/lib/Camera.lua @@ -0,0 +1,113 @@ +--===============================================================================-- +-- -- +-- Copyright (c) 2014 Robert Machmer -- +-- -- +-- This software is provided 'as-is', without any express or implied -- +-- warranty. In no event will the authors be held liable for any damages -- +-- arising from the use of this software. -- +-- -- +-- Permission is granted to anyone to use this software for any purpose, -- +-- including commercial applications, and to alter it and redistribute it -- +-- freely, subject to the following restrictions: -- +-- -- +-- 1. The origin of this software must not be misrepresented; you must not -- +-- claim that you wrote the original software. If you use this software -- +-- in a product, an acknowledgment in the product documentation would be -- +-- appreciated but is not required. -- +-- 2. Altered source versions must be plainly marked as such, and must not be -- +-- misrepresented as being the original software. -- +-- 3. This notice may not be removed or altered from any source distribution. -- +-- -- +--===============================================================================-- + +local Camera = {}; + +function Camera.new() + local self = {}; + + -- ------------------------------------------------ + -- Private Variables + -- ------------------------------------------------ + + local x, y = 0, 0; + local sx, sy = 1, 1; + local graphMinX, graphMaxX, graphMinY, graphMaxY; + + -- ------------------------------------------------ + -- Private Methods + -- ------------------------------------------------ + + local function debugDraw() + love.graphics.setColor(180, 180, 180, 50); + love.graphics.rectangle('fill', graphMinX, graphMinY, graphMaxX - graphMinX, graphMaxY - graphMinY); + love.graphics.setColor(255, 0, 0, 100); + love.graphics.circle('fill', graphMinX + (graphMaxX - graphMinX) * 0.5, graphMinY + (graphMaxY - graphMinY) * 0.5, 2); + love.graphics.setColor(255,255,255, 255); + end + + -- ------------------------------------------------ + -- Public Methods + -- ------------------------------------------------ + + function self:update(dt) + self:track(graphMinX + (graphMaxX - graphMinX) * 0.5, graphMinY + (graphMaxY - graphMinY) * 0.5, 3, dt); + end + + function self:set() + love.graphics.push(); + love.graphics.scale(sx, sy); + love.graphics.translate(-x, -y); + love.graphics.translate(love.graphics.getWidth() / (2 * sx), love.graphics.getHeight() / (2 * sy)); + end + + function self:unset() + love.graphics.pop(); + end + + function self:track(tarX, tarY, speed, dt) + x = x - (x - math.floor(tarX)) * dt * speed; + y = y - (y - math.floor(tarY)) * dt * speed; + end + + function self:checkEdges(tree) + local rootX = tree:getX(); + local rootY = tree:getY(); + graphMinX, graphMaxX, graphMinY, graphMaxY = rootX, rootX, rootY, rootY; + + local function traverseNodes(node, depth) + if node:getType() == 'folder' then + + -- Find the edges. + local x, y = node:getPosition(); + if x < graphMinX then + graphMinX = x; + elseif x > graphMaxX then + graphMaxX = x; + end + + if y < graphMinY then + graphMinY = y; + elseif y > graphMaxY then + graphMaxY = y; + end + + for key, child in pairs(node:getChildren()) do + traverseNodes(child, depth + 1); + end + end + end + traverseNodes(tree, 0); + end + + return self; +end + +-- ------------------------------------------------ +-- Return Module +-- ------------------------------------------------ + +return Camera; + +--================================================================================================== +-- Created 08.09.14 - 13:34 = +--================================================================================================== diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 859991f..ed8ac45 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -36,6 +36,7 @@ function FolderNode.new(name, world, static, parent) local parentBody = parent:getColliderBody(); love.physics.newRopeJoint(parentBody, collider.body, parentBody:getX(), parentBody:getY(), collider.body:getX(), collider.body:getY(), 150, true); end + self:setPosition(collider.body:getX(), collider.body:getY()); --- -- Counts the amount of children nodes that represent files. @@ -187,6 +188,8 @@ function FolderNode.new(name, world, static, parent) end node:update(dt); end + + self:setPosition(collider.body:getX(), collider.body:getY()); end function self:getNode(name) @@ -215,6 +218,10 @@ function FolderNode.new(name, world, static, parent) end return count; end + + function self:getChildren() + return children; + end return self; end diff --git a/src/nodes/Node.lua b/src/nodes/Node.lua index 99bfed1..8ffd69a 100644 --- a/src/nodes/Node.lua +++ b/src/nodes/Node.lua @@ -21,6 +21,10 @@ function Node.new(type, name, x, y) x, y = nx, ny; end + function self:getPosition() + return x, y; + end + function self:getX() return x; end @@ -48,4 +52,4 @@ return Node; --================================================================================================== -- Created 16.10.14 - 14:47 = ---================================================================================================== \ No newline at end of file +--================================================================================================== diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index 780a603..da72989 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -2,12 +2,13 @@ local Screen = require('lib/Screen'); local FileHandler = require('src/FileHandler'); local FolderNode = require('src/nodes/FolderNode'); local FileNode = require('src/nodes/FileNode'); +local Camera = require('lib/Camera'); -- ------------------------------------------------ -- Constants -- ------------------------------------------------ -local LOG_FILE = 'log.txt'; +local LOG_FILE = 'log.txt'; local MODIFIER_ADD = 'A'; local MODIFIER_COPY = 'C'; local MODIFIER_DELETE = 'D'; @@ -31,6 +32,7 @@ local MainScreen = {}; function MainScreen.new() local self = Screen.new(); + local camera = Camera.new(); local commits; local root; local index = 0; @@ -122,13 +124,19 @@ function MainScreen.new() function self:draw() love.graphics.print(date, 20, 20); love.graphics.print(author, 400, 20); + + camera:set(); root:draw(); + camera:unset(); end local timer = 0; function self:update(dt) world:update(dt) --this puts the world into motion + camera:checkEdges(root); + camera:update(dt); + timer = timer + dt; if timer > 0.2 then nextCommit(); @@ -149,4 +157,4 @@ return MainScreen; --================================================================================================== -- Created 01.10.14 - 13:18 = ---================================================================================================== \ No newline at end of file +--================================================================================================== From 2fd5a14050562b7ebcbc56f54b35577b919b3bed Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sun, 11 Jan 2015 15:34:09 +0100 Subject: [PATCH 30/54] Nodes also repel their siblings. --- src/nodes/FolderNode.lua | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index ed8ac45..d04a2ab 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -21,10 +21,11 @@ function FolderNode.new(name, world, static, parent) local children = {}; local radius = 8; - local collider = {} + local collider = {}; + local ropeLength = 150; if parent then local parentBody = parent:getColliderBody(); - collider.body = love.physics.newBody(world, parentBody:getX() + love.math.random(-10, 10), parentBody:getY() + love.math.random(-10, 10), static and 'static' or 'dynamic'); + collider.body = love.physics.newBody(world, parentBody:getX() + love.math.random(-20, 20), parentBody:getY() + love.math.random(-20, 20), static and 'static' or 'dynamic'); else collider.body = love.physics.newBody(world, love.graphics.getWidth() * 0.5, love.graphics.getHeight() * 0.5, static and 'static' or 'dynamic'); end @@ -34,7 +35,7 @@ function FolderNode.new(name, world, static, parent) collider.body:setMass(1.0); if parent then local parentBody = parent:getColliderBody(); - love.physics.newRopeJoint(parentBody, collider.body, parentBody:getX(), parentBody:getY(), collider.body:getX(), collider.body:getY(), 150, true); + love.physics.newRopeJoint(parentBody, collider.body, parentBody:getX(), parentBody:getY(), collider.body:getX(), collider.body:getY(), ropeLength, true); end self:setPosition(collider.body:getX(), collider.body:getY()); @@ -160,6 +161,24 @@ function FolderNode.new(name, world, static, parent) body:applyForce(force * dx, force * dy); end end + + if parent then + local siblings = parent:getChildren(); + + for _, sibling in pairs(siblings) do + if sibling:getType() == 'folder' and sibling ~= self then + local body = sibling:getColliderBody(); + + local dx = body:getX() - collider.body:getX(); + local dy = body:getY() - collider.body:getY(); + local len = math.sqrt(dx * dx + dy * dy); + local force = 400 * mass * mass / (len * len); + + collider.body:applyForce(-force * dx, -force * dy); + body:applyForce(force * dx, force * dy); + end + end + end end function self:draw() From 7a663e8506beb633493e62e8c8f3b432ef667eee Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Tue, 13 Jan 2015 14:01:31 +0100 Subject: [PATCH 31/54] Small code formatting fixes. --- src/nodes/FolderNode.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index d04a2ab..8837fdf 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -91,7 +91,7 @@ function FolderNode.new(name, world, static, parent) -- of the current layer and the number of nodes that can be placed -- on that layer. if arc < MIN_ARC_SIZE then - layers[#layers + 1] = { radius = radius, amount = amount - 1}; + layers[#layers + 1] = { radius = radius, amount = amount - 1 }; amount = 0; radius = radius + 15; else @@ -207,7 +207,7 @@ function FolderNode.new(name, world, static, parent) end node:update(dt); end - + self:setPosition(collider.body:getX(), collider.body:getY()); end @@ -237,7 +237,7 @@ function FolderNode.new(name, world, static, parent) end return count; end - + function self:getChildren() return children; end From 60ad1423431822df13f65b87644802727d4a0c77 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Tue, 13 Jan 2015 17:48:52 +0100 Subject: [PATCH 32/54] Create a list of all commit-authors. To get a clean list of the authors, the FileHandler removes the tag which marks the line in the log as an "author-line" so we only get the author's name. Whenever a new commit is processed the author is stored in a list. If LoGiVi finds a user-specified aliases.lua file it will use it to replace the author names read from the log with aliases (this can be helpful one author would be logged under two different names because of a typo). --- src/Authors.lua | 37 +++++++++++++++++++++++++++++++++++++ src/FileHandler.lua | 13 +++++++++++-- src/screens/MainScreen.lua | 4 ++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/Authors.lua diff --git a/src/Authors.lua b/src/Authors.lua new file mode 100644 index 0000000..c0f7c40 --- /dev/null +++ b/src/Authors.lua @@ -0,0 +1,37 @@ +local Authors = {}; + +-- ------------------------------------------------ +-- Local Variables +-- ------------------------------------------------ + +local list = {}; + +local aliases = love.filesystem.load('aliases.lua'); +aliases = aliases and aliases() or {}; + +-- ------------------------------------------------ +-- Public Functions +-- ------------------------------------------------ + +--- +-- Draws a list of all authors working on the project. +-- +function Authors.draw() + local count = 0; + for author, _ in pairs(list) do + count = count + 1; + love.graphics.print(author, 20, 100 + count * 20); + end +end + +--- +-- Adds a new author to the list. If a file for alternatives +-- was found, the function will use relapcements from that list. +-- This can be used to fix "faulty" authors in commits. +-- @param nauthor +-- +function Authors.add(nauthor) + list[aliases[nauthor] or nauthor] = true; +end + +return Authors; \ No newline at end of file diff --git a/src/FileHandler.lua b/src/FileHandler.lua index 302b9a3..a46fe35 100644 --- a/src/FileHandler.lua +++ b/src/FileHandler.lua @@ -3,7 +3,7 @@ -- ------------------------------------------------ local TAG_SEPARATOR = 'logivi_commit'; -local TAG_AUTHOR = 'author'; +local TAG_AUTHOR = 'author: '; local TAG_DATE = 'date'; -- ------------------------------------------------ @@ -20,6 +20,15 @@ local function trim(str) return str:match("^%s*(.-)%s*$"); end +--- +-- Remove the specified tag from the line. +-- @param line +-- @param tag +-- +local function removeTag(line, tag) + return line:gsub(tag, ''); +end + --- -- Loads the file and stores it line for line in a lua table. -- @param name @@ -47,7 +56,7 @@ function FileHandler.splitCommits(log) index = index + 1; commits[index] = {}; elseif line:find(TAG_AUTHOR) then - commits[index].author = line; + commits[index].author = removeTag(line, TAG_AUTHOR); elseif line:find(TAG_DATE) then commits[index].date = line; elseif line:len() ~= 0 then diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index da72989..e0ec615 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -3,6 +3,7 @@ local FileHandler = require('src/FileHandler'); local FolderNode = require('src/nodes/FolderNode'); local FileNode = require('src/nodes/FileNode'); local Camera = require('lib/Camera'); +local Authors = require('src/Authors'); -- ------------------------------------------------ -- Constants @@ -93,6 +94,8 @@ function MainScreen.new() index = index + 1; author = commits[index].author; + Authors.add(author); + date = commits[index].date; for i = 1, #commits[index] do @@ -124,6 +127,7 @@ function MainScreen.new() function self:draw() love.graphics.print(date, 20, 20); love.graphics.print(author, 400, 20); + Authors.draw(); camera:set(); root:draw(); From f42b8864d58f0dace08f336035acfa8f3452c018 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Tue, 13 Jan 2015 18:36:40 +0100 Subject: [PATCH 33/54] =?UTF-8?q?Move=20project=20to=20L=C3=96VE=20version?= =?UTF-8?q?=200.9.2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.lua b/conf.lua index 889e5b2..a40842c 100644 --- a/conf.lua +++ b/conf.lua @@ -1,6 +1,6 @@ local GAME_TITLE = "LoGiVi"; -local LOVE_VERSION = "0.9.1"; +local LOVE_VERSION = "0.9.2"; local GAME_VERSION = "0000"; From 97e42285b0c7d1d7288f9af770497ddf6d143ca0 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 14 Jan 2015 01:17:15 +0100 Subject: [PATCH 34/54] Fix placement of file nodes around their parents (folder nodes). The code ignored some of the nodes when it switched to a new layer and also didn't update the position of others correctly. Now, file nodes are distributed evenly around their parents and it seems to work fine with large amount of files too. --- src/nodes/FolderNode.lua | 77 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 8837fdf..0343206 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -65,38 +65,38 @@ function FolderNode.new(name, world, static, parent) --- -- Calculates how many layers we need and how many file nodes - -- can be placed on each layer. + -- can be placed on each layer. This basically generates a + -- blueprint of how the nodes need to be arranged. + -- @param children -- - local function createOnionLayers() + local function createOnionLayers(children) local MIN_ARC_SIZE = 15; - local amount = 0; + local nodes = 0; local radius = 15; -- Radius of the circle around the folder node. local layers = { - { radius = radius, amount = amount } + { radius = radius, amount = nodes } }; - local angle, arc; -- Go through all child nodes of type 'file'. - for _, node in pairs(children) do - if node:getType() == 'file' then - amount = amount + 1; - - -- Calculate the arc between the file nodes on the current layer. - -- The more files are on it the smaller it gets. - angle = 360 / amount; - arc = calcArc(layers[#layers].radius, angle); - - -- If the arc is smaller than the minimum arc size we store the radius - -- of the current layer and the number of nodes that can be placed - -- on that layer. - if arc < MIN_ARC_SIZE then - layers[#layers + 1] = { radius = radius, amount = amount - 1 }; - amount = 0; - radius = radius + 15; - else - layers[#layers].amount = amount; - end + for i = 1, countFileNodes(children) do + nodes = nodes + 1; + + -- Calculate the arc between the file nodes on the current layer. + -- The more files are on it the smaller it gets. + local arc = calcArc(layers[#layers].radius, 360 / nodes); + + -- If the arc is smaller than the allowed minimum we store the radius + -- of the current layer and the number of nodes that can be placed + -- on that layer and move to the next layer. + if arc < MIN_ARC_SIZE then + radius = radius + 15; + + -- Create a new layer. + layers[#layers + 1] = { radius = radius, amount = 1 }; + nodes = 1; + else + layers[#layers].amount = nodes; end end @@ -105,33 +105,32 @@ function FolderNode.new(name, world, static, parent) --- -- Distributes files nodes evenly on a circle around the parent node. - -- -- @param children -- local function plotCircle(children) - -- Determine how the file nodes need to be distributed amongst different layers. - local layers = createOnionLayers(); + -- Get a blueprint of how the file nodes need to be distributed amongst different layers. + local layers = createOnionLayers(children); - -- Update the position of the file nodes based on the onion-layers. + -- Update the position of the file nodes based on the previously calculated onion-layers. local count = 0; local layer = 1; for _, node in pairs(children) do if node:getType() == 'file' then count = count + 1; - -- As long as the amount of nodes on the current layer is smaller or - -- the calculated amount we keep adding them to this layer. - -- If we pass this threshold we add a new layer and reset the counter. - if count <= layers[layer].amount then - local angle = 360 / layers[layer].amount; - - local x = (layers[layer].radius * math.cos((angle * (count - 1)) * (math.pi / 180))); - local y = (layers[layer].radius * math.sin((angle * (count - 1)) * (math.pi / 180))); - node:setPosition(x + collider.body:getX(), y + collider.body:getY()); - else + -- If we have more nodes on the current layer than allowed, we "move" + -- the node to the next layer (this is why we reset the counter to one + -- instead of zero). + if count > layers[layer].amount then layer = layer + 1; - count = 0; + count = 1; end + + -- Calculate the new position of the node on its layer around the folder node. + local angle = 360 / layers[layer].amount; + local x = (layers[layer].radius * math.cos((angle * (count - 1)) * (math.pi / 180))); + local y = (layers[layer].radius * math.sin((angle * (count - 1)) * (math.pi / 180))); + node:setPosition(x + collider.body:getX(), y + collider.body:getY()); end end From 6649bec8186a01272d5c55c2bb08f752bde35772 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 14 Jan 2015 02:43:00 +0100 Subject: [PATCH 35/54] Count files based on their file extensions. --- src/FileManager.lua | 73 ++++++++++++++++++++++++++++++++++++++ src/screens/MainScreen.lua | 4 +++ 2 files changed, 77 insertions(+) create mode 100644 src/FileManager.lua diff --git a/src/FileManager.lua b/src/FileManager.lua new file mode 100644 index 0000000..3e3e1a4 --- /dev/null +++ b/src/FileManager.lua @@ -0,0 +1,73 @@ +local FileManager = {}; + +-- ------------------------------------------------ +-- Local Variables +-- ------------------------------------------------ + +local extensions = {}; + +-- ------------------------------------------------ +-- Local Functions +-- ------------------------------------------------ + +--- +-- Splits the extension from a file. +-- @param fileName +-- +local function splitExtension(fileName) + local pos = fileName:find('%.'); + if pos then + return fileName:sub(pos); + else + -- Prevents issues with files sans extension. + return '.?'; + end +end + +-- ------------------------------------------------ +-- Public Functions +-- ------------------------------------------------ + +--- +-- Draws a list of all authors working on the project. +-- +function FileManager.draw() + local count = 0; + for ext, amount in pairs(extensions) do + count = count + 1; + love.graphics.print(ext, love.graphics.getWidth() - 80, 100 + count * 20); + love.graphics.print(amount, love.graphics.getWidth() - 120, 100 + count * 20); + end +end + +--- +-- Adds a new file extension to the list. +-- @param fileName +-- +function FileManager.add(fileName) + local ext = splitExtension(fileName); + if not extensions[ext] then + extensions[ext] = 0; + end + extensions[ext] = extensions[ext] + 1; +end + +--- +-- Reduce the amount of counted files of the +-- same extension. If there are no more files +-- of that extension, it will remove it from +-- the list. +-- +function FileManager.remove(fileName) + local ext = splitExtension(fileName); + if not extensions[ext] then + error('Tried to remove the non existing file extension "' .. ext .. '".'); + end + + extensions[ext] = extensions[ext] - 1; + if extensions[ext] == 0 then + extensions[ext] = nil; + end +end + +return FileManager; \ No newline at end of file diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index e0ec615..69d111a 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -4,6 +4,7 @@ local FolderNode = require('src/nodes/FolderNode'); local FileNode = require('src/nodes/FileNode'); local Camera = require('lib/Camera'); local Authors = require('src/Authors'); +local FileManager = require('src/FileManager'); -- ------------------------------------------------ -- Constants @@ -81,8 +82,10 @@ function MainScreen.new() -- local function modifyFileNodes(target, fileName, modifier) if modifier == MODIFIER_ADD then -- Add file + FileManager.add(fileName); target:append(fileName, FileNode.new(fileName)); elseif modifier == MODIFIER_DELETE then + FileManager.remove(fileName); target:remove(fileName); end end @@ -128,6 +131,7 @@ function MainScreen.new() love.graphics.print(date, 20, 20); love.graphics.print(author, 400, 20); Authors.draw(); + FileManager.draw(); camera:set(); root:draw(); From f863a2970997ff92e297208c309ca3c9231ccd0f Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 14 Jan 2015 04:22:35 +0100 Subject: [PATCH 36/54] Rename FileHandler to LogReader. The old name was a bit misleading since the module only reads the git log. It also was hard to distinguish from the newer FileManager module. --- src/{FileHandler.lua => LogReader.lua} | 8 ++++---- src/screens/MainScreen.lua | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) rename src/{FileHandler.lua => LogReader.lua} (94%) diff --git a/src/FileHandler.lua b/src/LogReader.lua similarity index 94% rename from src/FileHandler.lua rename to src/LogReader.lua index a46fe35..1a5a37e 100644 --- a/src/FileHandler.lua +++ b/src/LogReader.lua @@ -10,7 +10,7 @@ local TAG_DATE = 'date'; -- Module -- ------------------------------------------------ -local FileHandler = {}; +local LogReader = {}; --- -- Remove leading and trailing whitespace. @@ -33,7 +33,7 @@ end -- Loads the file and stores it line for line in a lua table. -- @param name -- -function FileHandler.loadFile(name) +function LogReader.loadFile(name) local file = {}; for line in love.filesystem.lines(name) do file[#file + 1] = line; @@ -46,7 +46,7 @@ end -- nested table. -- @param log -- -function FileHandler.splitCommits(log) +function LogReader.splitCommits(log) local commits = {}; local index = 0; for i = 1, #log do @@ -77,7 +77,7 @@ end -- Return Module -- ------------------------------------------------ -return FileHandler; +return LogReader; --================================================================================================== -- Created 01.10.14 - 12:34 = diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index 69d111a..6fedeba 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -1,5 +1,5 @@ local Screen = require('lib/Screen'); -local FileHandler = require('src/FileHandler'); +local LogReader = require('src/LogReader'); local FolderNode = require('src/nodes/FolderNode'); local FileNode = require('src/nodes/FileNode'); local Camera = require('lib/Camera'); @@ -118,8 +118,8 @@ function MainScreen.new() end function self:init() - local log = FileHandler.loadFile(LOG_FILE); - commits = FileHandler.splitCommits(log); + local log = LogReader.loadFile(LOG_FILE); + commits = LogReader.splitCommits(log); world = love.physics.newWorld(0.0, 0.0, true); love.physics.setMeter(8); -- In our world 1m == 8px From 294e2e80b6c28ab142619011fe6b7b56a906ca0c Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 14 Jan 2015 04:33:57 +0100 Subject: [PATCH 37/54] Refactoring. Minor changes to the code flow and structure. --- src/LogReader.lua | 28 ++++++++++++++-------------- src/screens/MainScreen.lua | 3 +-- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/LogReader.lua b/src/LogReader.lua index 1a5a37e..89c17ad 100644 --- a/src/LogReader.lua +++ b/src/LogReader.lua @@ -29,30 +29,18 @@ local function removeTag(line, tag) return line:gsub(tag, ''); end ---- --- Loads the file and stores it line for line in a lua table. --- @param name --- -function LogReader.loadFile(name) - local file = {}; - for line in love.filesystem.lines(name) do - file[#file + 1] = line; - end - return file; -end - --- -- Split up the log table into commits. Each commit is a new -- nested table. -- @param log -- -function LogReader.splitCommits(log) +local function splitCommits(log) local commits = {}; local index = 0; for i = 1, #log do local line = log[i]; - if line:find(TAG_SEPARATOR) then -- Commit separator. + if line:find(TAG_SEPARATOR) then -- Commit separator. index = index + 1; commits[index] = {}; elseif line:find(TAG_AUTHOR) then @@ -73,6 +61,18 @@ function LogReader.splitCommits(log) return commits; end +--- +-- Loads the file and stores it line for line in a lua table. +-- @param name +-- +function LogReader.loadLog(name) + local log = {}; + for line in love.filesystem.lines(name) do + log[#log + 1] = line; + end + return splitCommits(log); +end + -- ------------------------------------------------ -- Return Module -- ------------------------------------------------ diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index 6fedeba..a8dde68 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -118,8 +118,7 @@ function MainScreen.new() end function self:init() - local log = LogReader.loadFile(LOG_FILE); - commits = LogReader.splitCommits(log); + commits = LogReader.loadLog(LOG_FILE); world = love.physics.newWorld(0.0, 0.0, true); love.physics.setMeter(8); -- In our world 1m == 8px From 24c855146d88a28fe6acbb4c9c59a91b9bdf1d85 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 14 Jan 2015 03:37:21 +0100 Subject: [PATCH 38/54] Assign a random color to each file node based on its extension. --- res/fileNode.png | Bin 1271 -> 113 bytes src/FileManager.lua | 22 ++++++++++++++++------ src/nodes/FileNode.lua | 4 +++- src/screens/MainScreen.lua | 4 ++-- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/res/fileNode.png b/res/fileNode.png index 5b456d3d541eb2d8578d94fd609d561892f8730b..cc36bacb2635b7d5351c1fc5dd2c85d18caa5578 100644 GIT binary patch delta 84 zcmey)SvW!2kHNyz#WAGfR&v4t#(#?$*^&;{Gc_okt>FFXue89!xJ^++^22;50~sEP o9}x?@oECWnE%QoKQnzMic)I?re(k=^?hHWS>FVdQ&MBb@07Ney>i_@% delta 1251 zcmV<91RVQu_X&_Ae*`3HLqkwWLqi}?a&Km7Y-IodI1zQlu6?AXrC- zip8&0Q(L(k8m-0#Nt31RN*1N**eWFCIyZ@_8wcCzwyIBifj0*H0YKRU4@f*A4F+O+ z+4jJ+NmGX^s!2$D=)?~pChY}P;k$NXCsV{+_4>;>-#OX-eVh__(Z?q}P9Z-Dj?gOW6|D%o z20XmjW-qs4e_sO_$dln!ZX3EHW|6b4l3{Ys;V+MIw=w?@E}M1q>|KLc`<$h@W4I5A z-YfQ0zKK8Awe%eDOR!(Bxk+Jv1^AEp(tHAVA5rwFl6`dE=SN>(trXq{-UWNnaHk7R z`)YMDdmI?C(e)+kn8+hI*L7zSv!oY*?^gJ<*kkCCf2hb)Y2abt!AgCqnO~Z5R_27= z%d=XU%mO2iWWT4) zbyOBQPEhjvKz%5PQO?=#8v4zT{)U>cODpsve^1acG+XTxAO{m@bvM#Jr)z6J><&E2 z2D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7qW-CFs9&fT)ZaU5gc&=gBz-Da zePod(y&RKbhpuXfcI6;Cqz3RHyZ!0HyS%%BL5cAW%EB-0C9M18!Hn4 z0053jL_t(I5o2V)0U~S9{YREs-fYB(%!jct1YsJlZ=VlS1Ew`S6TvjPK_~`*G^1-o zF$Ks08H8*I+yG)U!wf?<1Z)5)U7FDiVS)*eOEZ#VJIpeWS15MDz#A|KVgVMSq{IeB zLL$WwWX&Lb@T81v2#AfICqNoO068Ck_!tI&1VI4gB?t>bqHBc70RTX%MY)SyO=SQ8 N002ovPDHLkV1oDwQ>_31 diff --git a/src/FileManager.lua b/src/FileManager.lua index 3e3e1a4..ad2a59e 100644 --- a/src/FileManager.lua +++ b/src/FileManager.lua @@ -33,10 +33,12 @@ end -- function FileManager.draw() local count = 0; - for ext, amount in pairs(extensions) do + for ext, tbl in pairs(extensions) do count = count + 1; + love.graphics.setColor(tbl.color); love.graphics.print(ext, love.graphics.getWidth() - 80, 100 + count * 20); - love.graphics.print(amount, love.graphics.getWidth() - 120, 100 + count * 20); + love.graphics.print(tbl.amount, love.graphics.getWidth() - 120, 100 + count * 20); + love.graphics.setColor(255, 255, 255); end end @@ -47,9 +49,13 @@ end function FileManager.add(fileName) local ext = splitExtension(fileName); if not extensions[ext] then - extensions[ext] = 0; + extensions[ext] = {}; + extensions[ext].amount = 0; + extensions[ext].color = { love.math.random(0, 255), love.math.random(0, 255), love.math.random(0, 255) }; end - extensions[ext] = extensions[ext] + 1; + extensions[ext].amount = extensions[ext].amount + 1; + + return extensions[ext].color; end --- @@ -64,10 +70,14 @@ function FileManager.remove(fileName) error('Tried to remove the non existing file extension "' .. ext .. '".'); end - extensions[ext] = extensions[ext] - 1; - if extensions[ext] == 0 then + extensions[ext].amount = extensions[ext].amount - 1; + if extensions[ext].amount == 0 then extensions[ext] = nil; end end +function FileManager.getColor(ext) + return extensions[ext].color; +end + return FileManager; \ No newline at end of file diff --git a/src/nodes/FileNode.lua b/src/nodes/FileNode.lua index dbaf82c..33d5b84 100644 --- a/src/nodes/FileNode.lua +++ b/src/nodes/FileNode.lua @@ -16,11 +16,13 @@ local img = love.graphics.newImage('res/fileNode.png'); -- Constructor -- ------------------------------------------------ -function FileNode.new(name) +function FileNode.new(name, color) local self = Node.new('file', name); function self:draw() + love.graphics.setColor(color); love.graphics.draw(img, self:getX() - 8, self:getY() - 8); + love.graphics.setColor(255, 255, 255); end return self; diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index a8dde68..3ea04a7 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -82,8 +82,8 @@ function MainScreen.new() -- local function modifyFileNodes(target, fileName, modifier) if modifier == MODIFIER_ADD then -- Add file - FileManager.add(fileName); - target:append(fileName, FileNode.new(fileName)); + local color = FileManager.add(fileName); + target:append(fileName, FileNode.new(fileName, color)); elseif modifier == MODIFIER_DELETE then FileManager.remove(fileName); target:remove(fileName); From b40a846d699066a5f35659c1d3a0d1b2c423524a Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Wed, 14 Jan 2015 11:23:41 +0100 Subject: [PATCH 39/54] Update readme with better git command. Merge commits now show the full difference, just like regular commits. --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 84ce90f..85492b6 100644 --- a/Readme.md +++ b/Readme.md @@ -5,7 +5,7 @@ LoGiVi is a git repository visualisation tool inspired by [Gource](https://code. ## Instructions LoGiVi (LÖVE Git Viewer) can't read from a .git repository directly. Instead you will have to create a git-log which needs to have a specific format. Please use this command to create the file: - git log --reverse --date=iso --pretty=format:'logivi_commit%nauthor: %an%ndate: %ad%n' --name-status > log.txt + git log --reverse --date=iso -m --pretty=format:'logivi_commit%nauthor: %an%ndate: %ad%n' --name-status > log.txt This will create a log file in the same directory as the .git repository (of course you can write the log to any other location if you want to). From 7380c3085841ff3e3c84011ed1f38127571658df Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 16 Jan 2015 09:20:16 +0100 Subject: [PATCH 40/54] Write a default aliases file to the save folder when none can be found. --- src/Authors.lua | 25 +++++++++++++++++++++---- src/screens/MainScreen.lua | 2 ++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Authors.lua b/src/Authors.lua index c0f7c40..ed62e95 100644 --- a/src/Authors.lua +++ b/src/Authors.lua @@ -4,15 +4,32 @@ local Authors = {}; -- Local Variables -- ------------------------------------------------ -local list = {}; - -local aliases = love.filesystem.load('aliases.lua'); -aliases = aliases and aliases() or {}; +local list; +local default; +local aliases; -- ------------------------------------------------ -- Public Functions -- ------------------------------------------------ +function Authors.init() + list = {}; + default = [[ +return { + -- ['NameToReplace'] = 'ReplaceWith', +}; +]]; + + if not love.filesystem.isFile('aliases.lua') then + local file = love.filesystem.newFile('aliases.lua'); + file:open('w'); + file:write(default); + file:close(); + end + + aliases = love.filesystem.load('aliases.lua')(); +end + --- -- Draws a list of all authors working on the project. -- diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index 3ea04a7..fe92765 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -118,6 +118,8 @@ function MainScreen.new() end function self:init() + Authors.init(); + commits = LogReader.loadLog(LOG_FILE); world = love.physics.newWorld(0.0, 0.0, true); From e839582b5acc0576fc4b1d255f6938bead629c49 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 16 Jan 2015 09:37:07 +0100 Subject: [PATCH 41/54] Check if there is a log file ready to be loaded. If no log is found LoGiVi display a warning message and open the directory in which to place the git log. --- src/LogReader.lua | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/LogReader.lua b/src/LogReader.lua index 89c17ad..4f47c4e 100644 --- a/src/LogReader.lua +++ b/src/LogReader.lua @@ -61,11 +61,34 @@ local function splitCommits(log) return commits; end +--- +-- Checks if there is a log file LoGiVi can work with. If the file +-- can't be found it will display a warning message and open the save +-- folder. +-- @param name +-- +local function isLogFile(name) + if not love.filesystem.isFile(name) then + local msg = [[ +To use LoGiVi you will have to generate a git log first. See the readme for instructions on how to generate a proper log. + +LoGiVi now will open the file directory in which to place the log. +]]; + love.window.showMessageBox('No git log found.', msg, 'warning', false); + love.system.openURL('file://' .. love.filesystem.getSaveDirectory()); + return false; + end +end + --- -- Loads the file and stores it line for line in a lua table. -- @param name -- function LogReader.loadLog(name) + if not isLogFile(name) then + return {}; + end + local log = {}; for line in love.filesystem.lines(name) do log[#log + 1] = line; From 641dc890925bab9b7fea43fa08d50b994f029a58 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 16 Jan 2015 11:07:44 +0100 Subject: [PATCH 42/54] Fix loading of the log. --- src/LogReader.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LogReader.lua b/src/LogReader.lua index 4f47c4e..d1e0b75 100644 --- a/src/LogReader.lua +++ b/src/LogReader.lua @@ -78,6 +78,7 @@ LoGiVi now will open the file directory in which to place the log. love.system.openURL('file://' .. love.filesystem.getSaveDirectory()); return false; end + return true; end --- From 4c93d961732d87ce7c3f6fe621dca25adfe3241d Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Fri, 16 Jan 2015 12:44:23 +0100 Subject: [PATCH 43/54] Update readme. Moved instructions to the wiki. --- Readme.md | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/Readme.md b/Readme.md index 85492b6..a44169d 100644 --- a/Readme.md +++ b/Readme.md @@ -1,21 +1,5 @@ # LoGiVi -LoGiVi is a git repository visualisation tool inspired by [Gource](https://code.google.com/p/gource/). +LoGiVi the "lovely Git-Viewer" is a git-repository visualisation tool inspired by [Gource](https://code.google.com/p/gource/). It was written from scratch using [Lua](http://www.lua.org/) and the [LÖVE](https://love2d.org/) framework. -## Instructions -LoGiVi (LÖVE Git Viewer) can't read from a .git repository directly. Instead you will have to create a git-log which needs to have a specific format. Please use this command to create the file: - - git log --reverse --date=iso -m --pretty=format:'logivi_commit%nauthor: %an%ndate: %ad%n' --name-status > log.txt - -This will create a log file in the same directory as the .git repository (of course you can write the log to any other location if you want to). - -Now you have to move this file to a folder from which it can be read by the LÖVE framework. Depending on your operating system this can be one of the following locations: - -- Windows XP: C:\Documents and Settings\user\Application Data\LOVE\rmcode_logivi -- Windows Vista and 7: C:\Users\user\AppData\Roaming\LOVE\rmcode_logivi -- Linux: $XDG_DATA_HOME/love/ or ~/.local/share/love/rmcode_logivi -- Mac: /Users/user/Library/Application Support/LOVE/rmcode_logivi - -For more information check the [LÖVE wiki](https://love2d.org/wiki/love.filesystem). - -As soon as the file is at the correct folder you can start LoGiVi and watch as it creates a visual representation of your git repository. \ No newline at end of file +Check the [wiki](https://bitbucket.org/rmcode/logivi/wiki/Home) for instructions and further information. \ No newline at end of file From aef62d479067cefd368275d1601c86312fe154f5 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sat, 17 Jan 2015 16:45:27 +0100 Subject: [PATCH 44/54] Refactoring. Renamed Authors to AuthorManager and cleaned it up a bit. --- src/{Authors.lua => AuthorManager.lua} | 21 ++++++++++----------- src/screens/MainScreen.lua | 8 ++++---- 2 files changed, 14 insertions(+), 15 deletions(-) rename src/{Authors.lua => AuthorManager.lua} (77%) diff --git a/src/Authors.lua b/src/AuthorManager.lua similarity index 77% rename from src/Authors.lua rename to src/AuthorManager.lua index ed62e95..45d3caf 100644 --- a/src/Authors.lua +++ b/src/AuthorManager.lua @@ -1,20 +1,19 @@ -local Authors = {}; +local AuthorManager = {}; -- ------------------------------------------------ -- Local Variables -- ------------------------------------------------ -local list; -local default; +local authors; local aliases; -- ------------------------------------------------ -- Public Functions -- ------------------------------------------------ -function Authors.init() - list = {}; - default = [[ +function AuthorManager.init() + authors = {}; + local default = [[ return { -- ['NameToReplace'] = 'ReplaceWith', }; @@ -33,9 +32,9 @@ end --- -- Draws a list of all authors working on the project. -- -function Authors.draw() +function AuthorManager.draw() local count = 0; - for author, _ in pairs(list) do + for author, _ in pairs(authors) do count = count + 1; love.graphics.print(author, 20, 100 + count * 20); end @@ -47,8 +46,8 @@ end -- This can be used to fix "faulty" authors in commits. -- @param nauthor -- -function Authors.add(nauthor) - list[aliases[nauthor] or nauthor] = true; +function AuthorManager.add(nauthor) + authors[aliases[nauthor] or nauthor] = true; end -return Authors; \ No newline at end of file +return AuthorManager; \ No newline at end of file diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index fe92765..cc488b0 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -3,7 +3,7 @@ local LogReader = require('src/LogReader'); local FolderNode = require('src/nodes/FolderNode'); local FileNode = require('src/nodes/FileNode'); local Camera = require('lib/Camera'); -local Authors = require('src/Authors'); +local AuthorManager = require('src/AuthorManager'); local FileManager = require('src/FileManager'); -- ------------------------------------------------ @@ -97,7 +97,7 @@ function MainScreen.new() index = index + 1; author = commits[index].author; - Authors.add(author); + AuthorManager.add(author); date = commits[index].date; @@ -118,7 +118,7 @@ function MainScreen.new() end function self:init() - Authors.init(); + AuthorManager.init(); commits = LogReader.loadLog(LOG_FILE); @@ -131,7 +131,7 @@ function MainScreen.new() function self:draw() love.graphics.print(date, 20, 20); love.graphics.print(author, 400, 20); - Authors.draw(); + AuthorManager.draw(); FileManager.draw(); camera:set(); From 4c7fabffcac537d6385c53a1f109e20d9e2e5638 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sat, 17 Jan 2015 17:33:53 +0100 Subject: [PATCH 45/54] Mark modified files with a color that fades away over time. To fade the color we lerp between the default color for the file extension (which it was assigned based on its extension) and the "modified" color, which currently is a bright red. After a small delay we mark the file as unmodified, reset the timer and assign the default color (regardless of wether the lerping is done or not). --- src/nodes/FileNode.lua | 62 +++++++++++++++++++++++++++++++++++++- src/screens/MainScreen.lua | 3 ++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/nodes/FileNode.lua b/src/nodes/FileNode.lua index 33d5b84..7ec16e8 100644 --- a/src/nodes/FileNode.lua +++ b/src/nodes/FileNode.lua @@ -6,6 +6,13 @@ local Node = require('src/nodes/Node'); local FileNode = {}; +-- ------------------------------------------------ +-- Constants +-- ------------------------------------------------ + +local MOD_TIMER = 2; +local MOD_COLOR = { 255, 0, 0 }; + -- ------------------------------------------------ -- Local Variables -- ------------------------------------------------ @@ -19,12 +26,65 @@ local img = love.graphics.newImage('res/fileNode.png'); function FileNode.new(name, color) local self = Node.new('file', name); + local fileColor = color; + local currentColor = {}; + local modified = false; + local timer = MOD_TIMER; + + -- ------------------------------------------------ + -- Private Function + -- ------------------------------------------------ + + local function lerp(a, b, t) + return a + (b - a) * t; + end + + -- ------------------------------------------------ + -- Public Function + -- ------------------------------------------------ + + --- + -- Draw the node with the current color modifier. + -- function self:draw() - love.graphics.setColor(color); + love.graphics.setColor(currentColor); love.graphics.draw(img, self:getX() - 8, self:getY() - 8); love.graphics.setColor(255, 255, 255); end + --- + -- If the file is marked as modified the color will be lerped from + -- the modified color to the default file color. + -- @param dt + -- + function self:update(dt) + if timer > 0 and modified then + timer = timer - dt; + currentColor[1] = lerp(currentColor[1], fileColor[1], dt * 1.5); + currentColor[2] = lerp(currentColor[2], fileColor[2], dt * 1.5); + currentColor[3] = lerp(currentColor[3], fileColor[3], dt * 1.5); + else + -- Reset values. + timer = MOD_TIMER; + modified = false; + currentColor[1] = fileColor[1] + currentColor[2] = fileColor[2]; + currentColor[3] = fileColor[3]; + end + end + + --- + -- Marks the file as modified and changes the + -- current color to the modified color. + -- @param mod + -- + function self:setModified(mod) + modified = mod; + currentColor[1] = MOD_COLOR[1]; + currentColor[2] = MOD_COLOR[2]; + currentColor[3] = MOD_COLOR[3]; + end + return self; end diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index cc488b0..0799b26 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -84,6 +84,9 @@ function MainScreen.new() if modifier == MODIFIER_ADD then -- Add file local color = FileManager.add(fileName); target:append(fileName, FileNode.new(fileName, color)); + elseif modifier == MODIFIER_MODIFY then + local file = target:getNode(fileName); + file:setModified(true); elseif modifier == MODIFIER_DELETE then FileManager.remove(fileName); target:remove(fileName); From 5c341ce96aa00b314dba5526084d23729751cc36 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sat, 17 Jan 2015 20:33:18 +0100 Subject: [PATCH 46/54] Mark newly added files as modified. Files which are newly added by the commit start in the "modified" state which means they will be assigned a color to make them stand out. This color will then slowly fade out to become the default file color based on the extension the file has. --- src/screens/MainScreen.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index 0799b26..9df06ff 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -84,6 +84,8 @@ function MainScreen.new() if modifier == MODIFIER_ADD then -- Add file local color = FileManager.add(fileName); target:append(fileName, FileNode.new(fileName, color)); + local file = target:getNode(fileName); + file:setModified(true); elseif modifier == MODIFIER_MODIFY then local file = target:getNode(fileName); file:setModified(true); From e0626239da30977304efca0c304f19edd20de4e1 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sat, 17 Jan 2015 16:59:40 +0100 Subject: [PATCH 47/54] Add floating author objects that "shoot" beams at the files they modify. The author objects spawn randomly across the screen and move in a random direction until they hit a boundary and move in the opposite direction. The link of each author to the files he edited is purged when a new commit is loaded. This needs to be done or else each author would leave the links from his last commit in the log and they would stay on the screen forever. --- src/Author.lua | 43 ++++++++++++++++++++++++++++++++++++++ src/AuthorManager.lua | 35 +++++++++++++++++++++++++++---- src/screens/MainScreen.lua | 26 +++++++++++++++++------ 3 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 src/Author.lua diff --git a/src/Author.lua b/src/Author.lua new file mode 100644 index 0000000..09df19b --- /dev/null +++ b/src/Author.lua @@ -0,0 +1,43 @@ +local Author = {}; + +function Author.new(name) + local self = {}; + + local name = name; + local posX, posY = love.math.random(100, 1000), love.math.random(100, 600); + local dX, dY = love.math.random(-50, 50), love.math.random(-50, 50); + local links = {}; + + function self:draw() + for i = 1, #links do + love.graphics.setColor(255, 255, 255, 50); + love.graphics.line(posX, posY, links[i]:getX(), links[i]:getY()); + love.graphics.setColor(255, 255, 255, 255); + end + love.graphics.circle('fill', posX, posY, 20, 20); + love.graphics.print(name, posX + 10, posY + 10); + end + + function self:update(dt) + if posX < 200 or posX > love.graphics.getWidth() - 200 then + dX = -dX; + end + if posY < 200 or posY > love.graphics.getHeight() - 200 then + dY = -dY; + end + posX = posX + (dX * dt); + posY = posY + (dY * dt); + end + + function self:addLink(file) + links[#links + 1] = file; + end + + function self:resetLinks() + links = {}; + end + + return self; +end + +return Author; \ No newline at end of file diff --git a/src/AuthorManager.lua b/src/AuthorManager.lua index 45d3caf..87cc147 100644 --- a/src/AuthorManager.lua +++ b/src/AuthorManager.lua @@ -1,3 +1,9 @@ +local Author = require('src/Author'); + +-- ------------------------------------------------ +-- Module +-- ------------------------------------------------ + local AuthorManager = {}; -- ------------------------------------------------ @@ -32,11 +38,27 @@ end --- -- Draws a list of all authors working on the project. -- -function AuthorManager.draw() +function AuthorManager.drawLabels() + for _, author in pairs(authors) do + author:draw(); + end +end + +function AuthorManager.drawList() local count = 0; - for author, _ in pairs(authors) do + for name, _ in pairs(authors) do count = count + 1; - love.graphics.print(author, 20, 100 + count * 20); + love.graphics.print(name, 20, 100 + count * 20); + end +end + +--- +-- Updates all authors. +-- @param dt +-- +function AuthorManager.update(dt) + for name, author in pairs(authors) do + author:update(dt); end end @@ -47,7 +69,12 @@ end -- @param nauthor -- function AuthorManager.add(nauthor) - authors[aliases[nauthor] or nauthor] = true; + local nickname = aliases[nauthor] or nauthor; + + if not authors[nickname] then + authors[nickname] = Author.new(nickname); + end + return authors[nickname]; end return AuthorManager; \ No newline at end of file diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index 9df06ff..5eccf24 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -38,8 +38,8 @@ function MainScreen.new() local commits; local root; local index = 0; - local author = ''; local date = ''; + local previousAuthor; local world; --- @@ -86,12 +86,17 @@ function MainScreen.new() target:append(fileName, FileNode.new(fileName, color)); local file = target:getNode(fileName); file:setModified(true); + return file; elseif modifier == MODIFIER_MODIFY then local file = target:getNode(fileName); file:setModified(true); + return file; elseif modifier == MODIFIER_DELETE then + local file = target:getNode(fileName); + file:setModified(true); FileManager.remove(fileName); target:remove(fileName); + return file; end end @@ -101,8 +106,8 @@ function MainScreen.new() end index = index + 1; - author = commits[index].author; - AuthorManager.add(author); + local commitAuthor = AuthorManager.add(commits[index].author); + previousAuthor = commitAuthor; -- Store author so we can reset him when the next commit is loaded. date = commits[index].date; @@ -118,7 +123,10 @@ function MainScreen.new() local target = createSubFolders(root, subfolders); -- Create the file node at the bottom of the current path tree. - modifyFileNodes(target, file, change.modifier); + file = modifyFileNodes(target, file, change.modifier); + + -- Add a link from the file to the author of the commit. + commitAuthor:addLink(file); end end @@ -135,12 +143,12 @@ function MainScreen.new() function self:draw() love.graphics.print(date, 20, 20); - love.graphics.print(author, 400, 20); - AuthorManager.draw(); FileManager.draw(); + AuthorManager.drawList(); camera:set(); root:draw(); + AuthorManager.drawLabels(); camera:unset(); end @@ -153,11 +161,17 @@ function MainScreen.new() timer = timer + dt; if timer > 0.2 then + -- Reset links of the previous author. + if previousAuthor then + previousAuthor:resetLinks(); + end nextCommit(); timer = 0; end root:update(dt); + + AuthorManager.update(dt); end return self; From 6fd627e2ee7b4c7f0058c567736e48769758e64d Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sat, 17 Jan 2015 21:24:43 +0100 Subject: [PATCH 48/54] User objects can be assigned an avatar. This avatar can be set via the avatars.lua file in the save directory of LoGiVi. Right now it is only possible to grab avatars from the internet, by assigning an url that points directly to an image file. LoGiVi will download this file to the computer of the user and then load it as an image file. If no avatar is assigned to an user, LoGiVi will use a default image. There seems to be an issue with some urls currently, which I couldn't fix yet. --- src/Author.lua | 16 +++++++++++++--- src/AuthorManager.lua | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/Author.lua b/src/Author.lua index 09df19b..db03d68 100644 --- a/src/Author.lua +++ b/src/Author.lua @@ -1,6 +1,17 @@ local Author = {}; -function Author.new(name) + +-- ------------------------------------------------ +-- Constants +-- ------------------------------------------------ + +local AVATAR_SIZE = 48; + +-- ------------------------------------------------ +-- Constructor +-- ------------------------------------------------ + +function Author.new(name, avatar) local self = {}; local name = name; @@ -14,8 +25,7 @@ function Author.new(name) love.graphics.line(posX, posY, links[i]:getX(), links[i]:getY()); love.graphics.setColor(255, 255, 255, 255); end - love.graphics.circle('fill', posX, posY, 20, 20); - love.graphics.print(name, posX + 10, posY + 10); + love.graphics.draw(avatar, posX - AVATAR_SIZE * 0.5, posY - AVATAR_SIZE * 0.5, 0, AVATAR_SIZE / avatar:getWidth(), AVATAR_SIZE / avatar:getHeight()); end function self:update(dt) diff --git a/src/AuthorManager.lua b/src/AuthorManager.lua index 87cc147..31c03f0 100644 --- a/src/AuthorManager.lua +++ b/src/AuthorManager.lua @@ -1,4 +1,5 @@ local Author = require('src/Author'); +local http = require('socket.http'); -- ------------------------------------------------ -- Module @@ -11,6 +12,7 @@ local AuthorManager = {}; -- ------------------------------------------------ local authors; +local avatars; local aliases; -- ------------------------------------------------ @@ -31,8 +33,35 @@ return { file:write(default); file:close(); end - aliases = love.filesystem.load('aliases.lua')(); + + avatars = {}; + -- Grab the default avatar online, write it to the save folder and load it as an image. + local body = http.request('https://www.love2d.org/w/images/9/9b/Love-game-logo-256x256.png'); + love.filesystem.write('tmp_default.png', body); + avatars['default'] = love.graphics.newImage('tmp_default.png'); + + -- Read the avatars.lua file (if there is one) and use it to grab an avatar online, write it + -- to the save folder and load it as an image to use in LoGiVi. + local counter = 0; + if not love.filesystem.isFile('avatars.lua') then + local file = love.filesystem.newFile('avatars.lua'); + local default = [[ +return { + -- ['user'] = 'UrlToAvatar', +}; +]]; + file:open('w'); + file:write(default); + file:close(); + end + local avatarFile = love.filesystem.load('avatars.lua')(); + for author, url in pairs(avatarFile) do + local body = http.request(url); + love.filesystem.write(string.format("tmp_%03d.png", counter), body); + avatars[author] = love.graphics.newImage(string.format("tmp_%03d.png", counter)); + counter = counter + 1; + end end --- @@ -72,7 +101,7 @@ function AuthorManager.add(nauthor) local nickname = aliases[nauthor] or nauthor; if not authors[nickname] then - authors[nickname] = Author.new(nickname); + authors[nickname] = Author.new(nickname, avatars[nickname] or avatars['default']); end return authors[nickname]; end From f91071b825ad433493b4ab2f31b0a130e79280c3 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sun, 18 Jan 2015 01:11:12 +0100 Subject: [PATCH 49/54] Fade out authors who have been inactive for a certain amount of time. The authors won't be removed from the system, but instead they will just be hidden (their alpha is slowly set to 0). When another commit is registered for this author his alpha and his inactivity-counter will be reset. --- src/Author.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Author.lua b/src/Author.lua index db03d68..b5add79 100644 --- a/src/Author.lua +++ b/src/Author.lua @@ -6,6 +6,9 @@ local Author = {}; -- ------------------------------------------------ local AVATAR_SIZE = 48; +local INACTIVITY_TIMER = 10; +local FADE_FACTOR = 2; +local DEFAULT_ALPHA = 255; -- ------------------------------------------------ -- Constructor @@ -18,6 +21,8 @@ function Author.new(name, avatar) local posX, posY = love.math.random(100, 1000), love.math.random(100, 600); local dX, dY = love.math.random(-50, 50), love.math.random(-50, 50); local links = {}; + local inactivity = 0; + local alpha = DEFAULT_ALPHA; function self:draw() for i = 1, #links do @@ -25,7 +30,9 @@ function Author.new(name, avatar) love.graphics.line(posX, posY, links[i]:getX(), links[i]:getY()); love.graphics.setColor(255, 255, 255, 255); end + love.graphics.setColor(255, 255, 255, alpha); love.graphics.draw(avatar, posX - AVATAR_SIZE * 0.5, posY - AVATAR_SIZE * 0.5, 0, AVATAR_SIZE / avatar:getWidth(), AVATAR_SIZE / avatar:getHeight()); + love.graphics.setColor(255, 255, 255, 255); end function self:update(dt) @@ -37,9 +44,20 @@ function Author.new(name, avatar) end posX = posX + (dX * dt); posY = posY + (dY * dt); + + inactivity = inactivity + dt; + if inactivity > INACTIVITY_TIMER then + alpha = alpha - alpha * dt * FADE_FACTOR; + end + end + + local function reactivate() + inactivity = 0; + alpha = DEFAULT_ALPHA; end function self:addLink(file) + reactivate(); links[#links + 1] = file; end From 4ad8d9723415474a0c27d9ccda020e07f9afed42 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sun, 18 Jan 2015 01:24:58 +0100 Subject: [PATCH 50/54] Refactoring. Cleaned up AuthorManager.lua by moving some variables to the top of the file as constants and making the code a bit more D.R.Y. --- src/AuthorManager.lua | 69 ++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/src/AuthorManager.lua b/src/AuthorManager.lua index 31c03f0..6520ba4 100644 --- a/src/AuthorManager.lua +++ b/src/AuthorManager.lua @@ -7,6 +7,25 @@ local http = require('socket.http'); local AuthorManager = {}; +-- ------------------------------------------------ +-- Constants +-- ------------------------------------------------ + +local DEFAULT_ALIASES_FILE_CONTENT = [[ +return { + -- ['NameToReplace'] = 'ReplaceWith', +}; +]]; + +local DEFAULT_AVATARS_FILE_CONTENT = [[ +return { + -- ['user'] = 'UrlToAvatar', +}; +]]; + +local ALIASES_FILE_NAME = 'aliases.lua'; +local AVATARS_FILE_NAME = 'avatars.lua'; + -- ------------------------------------------------ -- Local Variables -- ------------------------------------------------ @@ -16,24 +35,37 @@ local avatars; local aliases; -- ------------------------------------------------ --- Public Functions +-- Private Functions -- ------------------------------------------------ -function AuthorManager.init() - authors = {}; - local default = [[ -return { - -- ['NameToReplace'] = 'ReplaceWith', -}; -]]; - - if not love.filesystem.isFile('aliases.lua') then - local file = love.filesystem.newFile('aliases.lua'); +--- +-- Checks if the file already exists. If it does it is +-- loaded, executed and returned. If the file doesn't +-- exist yet a default file will be written instead. +-- This default file is then read and returned. +-- @param name +-- @param default +-- +local function loadFile(name, default) + if not love.filesystem.isFile(name) then + local file = love.filesystem.newFile(name); file:open('w'); file:write(default); file:close(); end - aliases = love.filesystem.load('aliases.lua')(); + return love.filesystem.load(name)(); +end + +-- ------------------------------------------------ +-- Public Functions +-- ------------------------------------------------ + +function AuthorManager.init() + -- Set up the table to store all authors. + authors = {}; + + -- Create an aliases default file or load an existing one. + aliases = loadFile(ALIASES_FILE_NAME, DEFAULT_ALIASES_FILE_CONTENT); avatars = {}; -- Grab the default avatar online, write it to the save folder and load it as an image. @@ -44,18 +76,7 @@ return { -- Read the avatars.lua file (if there is one) and use it to grab an avatar online, write it -- to the save folder and load it as an image to use in LoGiVi. local counter = 0; - if not love.filesystem.isFile('avatars.lua') then - local file = love.filesystem.newFile('avatars.lua'); - local default = [[ -return { - -- ['user'] = 'UrlToAvatar', -}; -]]; - file:open('w'); - file:write(default); - file:close(); - end - local avatarFile = love.filesystem.load('avatars.lua')(); + local avatarFile = loadFile(AVATARS_FILE_NAME, DEFAULT_AVATARS_FILE_CONTENT); for author, url in pairs(avatarFile) do local body = http.request(url); love.filesystem.write(string.format("tmp_%03d.png", counter), body); From 6d482322eca93c6cf7fec08cf853e62f6e3496e6 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sun, 18 Jan 2015 03:24:51 +0100 Subject: [PATCH 51/54] Hide the collider body. It only was drawn for debugging (to make sure the body resizes correctly when files are added on multiple layers around the folder node) anyway. --- src/nodes/FolderNode.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 0343206..9ca1481 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -181,10 +181,6 @@ function FolderNode.new(name, world, static, parent) end function self:draw() - love.graphics.setColor(0, 200, 0, 100); - love.graphics.circle("fill", collider.body:getX(), collider.body:getY(), collider.shape:getRadius()); - love.graphics.setColor(255, 255, 255); - for _, node in pairs(children) do if node:getType() == 'folder' then love.graphics.setColor(50, 50, 50); From b484b1eeaaefdb9fe46ab56cd3815d77cdbccbaf Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sun, 18 Jan 2015 03:39:57 +0100 Subject: [PATCH 52/54] Bump version. --- conf.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.lua b/conf.lua index a40842c..2a8faeb 100644 --- a/conf.lua +++ b/conf.lua @@ -2,7 +2,7 @@ local GAME_TITLE = "LoGiVi"; local LOVE_VERSION = "0.9.2"; -local GAME_VERSION = "0000"; +local GAME_VERSION = "0052"; -- ------------------------------------------------ -- Local variables From e62ce0f59114b3df743827ee445a3c15aca55d21 Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sun, 18 Jan 2015 03:41:40 +0100 Subject: [PATCH 53/54] Add copyright information. --- conf.lua | 26 ++++++++++++++++++++++---- main.lua | 26 ++++++++++++++++++++++---- src/Author.lua | 25 +++++++++++++++++++++++-- src/AuthorManager.lua | 24 +++++++++++++++++++++++- src/FileManager.lua | 24 +++++++++++++++++++++++- src/LogReader.lua | 28 +++++++++++++++++++++------- src/nodes/FileNode.lua | 26 ++++++++++++++++++++++---- src/nodes/FolderNode.lua | 22 ++++++++++++++++++++++ src/nodes/Node.lua | 28 +++++++++++++++++++++------- src/screens/MainScreen.lua | 26 ++++++++++++++++++++++---- 10 files changed, 221 insertions(+), 34 deletions(-) diff --git a/conf.lua b/conf.lua index 2a8faeb..a737141 100644 --- a/conf.lua +++ b/conf.lua @@ -1,3 +1,25 @@ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== + local GAME_TITLE = "LoGiVi"; local LOVE_VERSION = "0.9.2"; @@ -73,7 +95,3 @@ function getVersion() return GAME_VERSION; end end - ---================================================================================================== --- Created 01.10.14 - 11:29 = ---================================================================================================== \ No newline at end of file diff --git a/main.lua b/main.lua index 56dc933..3b40895 100644 --- a/main.lua +++ b/main.lua @@ -1,3 +1,25 @@ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== + local ScreenManager = require('lib/ScreenManager'); function love.load() @@ -19,7 +41,3 @@ end function love.update(dt) ScreenManager.update(dt); end - ---================================================================================================== --- Created 01.10.14 - 11:01 = ---================================================================================================== \ No newline at end of file diff --git a/src/Author.lua b/src/Author.lua index b5add79..77c8a14 100644 --- a/src/Author.lua +++ b/src/Author.lua @@ -1,5 +1,26 @@ -local Author = {}; +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== +local Author = {}; -- ------------------------------------------------ -- Constants @@ -68,4 +89,4 @@ function Author.new(name, avatar) return self; end -return Author; \ No newline at end of file +return Author; diff --git a/src/AuthorManager.lua b/src/AuthorManager.lua index 6520ba4..0426fa9 100644 --- a/src/AuthorManager.lua +++ b/src/AuthorManager.lua @@ -1,3 +1,25 @@ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== + local Author = require('src/Author'); local http = require('socket.http'); @@ -127,4 +149,4 @@ function AuthorManager.add(nauthor) return authors[nickname]; end -return AuthorManager; \ No newline at end of file +return AuthorManager; diff --git a/src/FileManager.lua b/src/FileManager.lua index ad2a59e..489e65e 100644 --- a/src/FileManager.lua +++ b/src/FileManager.lua @@ -1,3 +1,25 @@ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== + local FileManager = {}; -- ------------------------------------------------ @@ -80,4 +102,4 @@ function FileManager.getColor(ext) return extensions[ext].color; end -return FileManager; \ No newline at end of file +return FileManager; diff --git a/src/LogReader.lua b/src/LogReader.lua index d1e0b75..f00fed9 100644 --- a/src/LogReader.lua +++ b/src/LogReader.lua @@ -1,6 +1,24 @@ --- ------------------------------------------------ --- Constants --- ------------------------------------------------ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== local TAG_SEPARATOR = 'logivi_commit'; local TAG_AUTHOR = 'author: '; @@ -102,7 +120,3 @@ end -- ------------------------------------------------ return LogReader; - ---================================================================================================== --- Created 01.10.14 - 12:34 = ---================================================================================================== \ No newline at end of file diff --git a/src/nodes/FileNode.lua b/src/nodes/FileNode.lua index 7ec16e8..3cce24f 100644 --- a/src/nodes/FileNode.lua +++ b/src/nodes/FileNode.lua @@ -1,3 +1,25 @@ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== + local Node = require('src/nodes/Node'); -- ------------------------------------------------ @@ -93,7 +115,3 @@ end -- ------------------------------------------------ return FileNode; - ---================================================================================================== --- Created 01.10.14 - 14:41 = ---================================================================================================== \ No newline at end of file diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 9ca1481..3264d57 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -1,3 +1,25 @@ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== + local Node = require('src/nodes/Node'); -- ------------------------------------------------ diff --git a/src/nodes/Node.lua b/src/nodes/Node.lua index 8ffd69a..6f4633d 100644 --- a/src/nodes/Node.lua +++ b/src/nodes/Node.lua @@ -1,6 +1,24 @@ --- ------------------------------------------------ --- Module --- ------------------------------------------------ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== local Node = {}; @@ -49,7 +67,3 @@ end -- ------------------------------------------------ return Node; - ---================================================================================================== --- Created 16.10.14 - 14:47 = ---================================================================================================== diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index 5eccf24..4303eb5 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -1,3 +1,25 @@ +--================================================================================================== +-- Copyright (C) 2014 - 2015 by Robert Machmer = +-- = +-- Permission is hereby granted, free of charge, to any person obtaining a copy = +-- of this software and associated documentation files (the "Software"), to deal = +-- in the Software without restriction, including without limitation the rights = +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell = +-- copies of the Software, and to permit persons to whom the Software is = +-- furnished to do so, subject to the following conditions: = +-- = +-- The above copyright notice and this permission notice shall be included in = +-- all copies or substantial portions of the Software. = +-- = +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR = +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, = +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE = +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER = +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, = +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN = +-- THE SOFTWARE. = +--================================================================================================== + local Screen = require('lib/Screen'); local LogReader = require('src/LogReader'); local FolderNode = require('src/nodes/FolderNode'); @@ -182,7 +204,3 @@ end -- ------------------------------------------------ return MainScreen; - ---================================================================================================== --- Created 01.10.14 - 13:18 = ---================================================================================================== From 247914c52ffe5ce53c7e73e1d02e0193c64f8fbb Mon Sep 17 00:00:00 2001 From: Robert Machmer Date: Sun, 18 Jan 2015 04:02:02 +0100 Subject: [PATCH 54/54] Clean up code. Add comments, add delimiters, restructure files... --- main.lua | 4 ++++ src/Author.lua | 22 +++++++++++++++++----- src/AuthorManager.lua | 4 ++++ src/FileManager.lua | 11 +++++++++++ src/LogReader.lua | 26 ++++++++++++++++++++------ src/nodes/FileNode.lua | 4 ++-- src/nodes/FolderNode.lua | 20 ++++++++++++++++---- src/screens/MainScreen.lua | 16 ++++++++++++---- 8 files changed, 86 insertions(+), 21 deletions(-) diff --git a/main.lua b/main.lua index 3b40895..7394377 100644 --- a/main.lua +++ b/main.lua @@ -22,6 +22,10 @@ local ScreenManager = require('lib/ScreenManager'); +-- ------------------------------------------------ +-- Callbacks +-- ------------------------------------------------ + function love.load() local screens = { main = require('src/screens/MainScreen'); diff --git a/src/Author.lua b/src/Author.lua index 77c8a14..8d53815 100644 --- a/src/Author.lua +++ b/src/Author.lua @@ -45,6 +45,19 @@ function Author.new(name, avatar) local inactivity = 0; local alpha = DEFAULT_ALPHA; + -- ------------------------------------------------ + -- Private Functions + -- ------------------------------------------------ + + local function reactivate() + inactivity = 0; + alpha = DEFAULT_ALPHA; + end + + -- ------------------------------------------------ + -- Public Functions + -- ------------------------------------------------ + function self:draw() for i = 1, #links do love.graphics.setColor(255, 255, 255, 50); @@ -72,11 +85,6 @@ function Author.new(name, avatar) end end - local function reactivate() - inactivity = 0; - alpha = DEFAULT_ALPHA; - end - function self:addLink(file) reactivate(); links[#links + 1] = file; @@ -89,4 +97,8 @@ function Author.new(name, avatar) return self; end +-- ------------------------------------------------ +-- Return Module +-- ------------------------------------------------ + return Author; diff --git a/src/AuthorManager.lua b/src/AuthorManager.lua index 0426fa9..9bde5b7 100644 --- a/src/AuthorManager.lua +++ b/src/AuthorManager.lua @@ -149,4 +149,8 @@ function AuthorManager.add(nauthor) return authors[nickname]; end +-- ------------------------------------------------ +-- Return Module +-- ------------------------------------------------ + return AuthorManager; diff --git a/src/FileManager.lua b/src/FileManager.lua index 489e65e..c942476 100644 --- a/src/FileManager.lua +++ b/src/FileManager.lua @@ -98,8 +98,19 @@ function FileManager.remove(fileName) end end +-- ------------------------------------------------ +-- Getters +-- ------------------------------------------------ + +--- +-- @param ext +-- function FileManager.getColor(ext) return extensions[ext].color; end +-- ------------------------------------------------ +-- Return Module +-- ------------------------------------------------ + return FileManager; diff --git a/src/LogReader.lua b/src/LogReader.lua index f00fed9..a891782 100644 --- a/src/LogReader.lua +++ b/src/LogReader.lua @@ -30,6 +30,20 @@ local TAG_DATE = 'date'; local LogReader = {}; +-- ------------------------------------------------ +-- Constants +-- ------------------------------------------------ + +local WARNING_MESSAGE = [[ +To use LoGiVi you will have to generate a git log first. See the readme for instructions on how to generate a proper log. + +LoGiVi now will open the file directory in which to place the log. +]]; + +-- ------------------------------------------------ +-- Local Functions +-- ------------------------------------------------ + --- -- Remove leading and trailing whitespace. -- @param str @@ -87,18 +101,17 @@ end -- local function isLogFile(name) if not love.filesystem.isFile(name) then - local msg = [[ -To use LoGiVi you will have to generate a git log first. See the readme for instructions on how to generate a proper log. - -LoGiVi now will open the file directory in which to place the log. -]]; - love.window.showMessageBox('No git log found.', msg, 'warning', false); + love.window.showMessageBox('No git log found.', WARNING_MESSAGE, 'warning', false); love.system.openURL('file://' .. love.filesystem.getSaveDirectory()); return false; end return true; end +-- ------------------------------------------------ +-- Public Functions +-- ------------------------------------------------ + --- -- Loads the file and stores it line for line in a lua table. -- @param name @@ -112,6 +125,7 @@ function LogReader.loadLog(name) for line in love.filesystem.lines(name) do log[#log + 1] = line; end + return splitCommits(log); end diff --git a/src/nodes/FileNode.lua b/src/nodes/FileNode.lua index 3cce24f..ff580c9 100644 --- a/src/nodes/FileNode.lua +++ b/src/nodes/FileNode.lua @@ -54,7 +54,7 @@ function FileNode.new(name, color) local timer = MOD_TIMER; -- ------------------------------------------------ - -- Private Function + -- Private Functions -- ------------------------------------------------ local function lerp(a, b, t) @@ -62,7 +62,7 @@ function FileNode.new(name, color) end -- ------------------------------------------------ - -- Public Function + -- Public Functions -- ------------------------------------------------ --- diff --git a/src/nodes/FolderNode.lua b/src/nodes/FolderNode.lua index 3264d57..eca8851 100644 --- a/src/nodes/FolderNode.lua +++ b/src/nodes/FolderNode.lua @@ -61,6 +61,10 @@ function FolderNode.new(name, world, static, parent) end self:setPosition(collider.body:getX(), collider.body:getY()); + -- ------------------------------------------------ + -- Private Functions + -- ------------------------------------------------ + --- -- Counts the amount of children nodes that represent files. -- @@ -202,6 +206,10 @@ function FolderNode.new(name, world, static, parent) end end + -- ------------------------------------------------ + -- Public Functions + -- ------------------------------------------------ + function self:draw() for _, node in pairs(children) do if node:getType() == 'folder' then @@ -228,10 +236,6 @@ function FolderNode.new(name, world, static, parent) self:setPosition(collider.body:getX(), collider.body:getY()); end - function self:getNode(name) - return children[name]; - end - function self:append(name, node) if not children[name] then children[name] = node; @@ -243,6 +247,14 @@ function FolderNode.new(name, world, static, parent) children[name] = nil; end + -- ------------------------------------------------ + -- Getters + -- ------------------------------------------------ + + function self:getNode(name) + return children[name]; + end + function self:getColliderBody() return collider.body; end diff --git a/src/screens/MainScreen.lua b/src/screens/MainScreen.lua index 4303eb5..e64c1ea 100644 --- a/src/screens/MainScreen.lua +++ b/src/screens/MainScreen.lua @@ -63,6 +63,11 @@ function MainScreen.new() local date = ''; local previousAuthor; local world; + local commitTimer = 0; + + -- ------------------------------------------------ + -- Private Functions + -- ------------------------------------------------ --- -- @param path @@ -152,6 +157,10 @@ function MainScreen.new() end end + -- ------------------------------------------------ + -- Public Functions + -- ------------------------------------------------ + function self:init() AuthorManager.init(); @@ -174,21 +183,20 @@ function MainScreen.new() camera:unset(); end - local timer = 0; function self:update(dt) world:update(dt) --this puts the world into motion camera:checkEdges(root); camera:update(dt); - timer = timer + dt; - if timer > 0.2 then + commitTimer = commitTimer + dt; + if commitTimer > 0.2 then -- Reset links of the previous author. if previousAuthor then previousAuthor:resetLinks(); end nextCommit(); - timer = 0; + commitTimer = 0; end root:update(dt);