Sneaking in a few more features

- Sort button for 'All items' list
- Improved keyboard interaction
This commit is contained in:
Openarl
2016-11-21 02:54:19 +10:00
parent 5b0bc604ad
commit 867df49074
14 changed files with 161 additions and 41 deletions

View File

@@ -41,6 +41,13 @@ function BuildListClass:ScrollSelIntoView()
end
end
function BuildListClass:SelectIndex(index)
if self.listMode.list[index] then
self.listMode.sel = index
self:ScrollSelIntoView()
end
end
function BuildListClass:IsMouseOver()
if not self:IsShown() then
return
@@ -134,6 +141,14 @@ function BuildListClass:OnKeyDown(key, doubleClick)
end
end
end
elseif key == "UP" then
self:SelectIndex(((self.listMode.sel or 1) - 2) % #self.listMode.list + 1)
elseif key == "DOWN" then
self:SelectIndex((self.listMode.sel or #self.listMode.list) % #self.listMode.list + 1)
elseif key == "HOME" then
self:SelectIndex(1)
elseif key == "END" then
self:SelectIndex(#self.listMode.list)
elseif self.listMode.sel then
if key == "BACK" or key == "DELETE" then
self.listMode:DeleteSel()

View File

@@ -11,6 +11,12 @@ local ButtonClass = common.NewClass("ButtonControl", "Control", function(self, a
self.onClick = onClick
end)
function ButtonClass:Click()
if self:IsShown() and self:IsEnabled() then
self.onClick()
end
end
function ButtonClass:IsMouseOver()
if not self:IsShown() then
return false

View File

@@ -160,6 +160,14 @@ function ItemDBClass:BuildOrderList()
end)
end
function ItemDBClass:SelectIndex(index)
self.selItem = self.orderList[index]
if self.selItem then
self.selIndex = index
self.controls.scrollBar:ScrollIntoView((index - 2) * 16, 48)
end
end
function ItemDBClass:IsMouseOver()
if not self:IsShown() then
return
@@ -242,6 +250,7 @@ function ItemDBClass:OnKeyDown(key, doubleClick)
end
if key == "LEFTBUTTON" then
self.selItem = nil
self.selIndex = nil
local x, y = self:GetPos()
local width, height = self:GetSize()
local cursorX, cursorY = GetCursorPos()
@@ -283,6 +292,14 @@ function ItemDBClass:OnKeyDown(key, doubleClick)
self.selDragging = true
self.selDragActive = false
end
elseif key == "UP" then
self:SelectIndex(((self.selIndex or 1) - 2) % #self.orderList + 1)
elseif key == "DOWN" then
self:SelectIndex((self.selIndex or #self.orderList) % #self.orderList + 1)
elseif key == "HOME" then
self:SelectIndex(1)
elseif key == "END" then
self:SelectIndex(#self.orderList)
elseif key == "c" and IsKeyDown("CTRL") then
if self.selItem then
Copy(self.selItem.raw:gsub("\n","\r\n"))
@@ -325,6 +342,7 @@ function ItemDBClass:OnKeyUp(key)
self.itemsTab.build.buildFlag = true
end
self.selItem = nil
self.selIndex = nil
return
end
end

View File

@@ -20,6 +20,33 @@ local ItemListClass = common.NewClass("ItemList", "Control", "ControlHost", func
local width, height = self:GetSize()
return height - 2
end
self.controls.sort = common.New("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, -64, -2, 60, 18, "Sort", function()
table.sort(itemsTab.orderList, function(a, b)
local itemA = itemsTab.list[a]
local itemB = itemsTab.list[b]
local primSlotA = itemLib.getPrimarySlotForItem(itemA)
local primSlotB = itemLib.getPrimarySlotForItem(itemB)
if primSlotA ~= primSlotB then
if not itemsTab.slotOrder[primSlotA] then
return false
elseif not itemsTab.slotOrder[primSlotB] then
return true
end
return itemsTab.slotOrder[primSlotA] < itemsTab.slotOrder[primSlotB]
end
local equipSlotA = itemsTab:GetEquippedSlotForItem(itemA)
local equipSlotB = itemsTab:GetEquippedSlotForItem(itemB)
if equipSlotA and equipSlotB then
return itemsTab.slotOrder[equipSlotA.slotName] < itemsTab.slotOrder[equipSlotB.slotName]
elseif not equipSlotA then
return false
elseif not equipSlotB then
return true
end
return itemA.name < itemB.name
end)
itemsTab:AddUndoState()
end)
self.controls.delete = common.New("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, 0, -2, 60, 18, "Delete", function()
self:OnKeyUp("DELETE")
end)
@@ -28,6 +55,15 @@ local ItemListClass = common.NewClass("ItemList", "Control", "ControlHost", func
end
end)
function ItemListClass:SelectIndex(index)
local selItemId = self.itemsTab.orderList[index]
if selItemId then
self.selItem = self.itemsTab.list[selItemId]
self.selIndex = index
self.controls.scrollBar:ScrollIntoView((index - 2) * 16, 48)
end
end
function ItemListClass:IsMouseOver()
if not self:IsShown() then
return
@@ -134,6 +170,7 @@ function ItemListClass:OnKeyDown(key, doubleClick)
end
if key == "LEFTBUTTON" then
self.selItem = nil
self.selIndex = nil
local x, y = self:GetPos()
local width, height = self:GetSize()
local cursorX, cursorY = GetCursorPos()
@@ -173,6 +210,14 @@ function ItemListClass:OnKeyDown(key, doubleClick)
self.selDragging = true
self.selDragActive = false
end
elseif key == "UP" then
self:SelectIndex(((self.selIndex or 1) - 2) % #self.itemsTab.orderList + 1)
elseif key == "DOWN" then
self:SelectIndex((self.selIndex or #self.itemsTab.orderList) % #self.itemsTab.orderList + 1)
elseif key == "HOME" then
self:SelectIndex(1)
elseif key == "END" then
self:SelectIndex(#self.itemsTab.orderList)
elseif key == "c" and IsKeyDown("CTRL") then
if self.selItem then
Copy(self.selItem.raw:gsub("\n","\r\n"))
@@ -196,10 +241,12 @@ function ItemListClass:OnKeyUp(key)
main:OpenConfirmPopup("Delete Item", self.selItem.name.." is currently equipped in "..equipSlot.label..".\nAre you sure you want to delete it?", "Delete", function()
self.itemsTab:DeleteItem(self.selItem)
self.selItem = nil
self.selIndex = nil
end)
else
self.itemsTab:DeleteItem(self.selItem)
self.selItem = nil
self.selIndex = nil
end
elseif key == "LEFTBUTTON" then
self.selDragging = false
@@ -214,6 +261,7 @@ function ItemListClass:OnKeyUp(key)
t_insert(self.itemsTab.orderList, self.selDragIndex, self.selItem.id)
self.itemsTab:AddUndoState()
self.selItem = nil
self.selIndex = nil
end
else
for slotName, slot in pairs(self.itemsTab.slots) do
@@ -225,6 +273,7 @@ function ItemListClass:OnKeyUp(key)
self.itemsTab.build.buildFlag = true
end
self.selItem = nil
self.selIndex = nil
return
end
end

View File

@@ -31,6 +31,7 @@ local ItemSlotClass = common.NewClass("ItemSlot", "DropDownControl", function(se
self.label = slotLabel or slotName
self.nodeId = nodeId
itemsTab.slots[slotName] = self
t_insert(itemsTab.orderedSlots, self)
end)
function ItemSlotClass:Populate()

View File

@@ -27,8 +27,11 @@ local ItemsTabClass = common.NewClass("ItemsTab", "UndoHandler", "ControlHost",
-- Item slots
self.slots = { }
for index, slotName in pairs(baseSlots) do
self.orderedSlots = { }
self.slotOrder = { }
for index, slotName in ipairs(baseSlots) do
t_insert(self.controls, common.New("ItemSlot", {"TOPLEFT",self,"TOPLEFT"}, 96, (index - 1) * 20 + 24, self, slotName))
self.slotOrder[slotName] = index
end
self.sockets = { }
for _, node in pairs(main.tree.nodes) do
@@ -36,12 +39,16 @@ local ItemsTabClass = common.NewClass("ItemsTab", "UndoHandler", "ControlHost",
local socketControl = common.New("ItemSlot", {"TOPLEFT",self,"TOPLEFT"}, 96, 0, self, "Jewel "..node.id, "Socket", node.id)
self.controls["socket"..node.id] = socketControl
self.sockets[node.id] = socketControl
self.slotOrder["Jewel "..node.id] = #baseSlots + 1 + node.id
end
end
self.controls.slotHeader = common.New("LabelControl", {"BOTTOMLEFT",self.slots[baseSlots[1]],"TOPLEFT"}, 0, -4, 0, 16, "^7Equipped items:")
table.sort(self.orderedSlots, function(a, b)
return self.slotOrder[a.slotName] < self.slotOrder[b.slotName]
end)
self.controls.slotHeader = common.New("LabelControl", {"BOTTOMLEFT",self.orderedSlots[1],"TOPLEFT"}, 0, -4, 0, 16, "^7Equipped items:")
-- Build item list
self.controls.itemList = common.New("ItemList", {"TOPLEFT",self.slots[baseSlots[1]],"TOPRIGHT"}, 20, 0, 360, 308, self)
self.controls.itemList = common.New("ItemList", {"TOPLEFT",self.orderedSlots[1],"TOPRIGHT"}, 20, 0, 360, 308, self)
-- Database selector
self.controls.selectDBLabel = common.New("LabelControl", {"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, 0, 14, 0, 16, "^7Import from:")
@@ -335,10 +342,9 @@ function ItemsTabClass:DeleteItem(item)
self:AddUndoState()
end
-- Returns a slot in which the given item is equipped, if one exists
-- If the item is equipped in multiple slots, the return value may be any of those slots
-- Returns the first slot in which the given item is equipped
function ItemsTabClass:GetEquippedSlotForItem(item)
for _, slot in pairs(self.slots) do
for _, slot in ipairs(self.orderedSlots) do
if not slot.inactive and slot.selItemId == item.id then
return slot
end

View File

@@ -7,7 +7,7 @@ local launch, main = ...
local m_floor = math.floor
local PopupDialogClass = common.NewClass("PopupDialog", "ControlHost", "Control", function(self, width, height, title, controls)
local PopupDialogClass = common.NewClass("PopupDialog", "ControlHost", "Control", function(self, width, height, title, controls, enterControl, defaultControl)
self.ControlHost()
self.Control(nil, 0, 0, width, height)
self.x = function()
@@ -18,6 +18,7 @@ local PopupDialogClass = common.NewClass("PopupDialog", "ControlHost", "Control"
end
self.title = title
self.controls = controls
self.enterControl = enterControl
for id, control in pairs(self.controls) do
if not control.anchor.point then
control:SetAnchor("TOP", self, "TOP")
@@ -27,6 +28,9 @@ local PopupDialogClass = common.NewClass("PopupDialog", "ControlHost", "Control"
control.anchor.other = self.controls[control.anchor.other]
end
end
if defaultControl then
self:SelectControl(self.controls[defaultControl])
end
end)
function PopupDialogClass:Draw(viewPort)
@@ -57,6 +61,11 @@ function PopupDialogClass:ProcessInput(inputEvents, viewPort)
if event.key == "ESCAPE" then
main:ClosePopup()
return
elseif event.key == "RETURN" then
if self.enterControl then
self.controls[self.enterControl]:Click()
return
end
end
end
end

View File

@@ -47,6 +47,15 @@ local SkillListClass = common.NewClass("SkillList", "Control", "ControlHost", fu
end)
end)
function SkillListClass:SelectIndex(index)
self.selGroup = self.skillsTab.socketGroupList[index]
if self.selGroup then
self.selIndex = index
self.skillsTab:SetDisplayGroup(self.selGroup)
self.controls.scrollBar:ScrollIntoView((index - 2) * 16, 48)
end
end
function SkillListClass:IsMouseOver()
if not self:IsShown() then
return
@@ -229,13 +238,13 @@ function SkillListClass:OnKeyDown(key, doubleClick)
end
elseif #self.skillsTab.socketGroupList > 0 then
if key == "UP" then
self.selIndex = ((self.selIndex or 1) - 2) % #self.skillsTab.socketGroupList + 1
self.selGroup = self.skillsTab.socketGroupList[self.selIndex]
self.skillsTab:SetDisplayGroup(self.selGroup)
self:SelectIndex(((self.selIndex or 1) - 2) % #self.skillsTab.socketGroupList + 1)
elseif key == "DOWN" then
self.selIndex = (self.selIndex or #self.skillsTab.socketGroupList) % #self.skillsTab.socketGroupList + 1
self.selGroup = self.skillsTab.socketGroupList[self.selIndex]
self.skillsTab:SetDisplayGroup(self.selGroup)
self:SelectIndex((self.selIndex or #self.skillsTab.socketGroupList) % #self.skillsTab.socketGroupList + 1)
elseif key == "HOME" then
self:SelectIndex(1)
elseif key == "END" then
self:SelectIndex(#self.skillsTab.socketGroupList)
end
end
return self

View File

@@ -32,7 +32,7 @@ local TreeTabClass = common.NewClass("TreeTab", "ControlHost", function(self, bu
showMsg = nil
end),
common.New("LabelControl", nil, 0, 58, 0, 16, function() return showMsg or "" end),
common.New("ButtonControl", nil, -45, 80, 80, 20, "Import", function()
import = common.New("ButtonControl", nil, -45, 80, 80, 20, "Import", function()
if #treeLink > 0 then
if treeLink:match("poeurl%.com/") then
local curl = require("lcurl")
@@ -63,8 +63,7 @@ local TreeTabClass = common.NewClass("TreeTab", "ControlHost", function(self, bu
common.New("ButtonControl", nil, 45, 80, 80, 20, "Cancel", function()
main:ClosePopup()
end),
})
popup:SelectControl(popup.controls.edit)
}, "import", "edit")
end)
self.controls.export = common.New("ButtonControl", {"LEFT",self.controls.import,"RIGHT"}, 8, 0, 90, 20, "Export Tree", function()
local treeLink = self.build.spec:EncodeURL("https://www.pathofexile.com/passive-skill-tree/")
@@ -89,11 +88,10 @@ local TreeTabClass = common.NewClass("TreeTab", "ControlHost", function(self, bu
common.New("ButtonControl", nil, 30, 70, 80, 20, "Copy", function()
Copy(treeLink)
end),
common.New("ButtonControl", nil, 120, 70, 80, 20, "Done", function()
done = common.New("ButtonControl", nil, 120, 70, 80, 20, "Done", function()
main:ClosePopup()
end),
})
popup:SelectControl(popup.controls.edit)
}, "done", "edit")
end)
self.controls.treeSearch = common.New("EditControl", {"LEFT",self.controls.export,"RIGHT"}, 8, 0, 400, 20, "", "Search", "[^%c%(%)]", 100, function(buf)
self.viewer.searchStr = buf

View File

@@ -95,9 +95,8 @@ function buildMode:Init(dbFileName, buildName)
common.New("ButtonControl", nil, 45, 70, 80, 20, "Cancel", function()
main:ClosePopup()
end),
})
}, "save", "edit")
popup.controls.save.enabled = false
popup:SelectControl(popup.controls.edit)
end)
-- Controls: top bar, right side

View File

@@ -369,8 +369,8 @@ function main:DrawCheckMark(x, y, size)
DrawImageQuad(nil, x + size * 0.40, y + size * 0.90, x + size * 0.35, y + size * 0.75, x + size * 0.80, y + size * 0.10, x + size * 0.90, y + size * 0.20)
end
function main:OpenPopup(width, height, title, controls)
local popup = common.New("PopupDialog", width, height, title, controls)
function main:OpenPopup(width, height, title, controls, enterControl, defaultControl)
local popup = common.New("PopupDialog", width, height, title, controls, enterControl, defaultControl)
t_insert(self.popups, popup)
return popup
end
@@ -386,10 +386,10 @@ function main:OpenMessagePopup(title, msg)
t_insert(controls, common.New("LabelControl", nil, 0, 20 + numMsgLines * 16, 0, 16, line))
numMsgLines = numMsgLines + 1
end
t_insert(controls, common.New("ButtonControl", nil, 0, 40 + numMsgLines * 16, 80, 20, "Ok", function()
controls.close = common.New("ButtonControl", nil, 0, 40 + numMsgLines * 16, 80, 20, "Ok", function()
main:ClosePopup()
end))
return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls)
end)
return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close")
end
function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm)
@@ -399,14 +399,14 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm)
t_insert(controls, common.New("LabelControl", nil, 0, 20 + numMsgLines * 16, 0, 16, line))
numMsgLines = numMsgLines + 1
end
t_insert(controls, common.New("ButtonControl", nil, -45, 40 + numMsgLines * 16, 80, 20, confirmLabel, function()
controls.confirm = common.New("ButtonControl", nil, -45, 40 + numMsgLines * 16, 80, 20, confirmLabel, function()
onConfirm()
main:ClosePopup()
end))
end)
t_insert(controls, common.New("ButtonControl", nil, 45, 40 + numMsgLines * 16, 80, 20, "Cancel", function()
main:ClosePopup()
end))
return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls)
return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm")
end
function main:AddTooltipLine(size, text)

View File

@@ -51,6 +51,11 @@ Head over to the [Releases](https://github.com/Openarl/PathOfBuilding/releases)
## Changelog
### 1.2.10 - 2016/11/21
* Added support for Unholy Might; you can enable it in the Configuration tab in the Combat section
* Added a Sort button to the "All items" list in the Items tab
* Improved keyboard interaction throughout the program:
* Enabled keyboard navigation for all lists
* 'Enter' now accepts confirmation popups, and other popups such as "Save As"
* Dropdown lists can be cycled with Up/Down as well as the mousewheel
* Fixed Elreon's -mana cost modifier increasing the mana cost instead of decreasing it
### 1.2.9 - 2016/11/20

View File

@@ -1,5 +1,10 @@
VERSION[1.2.10][2016/11/21]
* Added support for Unholy Might; you can enable it in the Configuration tab in the Combat section
* Added a Sort button to the "All items" list in the Items tab
* Improved keyboard interaction throughout the program:
* Enabled keyboard navigation for all lists
* 'Enter' now accepts confirmation popups, and other popups such as "Save As"
* Dropdown lists can be cycled with Up/Down as well as the mousewheel
* Fixed Elreon's -mana cost modifier increasing the mana cost instead of decreasing it
VERSION[1.2.9][2016/11/20]
* Blade Flurry now shows DPS instead of average damage

View File

@@ -7,9 +7,9 @@
<File sha1="6bb074e0d3a4043f0e5dcbd25c33f8e5e1f5cfe0" name="Launch.lua" part="program"/>
<File sha1="93e19c2a160eb49993d50d9e2b47ea79962373d9" name="UpdateCheck.lua" part="program"/>
<File sha1="4f17937f2b37784e169a3792b235f2a0a3961e61" name="UpdateApply.lua" part="program"/>
<File sha1="06ab8a69b017e470ab093298b3d81d217b065b12" name="changelog.txt" part="program"/>
<File sha1="ea886e9e8ce013ed7d8805174d43becdca1f533e" name="Classes/BuildListControl.lua" part="program"/>
<File sha1="e42437dd7e1b5a1032f1be9852ede4399a003826" name="Classes/ButtonControl.lua" part="program"/>
<File sha1="5c00501920ba639d7f80e3eeb4fe842ccba56519" name="changelog.txt" part="program"/>
<File sha1="8f552be8544dbfb32882cb9dbba1907ce9a67522" name="Classes/BuildListControl.lua" part="program"/>
<File sha1="331c2ab54695ed4f0b48dd00b516857678766719" name="Classes/ButtonControl.lua" part="program"/>
<File sha1="8df790619a3284b8ed78075f59dd34d5b00d28a3" name="Classes/CalcBreakdownControl.lua" part="program"/>
<File sha1="23171916fa590c5344b17e67bd8d378574922388" name="Classes/CalcSectionControl.lua" part="program"/>
<File sha1="57ac3bdfbe1fe07539326e983a6df92a60c2cb78" name="Classes/CalcsTab.lua" part="program"/>
@@ -21,34 +21,34 @@
<File sha1="6f2e9d28d084a87fab4c12929938085feff27478" name="Classes/EditControl.lua" part="program"/>
<File sha1="dca9446ea1a4846f6de2147b25df7818826f9942" name="Classes/GemSelectControl.lua" part="program"/>
<File sha1="760dd37813ea5a2fa5f746de2cfa864abc15695c" name="Classes/ImportTab.lua" part="program"/>
<File sha1="a9d92fa939c186706876a869540364647718be38" name="Classes/ItemDBControl.lua" part="program"/>
<File sha1="1d35b4c7c20bb6380c8b739658101fb1bf37cc3c" name="Classes/ItemListControl.lua" part="program"/>
<File sha1="b547357491a4faec1d007ae44604b75e05a2613c" name="Classes/ItemSlotControl.lua" part="program"/>
<File sha1="0904a0c9856aef974fce28e3ae084349202b6d8b" name="Classes/ItemsTab.lua" part="program"/>
<File sha1="6ce8eb56061bf77ce3421f6cfe32e82b1d4814db" name="Classes/ItemDBControl.lua" part="program"/>
<File sha1="2e3025ba6a0c6e5bbabe047aa53d50ed18e1be6e" name="Classes/ItemListControl.lua" part="program"/>
<File sha1="e0214289f3f946a387800ff4ef11a823abb846b2" name="Classes/ItemSlotControl.lua" part="program"/>
<File sha1="6c1bd3d91174c2417731ee0ae67040720ea2a504" name="Classes/ItemsTab.lua" part="program"/>
<File sha1="62138c7db82d57d638a16610a26acd0de75d3486" name="Classes/LabelControl.lua" part="program"/>
<File sha1="a26d1a34424222856ad018ac43e3c7895d7f05b5" name="Classes/ModDB.lua" part="program"/>
<File sha1="a3ed881ebe1ed7c8931675937b4661d77decc316" name="Classes/ModList.lua" part="program"/>
<File sha1="6f8f98d6ee505af53441c1fe9ad74fbff86d56ad" name="Classes/PassiveSpec.lua" part="program"/>
<File sha1="9a6bce38a62d9c07851cdd095e91f088e37cea4e" name="Classes/PassiveTree.lua" part="program"/>
<File sha1="5a136be72fe9722bf59ac6f85dc411a16165e65e" name="Classes/PassiveTreeView.lua" part="program"/>
<File sha1="b5d4e4e7cedcabefa029cdefc74db5ac0a82d87f" name="Classes/PopupDialog.lua" part="program"/>
<File sha1="fd75c7a6a55b13163ac4068bbef9cb49a898eb24" name="Classes/PopupDialog.lua" part="program"/>
<File sha1="86fee3127d9520144fc741f6fccc3c1d9f1aa532" name="Classes/ScrollBarControl.lua" part="program"/>
<File sha1="261dcf54a4542e6160fd7024d8edf4fc095d9c71" name="Classes/SectionControl.lua" part="program"/>
<File sha1="48da9a792d6c23ab2bf4821388bdca8b5a09cd62" name="Classes/SkillListControl.lua" part="program"/>
<File sha1="a29cf1ce2135742b3182143de40d291056ccaef5" name="Classes/SkillListControl.lua" part="program"/>
<File sha1="45d425fc2968e07ee4b1505a391a4c319d6fed0c" name="Classes/SkillsTab.lua" part="program"/>
<File sha1="6317bd9ba391832dccafcb62409a5ce2988d1928" name="Classes/SliderControl.lua" part="program"/>
<File sha1="80527e0e05c986355ce7af2ba026538aec99a63a" name="Classes/SlotSelectControl.lua" part="program"/>
<File sha1="a4f9cc96ba474d0a75c768a0eabec92837e027cf" name="Classes/TextListControl.lua" part="program"/>
<File sha1="8b8fbea27b00c702ea7bcffa6945cc814cc2fa41" name="Classes/TreeTab.lua" part="program"/>
<File sha1="c1fe2beba55e93d284ed1b418af3a2c0adf57e5f" name="Classes/TreeTab.lua" part="program"/>
<File sha1="4b7675c8b4fe71cade7dd3d70793df1ed8022d01" name="Classes/UndoHandler.lua" part="program"/>
<File sha1="75cac21dc38aa8ff266ba7362ba4abfb27092774" name="Modules/Build.lua" part="program"/>
<File sha1="3e3422b86e9599a2543074faefb661bb547fd13f" name="Modules/Build.lua" part="program"/>
<File sha1="c03a7796aea3e9aa832fbb92c1f674ef5af690ca" name="Modules/BuildList.lua" part="program"/>
<File sha1="c4d10a3899c11b004910d6ecf58511b836a5d48c" name="Modules/Calcs.lua" part="program"/>
<File sha1="99148774ffc1c326f3a50e7d8b3f7a68fe1ede57" name="Modules/CalcSections.lua" part="program"/>
<File sha1="f207df4010cb3c7bc6cce98be2529a3b8a708b8f" name="Modules/Common.lua" part="program"/>
<File sha1="0deb086a2fcf8aa8637d59ef6f2b825354b9b2c3" name="Modules/Data.lua" part="program"/>
<File sha1="5ddfa4a5904cefbf2755c231797175c8ae24ac49" name="Modules/ItemTools.lua" part="program"/>
<File sha1="b97d6e1c70b75805f4a2d0d0950c170f4b6d7e17" name="Modules/Main.lua" part="program"/>
<File sha1="e881a33fb01053d69d58af5a112e5fb03bc29188" name="Modules/Main.lua" part="program"/>
<File sha1="eb5792af777dba9bb1861398aeb977df314ec6f5" name="Modules/ModParser.lua" part="program"/>
<File sha1="5f93a9d8f58e0d5990a1f84e1ab1d53fbd35fb56" name="Modules/ModTools.lua" part="program"/>
<File sha1="e7ee7e5b6388facb7bf568517ecc401590757df7" name="Assets/ring.png" part="program"/>