Ui enhancements 2.0 (#29)

* canvas overhaul

* editor 2.0

* more tweaks

* more editor work

* completions + refactor

* cleanup + editor additions

* cleanup + undo overhaul

* editor recent/peripherals/redo + cleanup

* editor path issues

* cleanup

* changes for deprecated ui methods - recolor milo - make turtle scripts run again - mob rancher improvements

* can now use named colors
This commit was merged in pull request #29.
This commit is contained in:
kepler155c
2020-04-21 22:40:47 -06:00
committed by GitHub
parent 47e0a90116
commit 4576969739
65 changed files with 1842 additions and 1310 deletions

View File

@@ -8,10 +8,10 @@ local http = _G.http
local multishell = _ENV.multishell
local os = _G.os
local shell = _ENV.shell
local colors = _G.colors
local REGISTRY_DIR = 'usr/.registry'
-- FIX SOMEDAY
local function registerApp(app, key)
app.key = SHA.compute(key)
@@ -27,7 +27,6 @@ local function unregisterApp(key)
end
end
local sandboxEnv = Util.shallowCopy(_ENV)
setmetatable(sandboxEnv, { __index = _G })
@@ -36,21 +35,10 @@ UI:configure('Appstore', ...)
local APP_DIR = 'usr/apps'
local sources = {
{ text = "STD Default",
event = 'source',
url = "https://github.com/LDDestroier/STD-GUI/raw/master/list.lua" }, --stock
--[[
{ text = "Discover",
event = 'source',
generateName = true,
url = "http://pastebin.com/raw/9bXfCz6M" }, --owned by dannysmc95
{ text = "Opus",
event = 'source',
url = "http://pastebin.com/raw/ajQ91Rmn" },
]]
local source = {
text = "STD Default",
event = 'source',
url = "https://github.com/LDDestroier/STD-GUI/raw/master/list.lua",
}
shell.setDir(APP_DIR)
@@ -87,14 +75,14 @@ local function runApp(app, checkExists, ...)
error('Failed to download')
end
local fn = loadstring(program, app.name)
fn = _G.loadstring(program, app.name)
if not fn then
error('Failed to download')
end
setfenv(fn, sandboxEnv)
fn(unpack(args))
_G.setfenv(fn, sandboxEnv)
fn(table.unpack(args))
end
end
@@ -134,16 +122,16 @@ local viewApp = function(app)
return true
end
local getSourceListing = function(source)
local getSourceListing = function()
local contents = http.get(source.url)
if contents then
local fn = loadstring(contents.readAll(), source.text)
local fn = _G.loadstring(contents.readAll(), source.text)
contents.close()
local env = { std = { } }
setmetatable(env, { __index = _G })
setfenv(fn, env)
_G.setfenv(fn, env)
fn()
if env.contextualGet then
@@ -172,9 +160,28 @@ local getSourceListing = function(source)
end
end
getSourceListing()
if not source.storeURLs then
error('Unable to download application list')
end
local buttons = { }
for k,v in Util.spairs(source.storeCatagoryNames,
function(a, b) return a:lower() < b:lower() end) do
if v ~= 'Operating System' then
table.insert(buttons, {
text = v,
event = 'category',
index = k,
})
end
end
source.index, source.name = Util.first(source.storeCatagoryNames)
local appPage = UI.Page {
menuBar = UI.MenuBar {
-- showBackButton = not pocket,
buttons = {
{ text = '\027', event = 'back' },
{ text = 'Install', event = 'install' },
@@ -204,16 +211,14 @@ function appPage.container.viewport:draw()
Ansi.yellow .. app.description .. Ansi.reset)
self:clear()
self:setCursorPos(1, 1)
self:print(str)
self.ymax = self.cursorY
if appPage.notification.enabled then
appPage.notification:draw()
end
end
function appPage:enable(source, app)
function appPage:enable(app)
self.source = source
self.app = app
UI.Page.enable(self)
@@ -293,8 +298,7 @@ end
local categoryPage = UI.Page {
menuBar = UI.MenuBar {
buttons = {
{ text = 'Catalog', dropdown = sources },
{ text = 'Category', name = 'categoryButton', dropdown = { } },
{ text = 'Category', name = 'categoryButton', dropdown = buttons },
},
},
grid = UI.ScrollingGrid {
@@ -309,62 +313,21 @@ local categoryPage = UI.Page {
l = 'lua',
[ 'control-q' ] = 'quit',
},
source = source,
}
function categoryPage:setCategory(source, name, index)
function categoryPage:setCategory(name, index)
self.grid.values = { }
for _,v in pairs(source.storeURLs) do
if index == 0 or index == v.catagory then
table.insert(self.grid.values, v)
end
end
self.statusBar:setStatus(string.format('%s: %s', source.text, name))
self.statusBar:setStatus(string.format('%s: %s', self.source.text or '', name))
self.grid:update()
self.grid:setIndex(1)
end
function categoryPage:setSource(source)
if not source.categoryMenu then
self.statusBar:setStatus('Loading...')
self.statusBar:draw()
self:sync()
getSourceListing(source)
if not source.storeURLs then
error('Unable to download application list')
end
local buttons = { }
for k,v in Util.spairs(source.storeCatagoryNames,
function(a, b) return a:lower() < b:lower() end) do
if v ~= 'Operating System' then
table.insert(buttons, {
text = v,
event = 'category',
index = k,
})
end
end
source.categoryMenu = UI.DropMenu({
buttons = buttons,
})
source.index, source.name = Util.first(source.storeCatagoryNames)
categoryPage.menuBar.categoryButton:add({
categoryMenu = source.categoryMenu
})
end
self.source = source
self.menuBar.categoryButton.dropmenu = source.categoryMenu
categoryPage:setCategory(source, source.name, source.index)
end
function categoryPage.grid:sortCompare(a, b)
return a.ltitle < b.ltitle
end
@@ -377,12 +340,11 @@ function categoryPage.grid:getRowTextColor(row, selected)
end
function categoryPage:eventHandler(event)
if event.type == 'grid_select' or event.type == 'select' then
UI:setPage(appPage, self.source, self.grid:getSelected())
UI:setPage(appPage, self.grid:getSelected())
elseif event.type == 'category' then
self:setCategory(self.source, event.button.text, event.button.index)
self:setCategory(event.button.text, event.button.index)
self:setFocus(self.grid)
self:draw()
@@ -392,7 +354,7 @@ function categoryPage:eventHandler(event)
self:draw()
elseif event.type == 'quit' then
UI:exitPullEvents()
UI:quit()
else
return UI.Page.eventHandler(self, event)
@@ -401,8 +363,7 @@ function categoryPage:eventHandler(event)
end
print("Retrieving catalog list")
categoryPage:setSource(sources[1])
categoryPage:setCategory(source.name, source.index)
UI:setPage(categoryPage)
UI:pullEvents()
UI.term:reset()
UI:start()

View File

@@ -3,7 +3,6 @@ local Event = require('opus.event')
local UI = require('opus.ui')
local Util = require('opus.util')
local colors = _G.colors
local peripheral = _G.peripheral
--[[ -- PeripheralsPage -- ]] --
@@ -16,6 +15,20 @@ local peripheralsPage = UI.Page {
},
sortColumn = 'type',
autospace = true,
enable = function(self)
local sides = peripheral.getNames()
Util.clear(self.values)
for _,side in pairs(sides) do
table.insert(self.values, {
type = peripheral.getType(side),
side = side
})
end
self:update()
self:adjustWidth()
UI.Grid.enable(self)
end,
},
statusBar = UI.StatusBar {
values = 'Select peripheral',
@@ -23,52 +36,35 @@ local peripheralsPage = UI.Page {
accelerators = {
[ 'control-q' ] = 'quit',
},
updatePeripherals = function(self)
if UI:getCurrentPage() == self then
self.grid:draw()
self:sync()
end
end,
eventHandler = function(self, event)
if event.type == 'quit' then
UI:quit()
elseif event.type == 'grid_select' then
UI:setPage('methods', event.selected)
end
return UI.Page.eventHandler(self, event)
end,
}
function peripheralsPage.grid:enable()
local sides = peripheral.getNames()
Util.clear(self.values)
for _,side in pairs(sides) do
table.insert(self.values, {
type = peripheral.getType(side),
side = side
})
end
self:update()
self:adjustWidth()
UI.Grid.enable(self)
end
function peripheralsPage:updatePeripherals()
if UI:getCurrentPage() == self then
self.grid:draw()
self:sync()
end
end
function peripheralsPage:eventHandler(event)
if event.type == 'quit' then
Event.exitPullEvents()
elseif event.type == 'grid_select' then
UI:setPage('methods', event.selected)
end
return UI.Page.eventHandler(self, event)
end
--[[ -- MethodsPage -- ]] --
local methodsPage = UI.Page {
backgroundColor = colors.black,
doc = UI.TextArea {
backgroundColor = colors.black,
x = 2, y = 2, ex = -1, ey = -7,
backgroundColor = 'black',
ey = -7,
marginLeft = 1, marginTop = 1,
},
grid = UI.ScrollingGrid {
y = -6, ey = -2,
columns = {
{ heading = 'Name', key = 'name', width = UI.term.width }
{ heading = 'Name', key = 'name' }
},
sortColumn = 'name',
},
@@ -198,4 +194,4 @@ UI:setPages({
methods = methodsPage,
})
UI:pullEvents()
UI:start()

View File

@@ -122,7 +122,6 @@ function page:drawInfo(drive, textArea)
return isValid(drive) and fs.getFreeSpace(drive.getMountPath()) or 0
end
textArea:setCursorPos(1, 1)
textArea:print(string.format('Drive: %s%s%s\nLabel: %s%s%s\nUsed: %s%s%s\nFree: %s%s%s',
Ansi.yellow, drive.name, Ansi.reset,
isValid(drive) and Ansi.yellow or Ansi.orange, getLabel():sub(1, 10), Ansi.reset,
@@ -138,6 +137,7 @@ function page:scan()
self.copyButton.inactive = not valid
self:draw()
self.progress:clear()
self.progress:centeredWrite(1, 'Analyzing Disks..')
self.progress:sync()
@@ -167,6 +167,7 @@ function page:copy()
throttle()
end
self.progress:clear()
self.progress:centeredWrite(1, 'Computing..')
self.progress:sync()
@@ -211,6 +212,8 @@ function page:copy()
self.progress:clear()
rawCopy(sdrive.getMountPath(), tdrive.getMountPath())
cleanup()
self.progress:clear()
self.progress:centeredWrite(1, 'Copy Complete', colors.lime, colors.black)
self.progress:sync()
@@ -270,4 +273,4 @@ Event.onTimeout(.2, function()
end)
UI:setPage(page)
UI:pullEvents()
UI:start()

View File

@@ -27,6 +27,26 @@ local page = UI.Page {
},
autospace = true,
disableHeader = true,
getDisplayValues = function(_, row)
row = Util.shallowCopy(row)
local function tovalue(s)
if type(s) == 'table' then
return 'table'
end
return s
end
for k,v in pairs(row) do
row[k] = tovalue(v)
end
return row
end,
draw = function(self)
self:adjustWidth()
UI.Grid.draw(self)
end,
},
accelerators = {
f = 'filter',
@@ -36,81 +56,48 @@ local page = UI.Page {
[ 'control-q' ] = 'quit',
},
filtered = { },
}
eventHandler = function(self, event)
if event.type == 'filter' then
local entry = self.grid:getSelected()
self.filtered[entry.event] = true
function page:eventHandler(event)
elseif event.type == 'toggle' then
self.paused = not self.paused
if self.paused then
self.menuBar.pauseButton.text = 'Resume'
else
self.menuBar.pauseButton.text = 'Pause '
end
self.menuBar:draw()
if event.type == 'filter' then
local entry = self.grid:getSelected()
self.filtered[entry.event] = true
elseif event.type == 'grid_select' then
multishell.openTab({
path = 'sys/apps/Lua.lua',
args = { event.selected },
focused = true,
})
elseif event.type == 'toggle' then
self.paused = not self.paused
if self.paused then
self.menuBar.pauseButton.text = 'Resume'
else
self.menuBar.pauseButton.text = 'Pause '
end
self.menuBar:draw()
elseif event.type == 'grid_select' then
multishell.openTab({
path = 'sys/apps/Lua.lua',
args = { event.selected },
focused = true,
})
elseif event.type == 'reset' then
self.filtered = { }
self.grid:setValues({ })
self.grid:draw()
if self.paused then
self:emit({ type = 'toggle' })
end
elseif event.type == 'clear' then
self.grid:setValues({ })
self.grid:draw()
elseif event.type == 'quit' then
UI:exitPullEvents()
--[[
elseif event.type == 'focus_change' then
if event.focused == self.grid then
if not self.paused then
elseif event.type == 'reset' then
self.filtered = { }
self.grid:setValues({ })
self.grid:draw()
if self.paused then
self:emit({ type = 'toggle' })
end
elseif event.type == 'clear' then
self.grid:setValues({ })
self.grid:draw()
elseif event.type == 'quit' then
UI:quit()
else
return UI.Page.eventHandler(self, event)
end
--]]
else
return UI.Page.eventHandler(self, event)
end
return true
end
function page.grid:getDisplayValues(row)
row = Util.shallowCopy(row)
local function tovalue(s)
if type(s) == 'table' then
return 'table'
end
return s
end
for k,v in pairs(row) do
row[k] = tovalue(v)
end
return row
end
function page.grid:draw()
self:adjustWidth()
UI.Grid.draw(self)
end
return true
end,
}
local updated = false
local timerId = os.startTimer(1)
@@ -150,6 +137,6 @@ end
kernel.hook('*', hookFunction)
UI:setPage(page)
UI:pullEvents()
UI:start()
kernel.unhook('*', hookFunction)

View File

@@ -42,7 +42,6 @@ local page = UI.Page {
},
range = UI.SlideOut {
y = -7, height = 7,
backgroundColor = colors.cyan,
titleBar = UI.TitleBar {
event = 'cancel',
title = 'Enter range',
@@ -239,6 +238,6 @@ Event.addRoutine(function()
end)
UI:setPage(page)
UI:pullEvents()
UI:start()
swarm:stop()

View File

@@ -60,4 +60,4 @@ function page:eventHandler(event)
end
UI:setPage(page)
UI:pullEvents()
UI:start()

View File

@@ -2,7 +2,6 @@ local Config = require('opus.config')
local Event = require('opus.event')
local itemDB = require('core.itemDB')
local Socket = require('opus.socket')
local Terminal = require('opus.terminal')
local UI = require('opus.ui')
local Util = require('opus.util')
@@ -11,10 +10,7 @@ local fs = _G.fs
local multishell = _ENV.multishell
local network = _G.network
local os = _G.os
local shell = _ENV.shell
local term = _G.term
--UI.Button.defaults.focusIndicator = ' '
UI:configure('Turtles', ...)
local config = { }
@@ -31,13 +27,26 @@ local options = {
local SCRIPTS_PATH = 'packages/common/etc/scripts'
local nullTerm = Terminal.getNullTerm(term.current())
local socket
local socket, turtle, page
local page = UI.Page {
page = UI.Page {
coords = UI.Window {
backgroundColor = colors.black,
height = 3,
marginTop = 1, marginLeft = 1,
draw = function(self)
local t = turtle
self:clear()
if t then
self:setCursorPos(2, 2)
local ind = 'GPS'
if not t.point.gps then
ind = 'REL'
end
self:print(string.format('%s : %d,%d,%d',
ind, t.point.x, t.point.y, t.point.z))
end
end,
},
tabs = UI.Tabs {
x = 1, y = 4, ey = -2,
@@ -50,6 +59,23 @@ local page = UI.Page {
disableHeader = true,
sortColumn = 'label',
autospace = true,
draw = function(self)
Util.clear(self.values)
local files = fs.list(SCRIPTS_PATH)
for _,path in pairs(files) do
table.insert(self.values, { label = path, path = fs.combine(SCRIPTS_PATH, path) })
end
self:update()
UI.ScrollingGrid.draw(self)
end,
eventHandler = function(self, event)
if event.type == 'grid_select' then
page:runScript(event.selected.label)
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end,
},
turtles = UI.ScrollingGrid {
tabTitle = 'Select',
@@ -63,6 +89,41 @@ local page = UI.Page {
disableHeader = true,
sortColumn = 'label',
autospace = true,
getDisplayValues = function(_, row)
row = Util.shallowCopy(row)
if row.fuel then
row.fuel = Util.toBytes(row.fuel)
end
if row.distance then
row.distance = Util.round(row.distance, 1)
end
return row
end,
draw = function(self)
Util.clear(self.values)
for _,v in pairs(network) do
if v.fuel then
table.insert(self.values, v)
end
end
self:update()
UI.ScrollingGrid.draw(self)
end,
eventHandler = function(self, event)
if event.type == 'grid_select' then
turtle = event.selected
config.id = event.selected.id
Config.update('Turtles', config)
multishell.setTitle(multishell.getCurrent(), turtle.label)
if socket then
socket:close()
socket = nil
end
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end,
},
inventory = UI.ScrollingGrid {
backgroundColor = colors.cyan,
@@ -70,10 +131,58 @@ local page = UI.Page {
columns = {
{ heading = '', key = 'index', width = 2 },
{ heading = '', key = 'count', width = 2 },
{ heading = 'Inventory', key = 'key', width = UI.term.width - 7 },
{ heading = 'Inventory', key = 'key' },
},
disableHeader = true,
sortColumn = 'index',
getRowTextColor = function(self, row, selected)
if turtle and row.selected then
return colors.yellow
end
return UI.ScrollingGrid.getRowTextColor(self, row, selected)
end,
draw = function(self)
local t = turtle
Util.clear(self.values)
if t then
for k,v in pairs(t.inv or { }) do -- new method (less data)
local index, count = k:match('(%d+),(%d+)')
v = {
index = tonumber(index),
key = v,
count = tonumber(count),
}
table.insert(self.values, v)
end
for _,v in pairs(t.inventory or { }) do
if v.count > 0 then
table.insert(self.values, v)
end
end
for _,v in pairs(self.values) do
if v.index == t.slotIndex then
v.selected = true
end
if v.key then
v.key = itemDB:getName(v.key)
end
end
end
self:adjustWidth()
self:update()
UI.ScrollingGrid.draw(self)
end,
eventHandler = function(self, event)
if event.type == 'grid_select' then
local fn = string.format('turtle.select(%d)', event.selected.index)
page:runFunction(fn)
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end,
},
--[[
policy = UI.ScrollingGrid {
@@ -134,6 +243,15 @@ local page = UI.Page {
{ key = 'distance', width = 6 },
{ key = 'fuel', width = 6 },
},
draw = function(self)
local t = turtle
if t then
self.values.status = t.status
self.values.distance = t.distance and Util.round(t.distance, 2)
self.values.fuel = Util.toBytes(t.fuel)
end
UI.StatusBar.draw(self)
end,
},
notification = UI.Notification(),
accelerators = {
@@ -141,15 +259,10 @@ local page = UI.Page {
},
}
function page:enable(turtle)
self.turtle = turtle
UI.Page.enable(self)
end
function page:runFunction(script, nowrap)
for _ = 1, 2 do
if not socket then
socket = Socket.connect(self.turtle.id, 161)
socket = Socket.connect(turtle.id, 161)
end
if socket then
@@ -170,149 +283,52 @@ function page:runFunction(script, nowrap)
end
function page:runScript(scriptName)
if self.turtle then
if turtle then
self.notification:info('Connecting')
self:sync()
local cmd = string.format('Script %d %s', self.turtle.id, scriptName)
local ot = term.redirect(nullTerm)
pcall(function() shell.run(cmd) end)
term.redirect(ot)
self.notification:success('Sent')
end
end
function page.coords:draw()
local t = self.parent.turtle
self:clear()
if t then
self:setCursorPos(2, 2)
local ind = 'GPS'
if not t.point.gps then
ind = 'REL'
local script = Util.readFile(fs.combine(SCRIPTS_PATH, scriptName))
if not script then
print('Unable to read script file')
end
self:print(string.format('%s : %d,%d,%d',
ind, t.point.x, t.point.y, t.point.z))
end
end
--[[ Inventory Tab ]]--
function page.tabs.inventory:getRowTextColor(row, selected)
if page.turtle and row.selected then
return colors.yellow
end
return UI.ScrollingGrid.getRowTextColor(self, row, selected)
end
function page.tabs.inventory:draw()
local t = page.turtle
Util.clear(self.values)
if t then
for k,v in pairs(t.inv or { }) do -- new method (less data)
local index, count = k:match('(%d+),(%d+)')
v = {
index = tonumber(index),
key = v,
count = tonumber(count),
local function processVariables()
local variables = {
COMPUTER_ID = os.getComputerID,
GPS = function()
local pt = require('opus.gps').getPoint()
if not pt then
error('Unable to determine location')
end
return _G.textutils.serialize(pt)
end,
}
table.insert(self.values, v)
end
for _,v in pairs(t.inventory or { }) do
if v.count > 0 then
table.insert(self.values, v)
for k,v in pairs(variables) do
local token = string.format('{%s}', k)
if script:find(token, 1, true) then
local s, m = pcall(v)
if not s then
self.notification:error(m)
return
end
script = script:gsub(token, m)
end
end
return true
end
for _,v in pairs(self.values) do
if v.index == t.slotIndex then
v.selected = true
if processVariables(script) then
local socket = Socket.connect(turtle.id, 161)
if not socket then
self.notification:error('Unable to connect')
return
end
if v.key then
v.key = itemDB:getName(v.key)
end
end
end
self:adjustWidth()
self:update()
UI.ScrollingGrid.draw(self)
end
function page.tabs.inventory:eventHandler(event)
if event.type == 'grid_select' then
local fn = string.format('turtle.select(%d)', event.selected.index)
page:runFunction(fn)
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end
function page.tabs.scripts:draw()
Util.clear(self.values)
local files = fs.list(SCRIPTS_PATH)
for _,path in pairs(files) do
table.insert(self.values, { label = path, path = fs.combine(SCRIPTS_PATH, path) })
end
self:update()
UI.ScrollingGrid.draw(self)
end
function page.tabs.scripts:eventHandler(event)
if event.type == 'grid_select' then
page:runScript(event.selected.label)
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end
function page.tabs.turtles:getDisplayValues(row)
row = Util.shallowCopy(row)
if row.fuel then
row.fuel = Util.toBytes(row.fuel)
end
if row.distance then
row.distance = Util.round(row.distance, 1)
end
return row
end
function page.tabs.turtles:draw()
Util.clear(self.values)
for _,v in pairs(network) do
if v.fuel then
table.insert(self.values, v)
end
end
self:update()
UI.ScrollingGrid.draw(self)
end
function page.tabs.turtles:eventHandler(event)
if event.type == 'grid_select' then
page.turtle = event.selected
config.id = event.selected.id
Config.update('Turtles', config)
multishell.setTitle(multishell.getCurrent(), page.turtle.label)
if socket then
socket:write({ type = 'script', args = script })
socket:close()
socket = nil
end
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end
function page.statusBar:draw()
local t = self.parent.turtle
if t then
self.values.status = t.status
self.values.distance = t.distance and Util.round(t.distance, 2)
self.values.fuel = Util.toBytes(t.fuel)
self.notification:success('Sent')
end
end
UI.StatusBar.draw(self)
end
function page:showBlocks()
@@ -335,7 +351,7 @@ end
function page:eventHandler(event)
if event.type == 'quit' then
UI:exitPullEvents()
UI:quit()
elseif event.type == 'tab_select' then
config.tab = event.button.text
@@ -354,19 +370,14 @@ function page:eventHandler(event)
return true
end
function page:enable()
UI.Page.enable(self)
-- self.tabs:activateTab(page.tabs.turtles)
end
if not Util.getOptions(options, { ... }, true) then
return
end
if options.turtle.value >= 0 then
for _ = 1, 10 do
page.turtle = _G.network[options.turtle.value]
if page.turtle then
turtle = _G.network[options.turtle.value]
if turtle then
break
end
os.sleep(1)
@@ -374,9 +385,9 @@ if options.turtle.value >= 0 then
end
Event.onInterval(1, function()
if page.turtle then
local t = _G.network[page.turtle.id]
page.turtle = t
if turtle then
--local t = _G.network[turtle.id]
--turtle = t
page:draw()
page:sync()
end
@@ -387,5 +398,4 @@ if config.tab then
end
UI:setPage(page)
UI:pullEvents()
UI:start()

File diff suppressed because it is too large Load Diff

View File

@@ -57,7 +57,7 @@
category = "Apps",
requires = "advancedComputer",
iconExt = "\030 \031 \128\030d\159\030 \031d\140\030d\031 \155\030 \0315\140\0305\031 \155\030 \128\010\030 \031d\136\145\0315\136\145\031d\153\031 \128\0315\153\010\030 \031 \128\031d\130\140\134\0315\140\134\031 \128",
run = "packages/common/hexedit.lua",
run = "fileui --exec=hexedit.lua",
},
[ "fb1c39e9f4f3c2628ad173ab401a6e4e4baf783d" ] = {
title = "Sounds",
@@ -65,4 +65,17 @@
run = "SoundPlayer",
iconExt = "\030 \031 \128\0307\159\129\030 \0317\149\0310\144\0300\031 \155\030 \0310\137\144\010\0307\0317\128\128\128\030 \149\0300\031 \149\030 \128\0310\149\0300\031 \149\010\030 \031 \128\0317\130\0307\031 \144\030 \0317\149\0310\129\134\152\129",
},
[ "464c4ffd019e1e9691dcf0537c797353ef2b1c1d4833d3d463e5b74ae4547344" ] = {
title = "Editor",
category = "Apps",
run = "edit",
iconExt = "7\
¨¨¨¨f€0¨\
¨¨f€0¨¨f€",
},
[ "3f00927a719345edd4a8316599d3b328857987547f8884306861161ffa09647e" ] = {
title = "Write",
category = "Apps",
run = "write",
},
}

View File

@@ -1,5 +1,5 @@
_G.requireInjector(_ENV)
local config = require('config').load('gps')
local config = require('opus.config').load('gps')
if config.home then
if turtle.enableGPS() then
return turtle.pathfind(config.home)

View File

@@ -1,29 +0,0 @@
turtle.run(function()
_G.requireInjector(_ENV)
local GPS = require('gps')
local Socket = require('socket')
local id = {COMPUTER_ID}
if not turtle.enableGPS() then
error('turtle: No GPS found')
end
local socket = Socket.connect(id, 161)
if not socket then
error('turtle: Unable to connect to ' .. id)
end
socket:write({ type = 'gps' })
local pt = socket:read(3)
if not pt then
error('turtle: No GPS response')
end
if not turtle.pathfind(pt) then
error('Unable to go to location')
end
end)

View File

@@ -0,0 +1,17 @@
local turtle = _G.turtle
turtle.run(function()
_G.requireInjector(_ENV)
local GPS = require('opus.gps')
if not turtle.enableGPS() then
error('turtle: No GPS found')
end
local pt = {GPS}
if not turtle.pathfind(pt) then
error('Unable to go to location')
end
end)

View File

@@ -1,5 +1,5 @@
_G.requireInjector(_ENV)
local Config = require('config')
local Config = require('opus.config')
local pt = turtle.enableGPS()
if pt then
local config = Config.load('gps', { })

View File

@@ -2,9 +2,9 @@ local function summon(id)
_G.requireInjector(_ENV)
local GPS = require('gps')
local Point = require('point')
local Socket = require('socket')
local GPS = require('opus.gps')
local Point = require('opus.point')
local Socket = require('opus.socket')
turtle.setStatus('GPSing')
turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 })

View File

@@ -19,10 +19,14 @@ local Util = require('opus.util')
local multishell = _ENV.multishell
local os = _G.os
local recTerm, oldTerm, arg, showInput, skipLast, lastDelay, curInput = {}, Util.shallowCopy(multishell.term), {...}, false, false, 2, ""
local colours = _G.colors
local args, options = Util.parse(...)
local oldTerm, showInput, skipLast, lastDelay, curInput = Util.shallowCopy(multishell.term), false, false, 2, ""
local curBlink, oldBlink, tTerm, buffer, colourNum, xPos, yPos, oldXPos, oldYPos, tCol, bCol, xSize, ySize = false, false, {}, {}, {}, 1, 1, 1, 1, colours.white, colours.black, oldTerm.getSize()
local greys, buttons = {["0"] = true, ["7"] = true, ["8"] = true, ["f"] = true}, {"l", "r", "m"}
local charW, charH, chars, resp
local charW, charH, chars
local calls = { }
local curCalls = { delay = 0 }
@@ -32,38 +36,44 @@ local callCount = 0
local function showSyntax()
print('Gif Recorder by Bomb Bloke\n')
print('Syntax: recGif [-i] [-s] [-ld:<delay>] filename')
print(' -i : show input')
print(' -s : skip last')
print(' -ld : last delay')
print(' --showInput : show input')
print(' --skipLast : skip last')
print(' --lastDelay : last delay')
print(' --noResize : dont resize')
end
for i = #arg, 1, -1 do
local curArg = arg[i]:lower()
if curArg == "-i" then
showInput, ySize = true, ySize + 1
table.remove(arg, i)
elseif curArg == "-s" then
skipLast = true
table.remove(arg, i)
elseif curArg:sub(1, 4) == "-ld:" then
curArg = tonumber(curArg:sub(5))
if curArg then lastDelay = curArg end
table.remove(arg, i)
elseif curArg == '-?' then
showSyntax()
return
elseif i ~= #arg then
showSyntax()
printError('\nInvalid argument')
return
end
if options.showInput then
showInput, ySize = true, ySize + 1
end
print('Gif Recorder by Bomb Bloke\n')
print('Press control-p to stop recording')
if options.skipLast then
skipLast = true
end
local filename = arg[#arg]
if options.lastDelay then
lastDelay = options.lastDelay
end
if options.help then
showSyntax()
return
end
if options.daemon then
device.keyboard.addHotkey('control-P', function()
multishell.openTab({
path = 'sys/apps/shell.lua',
args = { arg[0], '--noResize', '--rawOutput', 'recorder.gif' },
})
end)
return
end
print('Gif Recorder by Bomb Bloke')
print(version)
print('\nPress control-p to stop recording')
local filename = args[1]
if not filename then
print('Enter file name:')
filename = read()
@@ -131,37 +141,34 @@ end
-- Build a terminal that records stuff:
recTerm = multishell.term
local recTerm = multishell.term
for key, func in pairs(oldTerm) do
recTerm[key] = function(...)
local result = { func(...) }
if type(func) == 'function' then
recTerm[key] = function(...)
local result = { func(...) }
if callCount == 0 then
os.queueEvent('capture_frame')
if callCount == 0 then
os.queueEvent('capture_frame')
end
callCount = callCount + 1
curCalls[callCount] = { key, ... }
return unpack(result)
end
callCount = callCount + 1
curCalls[callCount] = { key, ... }
return unpack(result)
end
end
local tabId = multishell.getCurrent()
multishell.hideTab(tabId)
if not options.noResize then
os.queueEvent('term_resize')
end
_G.device.keyboard.addHotkey('control-p', function()
os.queueEvent('recorder_stop')
end)
local tabs = multishell.getTabs()
for _,tab in pairs(tabs) do
if tab.isOverview then
multishell.hideTab(tabId)
multishell.setFocus(tab.tabId)
os.queueEvent('term_resize')
break
end
end
local curTime = os.clock() - 1
while true do
@@ -200,8 +207,12 @@ if skipLast and #calls > 1 then calls[#calls] = nil end
calls[#calls].delay = lastDelay
if options.rawOutput then
Util.writeTable('tmp/raw.txt', calls)
return
end
print(string.format("Encoding %d frames...", #calls))
--Util.writeTable('tmp/raw.txt', calls)
-- Perform a quick re-parse of the recorded data (adding frames for when the cursor blinks):