mirror of
https://github.com/kepler155c/opus
synced 2025-01-12 00:30:27 +00:00
transitions and Lua improvements
This commit is contained in:
parent
3fdd7336f1
commit
4435a14ed1
38
apps/Lua.lua
38
apps/Lua.lua
@ -15,7 +15,7 @@ UI:configure('Lua', ...)
|
|||||||
local command = ''
|
local command = ''
|
||||||
local history = History.load('.lua_history', 25)
|
local history = History.load('.lua_history', 25)
|
||||||
|
|
||||||
local resultsPage = UI.Page({
|
local page = UI.Page({
|
||||||
menuBar = UI.MenuBar({
|
menuBar = UI.MenuBar({
|
||||||
buttons = {
|
buttons = {
|
||||||
{ text = 'Local', event = 'local' },
|
{ text = 'Local', event = 'local' },
|
||||||
@ -47,7 +47,7 @@ local resultsPage = UI.Page({
|
|||||||
notification = UI.Notification(),
|
notification = UI.Notification(),
|
||||||
})
|
})
|
||||||
|
|
||||||
function resultsPage:setPrompt(value, focus)
|
function page:setPrompt(value, focus)
|
||||||
self.prompt:setValue(value)
|
self.prompt:setValue(value)
|
||||||
self.prompt.scroll = 0
|
self.prompt.scroll = 0
|
||||||
self.prompt:setPosition(#value)
|
self.prompt:setPosition(#value)
|
||||||
@ -59,29 +59,29 @@ function resultsPage:setPrompt(value, focus)
|
|||||||
|
|
||||||
self.prompt:draw()
|
self.prompt:draw()
|
||||||
if focus then
|
if focus then
|
||||||
resultsPage:setFocus(self.prompt)
|
page:setFocus(self.prompt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function resultsPage:enable()
|
function page:enable()
|
||||||
self:setFocus(self.prompt)
|
self:setFocus(self.prompt)
|
||||||
UI.Page.enable(self)
|
UI.Page.enable(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function resultsPage:eventHandler(event)
|
function page:eventHandler(event)
|
||||||
|
|
||||||
if event.type == 'global' then
|
if event.type == 'global' then
|
||||||
resultsPage:setPrompt('', true)
|
page:setPrompt('', true)
|
||||||
self:executeStatement('getfenv(0)')
|
self:executeStatement('getfenv(0)')
|
||||||
command = nil
|
command = nil
|
||||||
|
|
||||||
elseif event.type == 'local' then
|
elseif event.type == 'local' then
|
||||||
resultsPage:setPrompt('', true)
|
page:setPrompt('', true)
|
||||||
self:executeStatement('getfenv(1)')
|
self:executeStatement('getfenv(1)')
|
||||||
command = nil
|
command = nil
|
||||||
|
|
||||||
elseif event.type == 'device' then
|
elseif event.type == 'device' then
|
||||||
resultsPage:setPrompt('device', true)
|
page:setPrompt('device', true)
|
||||||
self:executeStatement('device')
|
self:executeStatement('device')
|
||||||
|
|
||||||
elseif event.type == 'history_back' then
|
elseif event.type == 'history_back' then
|
||||||
@ -128,7 +128,7 @@ function resultsPage:eventHandler(event)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function resultsPage:setResult(result)
|
function page:setResult(result)
|
||||||
local t = { }
|
local t = { }
|
||||||
|
|
||||||
local function safeValue(v)
|
local function safeValue(v)
|
||||||
@ -169,7 +169,7 @@ function resultsPage:setResult(result)
|
|||||||
self:draw()
|
self:draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
function resultsPage.grid:eventHandler(event)
|
function page.grid:eventHandler(event)
|
||||||
|
|
||||||
local entry = self:getSelected()
|
local entry = self:getSelected()
|
||||||
|
|
||||||
@ -199,18 +199,18 @@ function resultsPage.grid:eventHandler(event)
|
|||||||
|
|
||||||
if event.type == 'grid_focus_row' then
|
if event.type == 'grid_focus_row' then
|
||||||
if self.focused then
|
if self.focused then
|
||||||
resultsPage:setPrompt(commandAppend())
|
page:setPrompt(commandAppend())
|
||||||
end
|
end
|
||||||
elseif event.type == 'grid_select' then
|
elseif event.type == 'grid_select' then
|
||||||
resultsPage:setPrompt(commandAppend(), true)
|
page:setPrompt(commandAppend(), true)
|
||||||
resultsPage:executeStatement(commandAppend())
|
page:executeStatement(commandAppend())
|
||||||
else
|
else
|
||||||
return UI.Grid.eventHandler(self, event)
|
return UI.Grid.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function resultsPage:rawExecute(s)
|
function page:rawExecute(s)
|
||||||
|
|
||||||
local fn, m = loadstring("return (" .. s .. ')', 'lua')
|
local fn, m = loadstring("return (" .. s .. ')', 'lua')
|
||||||
if not fn then
|
if not fn then
|
||||||
@ -225,7 +225,7 @@ function resultsPage:rawExecute(s)
|
|||||||
return fn, m
|
return fn, m
|
||||||
end
|
end
|
||||||
|
|
||||||
function resultsPage:executeStatement(statement)
|
function page:executeStatement(statement)
|
||||||
|
|
||||||
command = statement
|
command = statement
|
||||||
|
|
||||||
@ -242,6 +242,12 @@ function resultsPage:executeStatement(statement)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
UI:setPage(resultsPage)
|
sandboxEnv.args = { ... }
|
||||||
|
if sandboxEnv.args[1] then
|
||||||
|
command = 'args[1]'
|
||||||
|
page:setResult(sandboxEnv.args[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
UI:setPage(page)
|
||||||
Event.pullEvents()
|
Event.pullEvents()
|
||||||
UI.term:reset()
|
UI.term:reset()
|
||||||
|
@ -75,7 +75,7 @@ local systemPage = UI.Page {
|
|||||||
value = 'Label'
|
value = 'Label'
|
||||||
},
|
},
|
||||||
label = UI.TextEntry {
|
label = UI.TextEntry {
|
||||||
x = 9, y = 2, rex = -12,
|
x = 9, y = 2, rex = -4,
|
||||||
limit = 32,
|
limit = 32,
|
||||||
value = os.getComputerLabel(),
|
value = os.getComputerLabel(),
|
||||||
backgroundFocusColor = colors.black,
|
backgroundFocusColor = colors.black,
|
||||||
|
@ -246,8 +246,9 @@ function makeWalkableTunnel(action, tpt, pt)
|
|||||||
if action ~= 'turn' and not Point.compare(tpt, { x = 0, z = 0 }) then -- not at source
|
if action ~= 'turn' and not Point.compare(tpt, { x = 0, z = 0 }) then -- not at source
|
||||||
if not Point.compare(tpt, pt) then -- not at dest
|
if not Point.compare(tpt, pt) then -- not at dest
|
||||||
local r, block = turtle.inspectUp()
|
local r, block = turtle.inspectUp()
|
||||||
if r and block.name ~= 'minecraft:cobblestone' then
|
if r and not turtle.isTurtleAtSide('top') then
|
||||||
if block.name ~= 'minecraft:chest' then
|
if block.name ~= 'minecraft:cobblestone' and
|
||||||
|
block.name ~= 'minecraft:chest' then
|
||||||
turtle.digUp()
|
turtle.digUp()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -483,7 +484,10 @@ function boreCommand()
|
|||||||
|
|
||||||
turtle.clearMoveCallback()
|
turtle.clearMoveCallback()
|
||||||
|
|
||||||
|
-- location is either mined, currently being mined or is the
|
||||||
|
-- dropoff point for a turtle
|
||||||
if inspect(turtle.getAction('up'), 'minecraft:cobblestone') or
|
if inspect(turtle.getAction('up'), 'minecraft:cobblestone') or
|
||||||
|
inspect(turtle.getAction('up'), 'minecraft:chest') or
|
||||||
inspect(turtle.getAction('down'), 'minecraft:cobblestone') then
|
inspect(turtle.getAction('down'), 'minecraft:cobblestone') then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -1,68 +1,144 @@
|
|||||||
local resolver, loader
|
local DEFAULT_UPATH = 'https://raw.githubusercontent.com/kepler155c/opus/master/sys/apis'
|
||||||
|
local PASTEBIN_URL = 'http://pastebin.com/raw'
|
||||||
|
local GIT_URL = 'https://raw.githubusercontent.com/'
|
||||||
|
|
||||||
local function resolveFile(filename, dir, lua_path)
|
local function shellSearcher(modname, env, shell)
|
||||||
|
local fname = modname:gsub('%.', '/') .. '.lua'
|
||||||
|
|
||||||
if filename:sub(1, 1) == "/" then
|
if shell and type(shell.dir) == 'function' then
|
||||||
if not fs.exists(filename) then
|
local path = shell.resolve(fname)
|
||||||
error('Unable to load: ' .. filename, 2)
|
|
||||||
end
|
|
||||||
return filename
|
|
||||||
end
|
|
||||||
|
|
||||||
if dir then
|
|
||||||
local path = fs.combine(dir, filename)
|
|
||||||
if fs.exists(path) and not fs.isDir(path) then
|
if fs.exists(path) and not fs.isDir(path) then
|
||||||
return path
|
return loadfile(path, env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if lua_path then
|
|
||||||
for dir in string.gmatch(lua_path, "[^:]+") do
|
|
||||||
local path = fs.combine(dir, filename)
|
|
||||||
if fs.exists(path) and not fs.isDir(path) then
|
|
||||||
return path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
error('Unable to load: ' .. filename, 2)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function pathSearcher(modname, env, shell)
|
||||||
|
local fname = modname:gsub('%.', '/') .. '.lua'
|
||||||
|
|
||||||
|
for dir in string.gmatch(package.path, "[^:]+") do
|
||||||
|
local path = fs.combine(dir, fname)
|
||||||
|
if fs.exists(path) and not fs.isDir(path) then
|
||||||
|
return loadfile(path, env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- fix broken http get
|
||||||
|
local syncLocks = { }
|
||||||
|
|
||||||
|
local function sync(obj, fn)
|
||||||
|
local key = tostring(obj)
|
||||||
|
if syncLocks[key] then
|
||||||
|
local cos = tostring(coroutine.running())
|
||||||
|
table.insert(syncLocks[key], cos)
|
||||||
|
repeat
|
||||||
|
local _, co = os.pullEvent('sync_lock')
|
||||||
|
until co == cos
|
||||||
|
else
|
||||||
|
syncLocks[key] = { }
|
||||||
|
end
|
||||||
|
local s, m = pcall(fn)
|
||||||
|
local co = table.remove(syncLocks[key], 1)
|
||||||
|
if co then
|
||||||
|
os.queueEvent('sync_lock', co)
|
||||||
|
else
|
||||||
|
syncLocks[key] = nil
|
||||||
|
end
|
||||||
|
if not s then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function loadUrl(url)
|
||||||
|
local c
|
||||||
|
sync(url, function()
|
||||||
|
local h = http.get(url)
|
||||||
|
if h then
|
||||||
|
c = h.readAll()
|
||||||
|
h.close()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
if c and #c > 0 then
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- require('BniCQPVf')
|
||||||
|
local function pastebinSearcher(modname, env, shell)
|
||||||
|
if #modname == 8 and not modname:match('%W') then
|
||||||
|
local url = PASTEBIN_URL .. '/' .. modname
|
||||||
|
local c = loadUrl(url)
|
||||||
|
if c then
|
||||||
|
return load(c, modname, nil, env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- require('kepler155c.opus.master.sys.apis.util')
|
||||||
|
local function gitSearcher(modname, env, shell)
|
||||||
|
local fname = modname:gsub('%.', '/') .. '.lua'
|
||||||
|
local _, count = fname:gsub("/", "")
|
||||||
|
if count >= 3 then
|
||||||
|
local url = GIT_URL .. '/' .. modname
|
||||||
|
local c = loadUrl(url)
|
||||||
|
if c then
|
||||||
|
return load(c, modname, nil, env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function urlSearcher(modname, env, shell)
|
||||||
|
local fname = modname:gsub('%.', '/') .. '.lua'
|
||||||
|
|
||||||
|
if fname:sub(1, 1) ~= '/' then
|
||||||
|
for entry in string.gmatch(package.upath, "[^;]+") do
|
||||||
|
local url = entry .. '/' .. fname
|
||||||
|
local c = loadUrl(url)
|
||||||
|
if c then
|
||||||
|
return load(c, modname, nil, env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
_G.package = {
|
||||||
|
path = LUA_PATH or 'sys/apis',
|
||||||
|
upath = LUA_UPATH or DEFAULT_UPATH,
|
||||||
|
loaders = {
|
||||||
|
shellSearcher,
|
||||||
|
pathSearcher,
|
||||||
|
pastebinSearcher,
|
||||||
|
gitSearcher,
|
||||||
|
urlSearcher,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
local function requireWrapper(env)
|
local function requireWrapper(env)
|
||||||
|
|
||||||
local modules = { }
|
local loaded = { }
|
||||||
|
|
||||||
return function(filename)
|
return function(modname)
|
||||||
|
|
||||||
local dir = DIR
|
if loaded[modname] then
|
||||||
if not dir and shell and type(shell.dir) == 'function' then
|
return loaded[modname]
|
||||||
dir = shell.dir()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local fname = resolver(filename:gsub('%.', '/') .. '.lua',
|
for _,searcher in ipairs(package.loaders) do
|
||||||
dir or '', LUA_PATH or '/sys/apis')
|
local fn = searcher(modname, env, shell)
|
||||||
|
if fn then
|
||||||
local rname = fname:gsub('%/', '.'):gsub('%.lua', '')
|
local module, msg = fn(modname, env)
|
||||||
|
|
||||||
local module = modules[rname]
|
|
||||||
if not module then
|
if not module then
|
||||||
|
error(msg)
|
||||||
local f, err = loader(fname, env)
|
|
||||||
if not f then
|
|
||||||
error(err)
|
|
||||||
end
|
end
|
||||||
module = f(rname)
|
loaded[modname] = module
|
||||||
modules[rname] = module
|
|
||||||
end
|
|
||||||
|
|
||||||
return module
|
return module
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
error('Unable to find module ' .. modname)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local args = { ... }
|
|
||||||
resolver = args[1] or resolveFile
|
|
||||||
loader = args[2] or loadfile
|
|
||||||
|
|
||||||
return function(env)
|
return function(env)
|
||||||
setfenv(requireWrapper, env)
|
setfenv(requireWrapper, env)
|
||||||
return requireWrapper(env)
|
return requireWrapper(env)
|
||||||
|
@ -120,6 +120,18 @@ function Terminal.toGrayscale(ct)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Terminal.getNullTerm(ct)
|
||||||
|
local nt = Terminal.copy(ct)
|
||||||
|
|
||||||
|
local methods = { 'blit', 'clear', 'clearLine', 'scroll',
|
||||||
|
'setCursorBlink', 'setCursorPos', 'write' }
|
||||||
|
for _,v in pairs(methods) do
|
||||||
|
nt[v] = function() end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nt
|
||||||
|
end
|
||||||
|
|
||||||
function Terminal.copy(ot)
|
function Terminal.copy(ot)
|
||||||
local ct = { }
|
local ct = { }
|
||||||
for k,v in pairs(ot) do
|
for k,v in pairs(ot) do
|
||||||
|
404
sys/apis/ui.lua
404
sys/apis/ui.lua
@ -1,6 +1,8 @@
|
|||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
local class = require('class')
|
local class = require('class')
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
|
local Tween = require('tween')
|
||||||
|
local Region = require('region')
|
||||||
|
|
||||||
local mapColorToGray = {
|
local mapColorToGray = {
|
||||||
[ colors.white ] = colors.white,
|
[ colors.white ] = colors.white,
|
||||||
@ -21,43 +23,16 @@ local mapColorToGray = {
|
|||||||
[ colors.black ] = colors.black,
|
[ colors.black ] = colors.black,
|
||||||
}
|
}
|
||||||
|
|
||||||
local mapColorToPaint = {
|
local mapColorToPaint = { }
|
||||||
[ colors.white ] = '0',
|
for n = 1, 16 do
|
||||||
[ colors.orange ] = '1',
|
mapColorToPaint[2 ^ (n - 1)] = string.sub("0123456789abcdef", n, n)
|
||||||
[ colors.magenta ] = '2',
|
end
|
||||||
[ colors.lightBlue ] = '3',
|
|
||||||
[ colors.yellow ] = '4',
|
|
||||||
[ colors.lime ] = '5',
|
|
||||||
[ colors.pink ] = '6',
|
|
||||||
[ colors.gray ] = '7',
|
|
||||||
[ colors.lightGray ] = '8',
|
|
||||||
[ colors.cyan ] = '9',
|
|
||||||
[ colors.purple ] = 'a',
|
|
||||||
[ colors.blue ] = 'b',
|
|
||||||
[ colors.brown ] = 'c',
|
|
||||||
[ colors.green ] = 'd',
|
|
||||||
[ colors.red ] = 'e',
|
|
||||||
[ colors.black ] = 'f',
|
|
||||||
}
|
|
||||||
|
|
||||||
local mapGrayToPaint = {
|
local mapGrayToPaint = { }
|
||||||
[ colors.white ] = '0',
|
for n = 0, 15 do
|
||||||
[ colors.orange ] = '8',
|
local gs = mapColorToGray[2 ^ n]
|
||||||
[ colors.magenta ] = '8',
|
mapGrayToPaint[2 ^ n] = mapColorToPaint[gs]
|
||||||
[ colors.lightBlue ] = '8',
|
end
|
||||||
[ colors.yellow ] = '8',
|
|
||||||
[ colors.lime ] = '8',
|
|
||||||
[ colors.pink ] = '8',
|
|
||||||
[ colors.gray ] = '7',
|
|
||||||
[ colors.lightGray ] = '8',
|
|
||||||
[ colors.cyan ] = '8',
|
|
||||||
[ colors.purple ] = '7',
|
|
||||||
[ colors.blue ] = '7',
|
|
||||||
[ colors.brown ] = '7',
|
|
||||||
[ colors.green ] = '8',
|
|
||||||
[ colors.red ] = '7',
|
|
||||||
[ colors.black ] = 'f',
|
|
||||||
}
|
|
||||||
|
|
||||||
local function colorToGrayScale(c)
|
local function colorToGrayScale(c)
|
||||||
return mapColorToGray[c]
|
return mapColorToGray[c]
|
||||||
@ -91,24 +66,6 @@ end
|
|||||||
|
|
||||||
--[[-- Top Level Manager --]]--
|
--[[-- Top Level Manager --]]--
|
||||||
local Manager = class()
|
local Manager = class()
|
||||||
Manager.effect = {
|
|
||||||
slideLeft = {
|
|
||||||
type = 'slideLeft',
|
|
||||||
ticks = 12,
|
|
||||||
easing = 'outBounce',
|
|
||||||
},
|
|
||||||
slideRight = {
|
|
||||||
type = 'slideRight',
|
|
||||||
ticks = 12,
|
|
||||||
easing = 'outBounce',
|
|
||||||
},
|
|
||||||
explode = {
|
|
||||||
type = 'explode',
|
|
||||||
ticks = 12,
|
|
||||||
easing = 'outBounce',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
function Manager:init(args)
|
function Manager:init(args)
|
||||||
local control = false
|
local control = false
|
||||||
local shift = false
|
local shift = false
|
||||||
@ -153,7 +110,13 @@ function Manager:init(args)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
Event.addHandler('mouse_click', function(h, button, x, y)
|
Event.addHandler('mouse_click', function(h, button, x, y)
|
||||||
if self.currentPage then
|
|
||||||
|
if button == 1 and shift and control then -- hack
|
||||||
|
|
||||||
|
local event = self:pointToChild(self.target, x, y)
|
||||||
|
multishell.openTab({ path = 'apps/Lua.lua', args = { event.element }, focused = true })
|
||||||
|
|
||||||
|
elseif self.currentPage then
|
||||||
if not self.currentPage.parent.device.side then
|
if not self.currentPage.parent.device.side then
|
||||||
self:click(button, x, y)
|
self:click(button, x, y)
|
||||||
end
|
end
|
||||||
@ -411,6 +374,7 @@ function Manager:setPage(pageOrName, ...)
|
|||||||
if page == self.currentPage then
|
if page == self.currentPage then
|
||||||
page:draw()
|
page:draw()
|
||||||
else
|
else
|
||||||
|
local needSync
|
||||||
if self.currentPage then
|
if self.currentPage then
|
||||||
if self.currentPage.focused then
|
if self.currentPage.focused then
|
||||||
self.currentPage.focused.focused = false
|
self.currentPage.focused.focused = false
|
||||||
@ -418,6 +382,8 @@ function Manager:setPage(pageOrName, ...)
|
|||||||
end
|
end
|
||||||
self.currentPage:disable()
|
self.currentPage:disable()
|
||||||
page.previousPage = self.currentPage
|
page.previousPage = self.currentPage
|
||||||
|
else
|
||||||
|
needSync = true
|
||||||
end
|
end
|
||||||
self.currentPage = page
|
self.currentPage = page
|
||||||
self.currentPage:clear(page.backgroundColor)
|
self.currentPage:clear(page.backgroundColor)
|
||||||
@ -428,7 +394,9 @@ function Manager:setPage(pageOrName, ...)
|
|||||||
self.currentPage.focused:focus()
|
self.currentPage.focused:focus()
|
||||||
end
|
end
|
||||||
self:capture(self.currentPage)
|
self:capture(self.currentPage)
|
||||||
page:sync()
|
if needSync then
|
||||||
|
page:sync() -- first time a page has been set
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -734,6 +702,17 @@ function UI.Window:print(text, bg, fg, indent)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
TODO
|
||||||
|
local test = "\027[0;1;33mYou tell foo, \"// Test string.\"\027[0;37mbar"
|
||||||
|
for sequence, text in string.gmatch (test, "\027%[([0-9;]+)m([^\027]+)") do
|
||||||
|
for ansi in string.gmatch (sequence, "%d+") do
|
||||||
|
print ("ANSI code: ", ansi)
|
||||||
|
end -- for
|
||||||
|
print ("Text: ", text)
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
local lines = Util.split(text)
|
local lines = Util.split(text)
|
||||||
for k,line in pairs(lines) do
|
for k,line in pairs(lines) do
|
||||||
local lx = 1
|
local lx = 1
|
||||||
@ -822,13 +801,13 @@ function UI.Window:scrollIntoView()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Window:setTransition(effect, x, y, width, height)
|
function UI.Window:addTransition(effect, x, y, width, height)
|
||||||
if self.parent then
|
if self.parent then
|
||||||
x = x or 1
|
x = x or 1
|
||||||
y = y or 1
|
y = y or 1
|
||||||
width = width or self.width
|
width = width or self.width
|
||||||
height = height or self.height
|
height = height or self.height
|
||||||
self.parent:setTransition(effect, x + self.x, y + self.y - 1, width, height)
|
self.parent:addTransition(effect, x + self.x - 1, y + self.y - 1, width, height)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -850,6 +829,144 @@ function UI.Window:eventHandler(event)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[-- Blit data manipulation --]]--
|
||||||
|
local Blob = class()
|
||||||
|
function Blob:init(args)
|
||||||
|
self.x = 1
|
||||||
|
self.y = 1
|
||||||
|
self.lines = { }
|
||||||
|
Util.merge(self, args)
|
||||||
|
|
||||||
|
for i = 1, self.ey - self.y + 1 do
|
||||||
|
self.lines[i] = { }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Blob:copy()
|
||||||
|
local b = Blob({ x = self.x, y = self.y, ex = self.ex, ey = self.ey })
|
||||||
|
for i = 1, self.ey - self.y + 1 do
|
||||||
|
b.lines[i].text = self.lines[i].text
|
||||||
|
b.lines[i].fg = self.lines[i].fg
|
||||||
|
b.lines[i].bg = self.lines[i].bg
|
||||||
|
end
|
||||||
|
return b
|
||||||
|
end
|
||||||
|
|
||||||
|
function Blob:write(y, text, fg, bg)
|
||||||
|
self.lines[y].dirty = true
|
||||||
|
self.lines[y].text = text
|
||||||
|
self.lines[y].fg = fg
|
||||||
|
self.lines[y].bg = bg
|
||||||
|
end
|
||||||
|
|
||||||
|
function Blob:reset()
|
||||||
|
self.region = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function Blob:punch(rect)
|
||||||
|
if not self.regions then
|
||||||
|
self.regions = Region.new(self.x, self.y, self.ex, self.ey)
|
||||||
|
end
|
||||||
|
self.regions:subRect(rect.x, rect.y, rect.ex, rect.ey)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Blob:blitClipped(device)
|
||||||
|
for _,region in ipairs(self.regions.region) do
|
||||||
|
self:blit(device,
|
||||||
|
{ x = region[1], y = region[2], ex = region[3], ey = region[4] },
|
||||||
|
{ x = region[1], y = region[2] })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Blob:blit(device, src, tgt)
|
||||||
|
for i = 0, src.ey - src.y do
|
||||||
|
local line = self.lines[src.y + i]
|
||||||
|
local t, fg, bg = line.text, line.fg, line.bg
|
||||||
|
if src.x > 1 or src.ex < self.ex then
|
||||||
|
t = t:sub(src.x, src.ex)
|
||||||
|
fg = fg:sub(src.x, src.ex)
|
||||||
|
bg = bg:sub(src.x, src.ex)
|
||||||
|
end
|
||||||
|
device.setCursorPos(tgt.x, tgt.y + i)
|
||||||
|
device.blit(t, fg, bg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[-- TransitionSlideLeft --]]--
|
||||||
|
UI.TransitionSlideLeft = class()
|
||||||
|
UI.TransitionSlideLeft.defaults = {
|
||||||
|
UIElement = 'TransitionSlideLeft',
|
||||||
|
ticks = 12,
|
||||||
|
easing = 'outBounce',
|
||||||
|
}
|
||||||
|
function UI.TransitionSlideLeft:init(args)
|
||||||
|
local defaults = UI:getDefaults(UI.TransitionSlideLeft, args)
|
||||||
|
UI.setProperties(self, defaults)
|
||||||
|
|
||||||
|
self.pos = { x = self.ex }
|
||||||
|
self.tween = Tween.new(self.ticks, self.pos, { x = self.x }, self.easing)
|
||||||
|
self.lastx = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.TransitionSlideLeft:update(device, screen, lastScreen)
|
||||||
|
self.tween:update(1)
|
||||||
|
local x = math.floor(self.pos.x)
|
||||||
|
if x ~= self.lastx then
|
||||||
|
self.lastx = x
|
||||||
|
lastScreen:blit(device, {
|
||||||
|
x = self.ex - x + self.x,
|
||||||
|
y = self.y,
|
||||||
|
ex = self.ex,
|
||||||
|
ey = self.ey },
|
||||||
|
{ x = self.x, y = self.y })
|
||||||
|
|
||||||
|
screen:blit(device, {
|
||||||
|
x = self.x,
|
||||||
|
y = self.y,
|
||||||
|
ex = self.ex - x + self.x + 1,
|
||||||
|
ey = self.ey },
|
||||||
|
{ x = x, y = self.y })
|
||||||
|
end
|
||||||
|
return self.pos.x ~= self.x
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[-- TransitionSlideRight --]]--
|
||||||
|
UI.TransitionSlideRight = class()
|
||||||
|
UI.TransitionSlideRight.defaults = {
|
||||||
|
UIElement = 'TransitionSlideRight',
|
||||||
|
ticks = 12,
|
||||||
|
easing = 'outBounce',
|
||||||
|
}
|
||||||
|
function UI.TransitionSlideRight:init(args)
|
||||||
|
local defaults = UI:getDefaults(UI.TransitionSlideLeft, args)
|
||||||
|
UI.setProperties(self, defaults)
|
||||||
|
|
||||||
|
self.pos = { x = self.x }
|
||||||
|
self.tween = Tween.new(self.ticks, self.pos, { x = self.ex }, self.easing)
|
||||||
|
self.lastx = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.TransitionSlideRight:update(device, screen, lastScreen)
|
||||||
|
self.tween:update(1)
|
||||||
|
local x = math.floor(self.pos.x)
|
||||||
|
if x ~= self.lastx then
|
||||||
|
self.lastx = x
|
||||||
|
lastScreen:blit(device, {
|
||||||
|
x = self.x,
|
||||||
|
y = self.y,
|
||||||
|
ex = self.ex - x + self.x + 1,
|
||||||
|
ey = self.ey },
|
||||||
|
{ x = x, y = self.y })
|
||||||
|
screen:blit(device, {
|
||||||
|
x = self.ex - x + self.x,
|
||||||
|
y = self.y,
|
||||||
|
ex = self.ex + 1,
|
||||||
|
ey = self.ey },
|
||||||
|
{ x = self.x, y = self.y })
|
||||||
|
end
|
||||||
|
return self.pos.x ~= self.ex
|
||||||
|
end
|
||||||
|
|
||||||
--[[-- Terminal for computer / advanced computer / monitor --]]--
|
--[[-- Terminal for computer / advanced computer / monitor --]]--
|
||||||
UI.Device = class(UI.Window)
|
UI.Device = class(UI.Window)
|
||||||
UI.Device.defaults = {
|
UI.Device.defaults = {
|
||||||
@ -858,9 +975,7 @@ UI.Device.defaults = {
|
|||||||
textColor = colors.white,
|
textColor = colors.white,
|
||||||
textScale = 1,
|
textScale = 1,
|
||||||
effectsEnabled = true,
|
effectsEnabled = true,
|
||||||
lines = { },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function UI.Device:init(args)
|
function UI.Device:init(args)
|
||||||
local defaults = UI:getDefaults(UI.Device)
|
local defaults = UI:getDefaults(UI.Device)
|
||||||
defaults.device = term.current()
|
defaults.device = term.current()
|
||||||
@ -879,6 +994,16 @@ function UI.Device:init(args)
|
|||||||
|
|
||||||
UI.Window.init(self, defaults)
|
UI.Window.init(self, defaults)
|
||||||
|
|
||||||
|
self.blob = Blob({
|
||||||
|
x = 1, y = 1, ex = self.width, ey = self.height
|
||||||
|
})
|
||||||
|
for i = 1, self.height do
|
||||||
|
self.blob:write(i,
|
||||||
|
string.rep(' ', self.width),
|
||||||
|
string.rep(colorToPaintColor(self.backgroundColor, self.isColor), self.width),
|
||||||
|
string.rep(colorToPaintColor(self.textColor, self.isColor), self.width))
|
||||||
|
end
|
||||||
|
|
||||||
self.isColor = self.device.isColor()
|
self.isColor = self.device.isColor()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -914,131 +1039,74 @@ function UI.Device:reset()
|
|||||||
self.device.setCursorPos(1, 1)
|
self.device.setCursorPos(1, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Device:setTransition(effect, x, y, width, height)
|
function UI.Device:addTransition(effect, x, y, width, height)
|
||||||
if not self.transition then
|
if not self.transitions then
|
||||||
self.transition = effect
|
self.transitions = { }
|
||||||
effect.x = x
|
|
||||||
effect.y = y
|
|
||||||
effect.width = width
|
|
||||||
effect.height = height
|
|
||||||
for i = y, y + height - 1 do
|
|
||||||
local line = self.lines[i]
|
|
||||||
if line then
|
|
||||||
line.transition = true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if type(effect) == 'string' then
|
||||||
|
local c
|
||||||
|
if effect == 'slideLeft' then
|
||||||
|
c = UI.TransitionSlideLeft
|
||||||
|
else
|
||||||
|
c = UI.TransitionSlideRight
|
||||||
end
|
end
|
||||||
|
effect = c {
|
||||||
|
x = x,
|
||||||
|
y = y,
|
||||||
|
ex = x + width - 1,
|
||||||
|
ey = y + height - 1,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
table.insert(self.transitions, effect)
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Device:runTransition(effect)
|
function UI.Device:runTransitions(transitions)
|
||||||
|
|
||||||
if not self.Tween then
|
for _,t in ipairs(transitions) do
|
||||||
self.Tween = require('tween')
|
self.blob:punch(t) -- punch out the effect areas
|
||||||
end
|
end
|
||||||
|
self.blob:blitClipped(self.device) -- and blit the remainder
|
||||||
|
self.blob:reset()
|
||||||
|
|
||||||
if effect.type == 'slideLeft' or effect.type == 'slideRight' then
|
while true do
|
||||||
for y, line in ipairs(self.lines) do
|
for _,k in ipairs(Util.keys(transitions)) do
|
||||||
if not line.transition then
|
local transition = transitions[k]
|
||||||
self.device.setCursorPos(1, y)
|
if not transition:update(self.device, self.blob, self.lastScreen) then
|
||||||
self.device.blit(line.text, line.fg, line.bg)
|
transitions[k] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if Util.empty(transitions) then
|
||||||
local pos = { x = 1 }
|
break
|
||||||
local tween = self.Tween.new(effect.ticks, pos, { x = self.width }, effect.easing)
|
|
||||||
|
|
||||||
local lastx = 0
|
|
||||||
repeat
|
|
||||||
tween:update(1)
|
|
||||||
local x = math.floor(pos.x)
|
|
||||||
if x ~= lastx then
|
|
||||||
lastx = x
|
|
||||||
for y, line in pairs(self.lines) do
|
|
||||||
if line.transition then
|
|
||||||
if effect.type == 'slideLeft' then
|
|
||||||
local text = self.lastScreen[y].text .. line.text
|
|
||||||
local bg = self.lastScreen[y].bg .. line.bg
|
|
||||||
local fg = self.lastScreen[y].fg .. line.fg
|
|
||||||
self.device.setCursorPos(1 - x, y)
|
|
||||||
self.device.blit(text, fg, bg)
|
|
||||||
else
|
|
||||||
local text = line.text .. self.lastScreen[y].text
|
|
||||||
local bg = line.bg .. self.lastScreen[y].bg
|
|
||||||
local fg = line.fg .. self.lastScreen[y].fg
|
|
||||||
self.device.setCursorPos(-self.width + x + 1, y)
|
|
||||||
self.device.blit(text, fg, bg)
|
|
||||||
end
|
end
|
||||||
end
|
Event.sleep()
|
||||||
end
|
|
||||||
end
|
|
||||||
os.sleep()
|
|
||||||
until pos.x == self.width
|
|
||||||
|
|
||||||
elseif effect.type == 'explode' then
|
|
||||||
local pos = { x = 1 }
|
|
||||||
local tween = self.Tween.new(effect.ticks, pos, { x = 100 }, effect.easing)
|
|
||||||
local mx = math.floor(effect.width / 2)
|
|
||||||
local my = math.floor(effect.height / 2)
|
|
||||||
|
|
||||||
local function replace(sstr, pos, rstr, width)
|
|
||||||
return sstr:sub(1, pos-1) .. rstr .. sstr:sub(pos+width)
|
|
||||||
end
|
|
||||||
|
|
||||||
debug('running')
|
|
||||||
repeat
|
|
||||||
tween:update(1)
|
|
||||||
local ux = math.floor(effect.width * pos.x / 200)
|
|
||||||
local uy = math.floor(effect.height * pos.x / 200)
|
|
||||||
local width = ux * 2
|
|
||||||
local sx = mx - ux + 1
|
|
||||||
debug({ pos.x, ux, uy })
|
|
||||||
for y = my - uy, my + uy do
|
|
||||||
local line = self.lines[y]
|
|
||||||
if line then
|
|
||||||
self.device.setCursorPos(1, y)
|
|
||||||
self.device.blit(
|
|
||||||
replace(self.lastScreen[y].text, sx, line.text:sub(sx, sx + width - 1), width),
|
|
||||||
replace(self.lastScreen[y].fg, sx, line.fg:sub(sx, sx + width - 1), width),
|
|
||||||
replace(self.lastScreen[y].bg, sx, line.bg:sub(sx, sx + width - 1), width))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
os.sleep(.4)
|
|
||||||
until pos.x == 100
|
|
||||||
debug('done running')
|
|
||||||
end
|
|
||||||
|
|
||||||
for y, line in ipairs(self.lines) do
|
|
||||||
line.dirty = false
|
|
||||||
line.transition = false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Device:sync()
|
function UI.Device:sync()
|
||||||
|
|
||||||
local transition
|
local transitions
|
||||||
if self.transition and self.effectsEnabled then
|
if self.transitions and self.effectsEnabled then
|
||||||
for y, line in pairs(self.lines) do
|
transitions = self.transitions
|
||||||
if line.dirty then
|
self.transitions = nil
|
||||||
transition = self.transition
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.transition = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if transition then
|
if transitions then
|
||||||
self:runTransition(transition)
|
self:runTransitions(transitions)
|
||||||
else
|
else
|
||||||
for y, line in pairs(self.lines) do
|
for y, line in pairs(self.blob.lines) do
|
||||||
if line.dirty then
|
if line.dirty then
|
||||||
self.device.setCursorPos(1, y)
|
self.device.setCursorPos(1, y)
|
||||||
self.device.blit(line.text, line.fg, line.bg)
|
self.device.blit(line.text, line.fg, line.bg)
|
||||||
line.dirty = false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self.lastScreen = Util.deepCopy(self.lines)
|
self.lastScreen = self.blob:copy()
|
||||||
|
|
||||||
|
for y, line in ipairs(self.blob.lines) do
|
||||||
|
line.dirty = false
|
||||||
|
end
|
||||||
|
|
||||||
if self:getCursorBlink() then
|
if self:getCursorBlink() then
|
||||||
self.device.setCursorPos(self.cursorX, self.cursorY)
|
self.device.setCursorPos(self.cursorX, self.cursorY)
|
||||||
@ -1049,14 +1117,6 @@ function UI.Device:write(x, y, text, bg, tc)
|
|||||||
|
|
||||||
if y > 0 and y <= self.height and x <= self.width then
|
if y > 0 and y <= self.height and x <= self.width then
|
||||||
|
|
||||||
if not self.lines[y] then
|
|
||||||
self.lines[y] = {
|
|
||||||
text = string.rep(' ', self.width),
|
|
||||||
bg = string.rep(colorToPaintColor(self.backgroundColor, self.isColor), self.width),
|
|
||||||
fg = string.rep(colorToPaintColor(self.textColor, self.isColor), self.width),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local width = #text
|
local width = #text
|
||||||
|
|
||||||
if x < 1 then
|
if x < 1 then
|
||||||
@ -1080,7 +1140,7 @@ function UI.Device:write(x, y, text, bg, tc)
|
|||||||
return sstr:sub(1, pos-1) .. string.rep(rstr, width) .. sstr:sub(pos+width)
|
return sstr:sub(1, pos-1) .. string.rep(rstr, width) .. sstr:sub(pos+width)
|
||||||
end
|
end
|
||||||
|
|
||||||
local line = self.lines[y]
|
local line = self.blob.lines[y]
|
||||||
line.dirty = true
|
line.dirty = true
|
||||||
line.text = replace(line.text, x, text, width)
|
line.text = replace(line.text, x, text, width)
|
||||||
if bg then
|
if bg then
|
||||||
@ -2113,9 +2173,9 @@ function UI.Tabs:eventHandler(event)
|
|||||||
for _,tab in ipairs(self.children) do
|
for _,tab in ipairs(self.children) do
|
||||||
if tab ~= self.tabBar then
|
if tab ~= self.tabBar then
|
||||||
if event.current > event.last then
|
if event.current > event.last then
|
||||||
tab:setTransition(UI.effect.slideLeft)
|
tab:addTransition('slideLeft')
|
||||||
else
|
else
|
||||||
tab:setTransition(UI.effect.slideRight)
|
tab:addTransition('slideRight')
|
||||||
end
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@ -2145,7 +2205,7 @@ function UI.WindowScroller:nextChild()
|
|||||||
for i = 1, #self.children do
|
for i = 1, #self.children do
|
||||||
if self.children[i].enabled then
|
if self.children[i].enabled then
|
||||||
if i < #self.children then
|
if i < #self.children then
|
||||||
self:setTransition(UI.effect.slideLeft)
|
self:addTransition('slideLeft')
|
||||||
self.children[i]:disable()
|
self.children[i]:disable()
|
||||||
self.children[i + 1]:enable()
|
self.children[i + 1]:enable()
|
||||||
end
|
end
|
||||||
@ -2158,7 +2218,7 @@ function UI.WindowScroller:prevChild()
|
|||||||
for i = 1, #self.children do
|
for i = 1, #self.children do
|
||||||
if self.children[i].enabled then
|
if self.children[i].enabled then
|
||||||
if i - 1 > 0 then
|
if i - 1 > 0 then
|
||||||
self:setTransition(UI.effect.slideRight)
|
self:addTransition('slideRight')
|
||||||
self.children[i]:disable()
|
self.children[i]:disable()
|
||||||
self.children[i - 1]:enable()
|
self.children[i - 1]:enable()
|
||||||
end
|
end
|
||||||
|
@ -457,6 +457,7 @@ end
|
|||||||
local function getopt( arg, options )
|
local function getopt( arg, options )
|
||||||
local tab = {}
|
local tab = {}
|
||||||
for k, v in ipairs(arg) do
|
for k, v in ipairs(arg) do
|
||||||
|
if type(v) == 'string' then
|
||||||
if string.sub( v, 1, 2) == "--" then
|
if string.sub( v, 1, 2) == "--" then
|
||||||
local x = string.find( v, "=", 1, true )
|
local x = string.find( v, "=", 1, true )
|
||||||
if x then tab[ string.sub( v, 3, x-1 ) ] = string.sub( v, x+1 )
|
if x then tab[ string.sub( v, 3, x-1 ) ] = string.sub( v, x+1 )
|
||||||
@ -482,6 +483,7 @@ local function getopt( arg, options )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
return tab
|
return tab
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user