Upload System Image

This commit is contained in:
Bommels05
2025-10-21 00:40:14 +02:00
parent 16da0a1837
commit acf66baf57
56 changed files with 28248 additions and 61 deletions

221
LevelOS/Changelog.lua Normal file
View File

@@ -0,0 +1,221 @@
if LevelOS and LevelOS.self and LevelOS.self.window then
LevelOS.self.window.winMode = "widget"
end
local oldlog = lUtils.asset.load("LevelOS/data/nativelog.lconf") or {}
local newlog = lUtils.asset.load("LevelOS/data/changelog.lconf")
if newlog then
fs.delete("LevelOS/data/nativelog.lconf")
fs.move("LevelOS/data/changelog.lconf","LevelOS/data/nativelog.lconf")
elseif oldlog then
newlog = oldlog
end
local run = false
for c=1,#newlog do
if not oldlog[c] then
newlog[c].new = true
run = true
end
end
local txt = term.setTextColor
local bg = term.setBackgroundColor
local function clr()
local w,h = term.getSize()
local x,y = term.getCursorPos()
term.setCursorPos(19,y)
term.write(string.rep(" ",w-21))
term.setCursorPos(x,y)
end
local function wr(text,color,mX,mY) --max x and y
if color then
txt(color)
end
local x,y = term.getCursorPos()
local cX = x
local cY = y
for word in text:gmatch("%S+") do
--[[if cX ~= x then
word = " "..word
end]]
if cX+#word <= mX then
term.write(word.." ")
cX = cX+#word+1
elseif cY < mY then
cX = x
cY = cY+1
term.setCursorPos(cX,cY)
clr()
term.write(word.." ")
cX = cX+#word+1
else
return (cY-y)+1
end
end
return (cY-y)+1
end
local function rm() -- reached max
local x,y = term.getCursorPos()
local w,h = term.getSize()
if y >= h then
return true
else
return false
end
end
function render(s)
local function cp(x,y)
term.setCursorPos(x,y+s)
end
bg(colors.cyan)
term.clear()
txt(colors.cyan)
bg(colors.white)
local w,h = term.getSize()
for t=0,h-s do
cp(14,4+t)
term.write("\149")
end
-- write with window height as max Y and width-4 as max X
local cY = 1
for k=#newlog,1,-1 do
local v = newlog[k]
cY = cY+2
-- the date
cp(2,cY+1)
bg(colors.cyan)
txt(colors.white)
term.write(v.date)
cp(13,cY)
-- cyan = 9, white = 0, lime=5
-- the dot
if k == #newlog then -- to check if its on top (for the line)
term.blit("\159\143\143","999","000")
else
term.blit("\159\133\143","999","000")
end
cp(13,cY+1)
if v.major then -- if major version make orange dot
term.blit("\149 \149","911","010")
else
term.blit("\149 \149","955","050")
end
cp(13,cY+2)
term.blit("\130\148\131","090","909")
-- the actual box
bg(colors.white)
txt(colors.cyan)
cp(19,cY)
clr()
--term.write("\151\129")
term.write("\129")
cp(w-3,cY)
term.write("\130")
--term.blit("\148","0","9")
--[[cY = cY+1
cp(19,cY)
clr()]]
cY = cY+1
cp(18,cY)
clr()
term.write("\145 ")
term.write("v"..v.version)
if v.new then
txt(colors.orange)
term.write(" New!")
end
cY = cY+1
cp(19,cY)
clr()
cY = cY+1
cp(20,cY)
clr()
if v.description then
cY = cY-1
cp(21,cY)
bg(colors.white)
txt(colors.black)
cY = cY+wr(v.description,nil,w-4,h)
cp(20,cY)
clr()
cY = cY+1
cp(20,cY)
clr()
end
if v.added and #v.added > 0 then
bg(colors.lime)
txt(colors.white)
term.write(" NEW ")
cY = cY+1
bg(colors.white)
cp(19,cY)
clr()
cY = cY+1
txt(colors.black)
for t=1,#v.added do
cp(21,cY)
clr()
term.write("\7 ")
cY = cY+wr(v.added[t],nil,w-4,h)
end
cp(20,cY)
clr()
end
if v.fixed and #v.fixed > 0 then
if v.added and #v.added > 0 then
cY = cY+1
cp(20,cY)
clr()
end
bg(colors.lightBlue)
txt(colors.white)
term.write(" FIXED ")
cY = cY+1
bg(colors.white)
cp(19,cY)
clr()
cY = cY+1
txt(colors.black)
for t=1,#v.fixed do
cp(21,cY)
clr()
term.write("\7 ")
cY = cY+wr(v.fixed[t],nil,w-4,h)
end
end
bg(colors.white)
txt(colors.cyan)
cp(19,cY)
clr()
cY = cY+1
cp(19,cY)
clr()
term.write("\144")
cp(w-3,cY)
term.blit("\159","0","9")
if rm() then break end
end
term.setCursorPos(1,1)
bg(colors.cyan)
txt(colors.white)
term.clearLine()
term.setCursorPos(2,1)
term.write("Changelog")
term.setCursorPos(w-2,1)
term.write("×")
end
render(0)
local scroll = 0
while true do
local e = {os.pullEvent()}
local w,h = term.getSize()
if e[1] == "term_resize" then
render(scroll)
elseif e[1] == "mouse_scroll" and scroll-e[2] <= 0 then
scroll = scroll-e[2]
render(scroll)
elseif e[1] == "mouse_up" and e[3] == w-2 and e[4] == 1 then
return
end
end

897
LevelOS/Clock.lua Normal file
View File

@@ -0,0 +1,897 @@
local assets = {
[ "slider.lua" ] = {
id = 1,
content = "local s = shapescape.getSlide()\
if not s.var then s.var = {} end\
\
local set = \"LevelOS/data/settings.lconf\"\
\
if lOS.settings.rTime == nil then\
lOS.settings.rTime = false\
end\
\
local r = string.rep\
\
local rtime = lOS.settings.rTime\
\
local w,h = term.getSize()\
\
if rtime then\
term.setBackgroundColor(colors.green)\
term.setCursorPos(1,1)\
term.write(r(\" \",w-1))\
term.setBackgroundColor(colors.white)\
term.write(\" \")\
else\
term.setCursorPos(1,1)\
term.setBackgroundColor(colors.white)\
term.write(\" \")\
term.setBackgroundColor(colors.red)\
term.write(r(\" \",w-1))\
end\
\
while true do\
local w,h = term.getSize()\
if lOS.settings.rTime ~= rtime then\
rtime = lOS.settings.rTime\
local b1,b2,fg\
b1 = \"d\"\
b2 = \"e\"\
fg = \"0\"\
local a,b,c\
if rtime then\
a,b,c = 1,w,1\
else\
a,b,c = w,1,-1\
end\
for x=a,b,c do\
local d,e = x-1,w-x\
term.setCursorPos(1,1)\
term.blit(r(\" \",d)..\" \"..r(\" \",e),r(\"f\",w),r(b1,d)..fg..r(b2,e))\
os.sleep(0.05)\
end\
end\
e = {os.pullEvent()}\
end",
name = "slider.lua",
},
[ "switch_time.lua" ] = {
id = 2,
content = "lOS.settings.rTime = not lOS.settings.rTime",
name = "switch_time.lua",
},
[ "rendercalender.lua" ] = {
id = 7,
content = "local w,h = term.getSize()\
while h < 21 do\
os.pullEvent()\
w,h = term.getSize()\
end\
local epoch = os.epoch(\"local\")/1000\
local date = os.date(\"*t\",epoch)\
local targetmonth = date.month\
local targetyear = date.year\
local d = {}\
d.sec = 1\
d.min = d.sec*60\
d.hour = d.min*60\
d.day = d.hour*24\
local function dayadd()\
epoch = epoch+d.day\
date = os.date(\"*t\",epoch)\
end\
local function daysub()\
epoch = epoch-d.day\
date = os.date(\"*t\",epoch)\
end\
while date.year < targetyear or date.month < targetmonth do\
dayadd()\
end\
term.setBackgroundColor(colors.gray)\
term.setTextColor(colors.white)\
term.clear()\
term.setCursorPos(1,1)\
term.write(os.date(\"%B %Y\"))\
term.setCursorPos(1,3)\
days = {\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\",\"Su\"}\
for t=1,7 do\
term.write(\" \"..days[t]..\" \")\
end\
local x = term.getCursorPos()\
term.setCursorPos(x-3,1)\
--LevelOS.setWin(x-1,24)\
term.write(\"\\30 \\31\")\
while date.day > 1 do\
daysub()\
end\
while date.wday ~= 2 do\
daysub()\
end\
local current = os.date(\"*t\")\
for w=1,6 do\
--term.setCursorPos(1,5+(w-1)*3)\
for t=1,7 do\
local x,y = 1+(t-1)*4,5+(w-1)*3\
local cur = false\
if current.day == date.day and current.month == date.month and current.year == date.year then\
term.setTextColor(colors.black)\
term.setBackgroundColor(colors.lightGray)\
lUtils.border(x,y-1,x+3,y+1)\
cur = true\
else\
term.setBackgroundColor(colors.gray)\
end\
if targetmonth == date.month then\
term.setTextColor(colors.white)\
elseif cur then\
term.setTextColor(colors.gray)\
else\
term.setTextColor(colors.lightGray)\
end\
term.setCursorPos(x+1,y)\
term.write(os.date(\"%d\",epoch))\
dayadd()\
end\
end\
while true do os.pullEvent() end",
name = "rendercalender.lua",
},
[ "offset.lua" ] = {
id = 3,
content = "if lOS.settings.timeOffset then\
local o = lOS.settings.timeOffset\
if o >= 0 then\
self.txt = \"+\"..o\
else\
self.txt = tostring(o)\
end\
end",
name = "offset.lua",
},
[ "offset_up.lua" ] = {
id = 5,
content = "lOS.settings.timeOffset = lOS.settings.timeOffset + 0.5",
name = "offset_up.lua",
},
[ "time.lua" ] = {
id = 0,
content = "if not lOS.settings.timeOffset then\
lOS.settings.timeOffset = 0\
end\
local t = os.date(\"*t\",os.epoch(\"utc\")/1000+lOS.settings.timeOffset*3600)\
term.setBackgroundColor(colors.gray)\
term.setTextColor(colors.white)\
term.setCursorPos(self.x1,self.y1)\
local function tz(n)\
return string.rep(\"0\",2-string.len(n))..n\
end\
if lOS.settings.rTime then\
bigfont.bigPrint(tz(t.hour)..\":\"..tz(t.min)..\":\"..tz(t.sec))\
else\
local nTime = (os.time()+lOS.settings.timeOffset)%24\
local nHour = math.floor(nTime)\
local nMinute = math.floor((nTime - nHour) * 60)\
bigfont.bigPrint(tz(nHour)..\":\"..tz(nMinute))\
end\
term.setTextColor(colors.lightGray)\
local days = {\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"}\
local months = {\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"}\
term.setCursorPos(self.x1,({term.getCursorPos()})[2])\
print(days[t.wday]..\", \"..months[t.month]..\" \"..t.day..\", \"..t.year)",
name = "time.lua",
},
[ "init.lua" ] = {
id = 4,
content = "local w,h = 27,13\
local tw,th = lOS.wAll.getSize()\
if th >= 40 then\
w,h = 32,36\
end\
LevelOS.setWin(w,h,\"widget\")\
LevelOS.self.window.win.reposition(tw-w,th-(h-1+lOS.tbSize))",
name = "init.lua",
},
[ "offset_down.lua" ] = {
id = 6,
content = "lOS.settings.timeOffset = lOS.settings.timeOffset - 0.5",
name = "offset_down.lua",
},
}
local nAssets = {}
for key,value in pairs(assets) do nAssets[key] = value nAssets[assets[key].id] = assets[key] end
assets = nAssets
nAssets = nil
local slides = {
{
y = 21,
x = 61,
h = 19,
w = 51,
objs = {
{
x2 = 51,
y2 = 19,
y1 = 1,
x1 = 1,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = 4,
},
},
ox2 = 0,
color = 128,
border = {
color = 256,
type = 1,
},
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap left",
Bottom = "Snap bottom",
},
oy2 = 0,
},
{
x2 = 26,
y2 = 4,
border = {
color = 128,
type = 1,
},
x1 = 3,
txt = "",
type = "text",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
render = {
[ 2 ] = 0,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 1,
color = 128,
snap = {
Top = "Snap top",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap top",
},
y1 = 2,
},
{
x2 = 50,
y2 = 8,
y1 = 7,
x1 = 2,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
ox2 = 1,
color = 128,
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap left",
Bottom = "Snap top",
},
border = {
color = 256,
type = 1,
},
},
{
x2 = 50,
y2 = 8,
y1 = 8,
x1 = 2,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
ox2 = 1,
color = 128,
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap left",
Bottom = "Snap top",
},
border = {
color = 0,
type = 1,
},
},
{
type = "rect",
color = 128,
y2 = 7,
y1 = 7,
x1 = 2,
x2 = 2,
border = {
color = 0,
type = 1,
},
snap = {
Top = "Snap top",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap top",
},
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
},
{
x2 = 50,
y2 = 7,
y1 = 7,
x1 = 50,
ox1 = 1,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
ox2 = 1,
color = 128,
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap right",
Bottom = "Snap top",
},
border = {
color = 0,
type = 1,
},
},
{
color = 128,
y2 = 8,
y1 = 8,
x1 = 11,
txt = "Use real time",
type = "text",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 1,
input = false,
x2 = 23,
border = {
color = 0,
type = 1,
},
},
{
color = 1,
y2 = 12,
y1 = 10,
x1 = 3,
txt = "+0",
type = "text",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = 3,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 32768,
input = false,
x2 = 9,
border = {
color = 256,
type = 1,
},
},
{
x2 = 9,
y2 = 10,
y1 = 10,
x1 = 3,
txt = " ",
type = "text",
event = {
mouse_up = {
[ 2 ] = 5,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 1,
input = false,
color = 256,
snap = {
Top = "Snap top",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap top",
},
border = {
color = 0,
type = 1,
},
},
{
color = 256,
y2 = 12,
y1 = 12,
x1 = 3,
txt = " ",
type = "text",
event = {
mouse_up = {
[ 2 ] = 6,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 1,
input = false,
x2 = 9,
border = {
color = 0,
type = 1,
},
},
{
color = 128,
y2 = 11,
y1 = 11,
x1 = 11,
txt = "Offset (hours)",
type = "text",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 1,
input = false,
x2 = 26,
border = {
color = 0,
type = 1,
},
},
{
type = "window",
color = 32768,
y2 = 8,
border = {
color = 0,
type = 1,
},
x1 = 3,
y1 = 8,
x2 = 9,
snap = {
Top = "Snap top",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap top",
},
event = {
mouse_up = {
[ 2 ] = 2,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = 1,
},
},
},
{
color = 128,
y2 = 15,
border = {
color = 256,
type = 1,
},
x1 = 2,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
ox2 = 1,
x2 = 50,
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap left",
Bottom = "Snap top",
},
y1 = 14,
},
{
type = "rect",
x2 = 2,
y2 = 14,
border = {
color = 0,
type = 1,
},
x1 = 2,
color = 128,
y1 = 14,
snap = {
Top = "Snap top",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap top",
},
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
},
{
color = 128,
y2 = 14,
border = {
color = 0,
type = 1,
},
x1 = 50,
ox1 = 1,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
ox2 = 1,
x2 = 50,
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap right",
Bottom = "Snap top",
},
y1 = 14,
},
{
color = 128,
y2 = 15,
border = {
color = 0,
type = 1,
},
x1 = 2,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
Initialize = {
[ 2 ] = -1,
},
selected = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
ox2 = 1,
x2 = 50,
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap left",
Bottom = "Snap top",
},
y1 = 15,
},
{
x2 = 49,
y2 = 18,
border = {
color = 0,
type = 1,
},
x1 = 3,
type = "window",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = 7,
},
},
ox2 = 2,
color = 32768,
y1 = 15,
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap left",
Bottom = "Snap bottom",
},
oy2 = 1,
},
},
c = 1,
},
{
y = 21,
x = 61,
h = 19,
w = 51,
objs = {},
c = 2,
},
}
for s=1,#slides do
local slide = slides[s]
for o=1,#slide.objs do
local obj = slide.objs[o]
for key,value in pairs(obj.event) do
if assets[ value[2] ] then
lUtils.shapescape.addScript(obj,value[2],key,assets,LevelOS,slides)
else
obj.event[key] = {function() end,-1}
end
end
end
end
local tArgs = {...}
if tArgs[1] and tArgs[1] == "load" then
return {assets=assets,slides=slides}
end
lUtils.shapescape.run(slides,...)

2063
LevelOS/Global_Login.lua Normal file

File diff suppressed because it is too large Load Diff

1734
LevelOS/Login_screen.sgui Normal file

File diff suppressed because it is too large Load Diff

124
LevelOS/Notification.lua Normal file
View File

@@ -0,0 +1,124 @@
local tArgs = {...}
if not tArgs then return end
local sID = #lOS.notifWins+1
lOS.notifWins[sID] = LevelOS.self.window
local function count(tbl)
local c = 0
for k,v in pairs(tbl) do
c = c+1
end
return c
end
local nAmount = count(lOS.notifWins)
term.setBackgroundColor(colors.gray)
term.clear()
local x,y = 2,2
local icon
if type(tArgs[3]) == "string" and fs.exists(tArgs[3]) and lOS.getIcon then
icon = lOS.getIcon(tArgs[3])
end
if icon then
lUtils.renderImg(icon,x,y)
x = x+4
end
if type(tArgs[1]) == "string" then
term.setCursorPos(x,y)
term.setTextColor(colors.white)
local w,h = term.getSize()
local nw = w-x
local txt = lUtils.wordwrap(tArgs[1],nw-1)
if y+#txt > h then
local dif = y+#txt-h
local wX,wY = LevelOS.self.window.win.getPosition()
wY = wY-dif
h = h+dif
LevelOS.self.window.win.reposition(wX,wY,w,h)
end
for t=1,#txt do
term.setCursorPos(x,y)
term.write(txt[t])
y = y+1
end
end
if type(tArgs[2]) == "string" then
term.setCursorPos(x,y)
term.setTextColor(colors.lightGray)
local w,h = term.getSize()
local nw = w-x
local txt = lUtils.wordwrap(tArgs[2],nw)
if y+#txt > h then
local dif = y+#txt-h
local wX,wY = LevelOS.self.window.win.getPosition()
wY = wY-dif
h = h+dif
LevelOS.self.window.win.reposition(wX,wY,w,h)
end
for t=1,#txt do
term.setCursorPos(x,y)
term.write(txt[t])
y = y+1
end
end
local w,h = term.getSize()
term.setCursorPos(w-1,2)
term.setTextColor(colors.lightGray)
term.write("×")
local timer = 3
if type(tArgs[4]) == "string" and tonumber(tArgs[4]) then
timer = tonumber(tArgs[4])
end
local tID = os.startTimer(timer)
local tID2
local sel = false
while true do
local e = {os.pullEvent()}
if e[1] == "timer" and e[2] == tID then
break
elseif e[1]:find("mouse") and e[3] and e[4] then
if e[3] == w-1 and e[4] == 2 then
if e[1] == "mouse_hover" then
term.setCursorPos(w-1,2)
term.setTextColor(colors.white)
term.write("×")
sel = true
elseif e[1] == "mouse_click" then
term.setCursorPos(w-1,2)
term.setTextColor(colors.red)
term.write("×")
sel = true
elseif e[1] == "mouse_up" and sel then
break
end
end
if e[1] == "mouse_up" and sel then
term.setCursorPos(w-1,2)
term.setTextColor(colors.lightGray)
term.write("×")
sel = false
end
end
--if count(lOS.notifWins) ~= nAmount then
nAmount = count(lOS.notifWins)
local tW,tH = lOS.wAll.getSize()
local w,h = term.getSize()
local newY = tH-h-lOS.tbSize
local x,y = LevelOS.self.window.win.getPosition()
for k,v in pairs(lOS.notifWins) do
--if v ~= LevelOS.self.window then
local tx,ty = v.win.getPosition()
if ty-h-1 <= newY and ty > y then -- use actual height
newY = ty-h-1
end
--end
end
if newY > y then
if not tID2 then
tID2 = os.startTimer(0.3)
elseif tID2 and e[1] == "timer" and e[2] == tID2 then
LevelOS.self.window.win.reposition(x,newY)
tID2 = nil
end
end
--end
end
lOS.notifWins[sID] = nil

725
LevelOS/Notifications.lua Normal file
View File

@@ -0,0 +1,725 @@
local assets = {}
local nAssets = {}
for key,value in pairs(assets) do nAssets[key] = value nAssets[assets[key].id] = assets[key] end
assets = nAssets
nAssets = nil
local slides = {
{
y = 21,
x = 70,
w = 32,
h = 19,
objs = {
{
type = "rect",
color = 32768,
y2 = 19,
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
x1 = 1,
x2 = 32,
border = {
color = 0,
type = 1,
},
y1 = 1,
},
{
type = "rect",
color = 128,
y2 = 6,
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
},
x1 = 2,
y1 = 2,
border = {
color = 0,
type = 1,
},
x2 = 31,
},
{
x2 = 19,
y2 = 3,
border = {
color = 0,
type = 1,
},
x1 = 8,
txt = "Notification",
type = "text",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
},
txtcolor = 1,
input = false,
color = 0,
y1 = 3,
},
{
type = "rect",
color = 16384,
y2 = 5,
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
},
x1 = 4,
y1 = 3,
border = {
color = 0,
type = 1,
},
x2 = 6,
},
{
x2 = 30,
y2 = 5,
border = {
color = 0,
type = 1,
},
x1 = 8,
txt = "This is a notification to tell you things yes.",
type = "text",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
},
txtcolor = 256,
input = false,
color = 0,
y1 = 4,
},
{
x2 = 30,
y2 = 3,
border = {
color = 0,
type = 1,
},
x1 = 30,
txt = "×",
type = "text",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
},
txtcolor = 256,
input = false,
color = 0,
y1 = 3,
},
},
c = 1,
},
{
y = 21,
x = 70,
c = 2,
objs = {
{
type = "rect",
color = 128,
y2 = 6,
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
},
x1 = 2,
x2 = 31,
y1 = 2,
border = {
color = 0,
type = 1,
},
},
{
type = "rect",
color = 16384,
y2 = 5,
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
},
x1 = 3,
x2 = 5,
y1 = 3,
border = {
color = 0,
type = 1,
},
},
{
color = 0,
y2 = 3,
y1 = 3,
x1 = 7,
txt = "Notification",
type = "text",
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
},
txtcolor = 1,
input = false,
x2 = 18,
border = {
color = 0,
type = 1,
},
},
{
color = 0,
y2 = 5,
y1 = 4,
x1 = 7,
txt = "This is a notification to tell you things yes.",
type = "text",
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
},
txtcolor = 256,
input = false,
x2 = 30,
border = {
color = 0,
type = 1,
},
},
{
color = 0,
y2 = 3,
y1 = 3,
x1 = 30,
txt = "×",
type = "text",
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
},
txtcolor = 256,
input = false,
x2 = 30,
border = {
color = 0,
type = 1,
},
},
{
type = "rect",
color = 128,
y2 = 12,
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
x1 = 2,
border = {
color = 0,
type = 1,
},
x2 = 31,
y1 = 8,
},
{
color = 0,
y2 = 9,
y1 = 9,
x1 = 3,
txt = "Notification",
type = "text",
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 1,
input = false,
x2 = 14,
border = {
color = 0,
type = 1,
},
},
{
x2 = 30,
y2 = 11,
border = {
color = 0,
type = 1,
},
x1 = 3,
txt = "This notification has no icon available.",
type = "text",
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 256,
input = false,
color = 0,
y1 = 10,
},
{
x2 = 30,
y2 = 9,
border = {
color = 0,
type = 1,
},
x1 = 30,
txt = "×",
type = "text",
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 256,
input = false,
color = 0,
y1 = 9,
},
{
type = "rect",
color = 128,
y2 = 19,
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
},
x1 = 2,
border = {
color = 0,
type = 1,
},
y1 = 14,
x2 = 31,
},
{
type = "rect",
color = 16384,
y2 = 17,
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
x1 = 3,
x2 = 5,
border = {
color = 0,
type = 1,
},
y1 = 15,
},
{
color = 0,
y2 = 15,
y1 = 15,
x1 = 7,
txt = "Notification",
type = "text",
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 1,
input = false,
x2 = 18,
border = {
color = 0,
type = 1,
},
},
{
color = 0,
y2 = 18,
y1 = 16,
x1 = 7,
txt = "This notification does not have enough space so it expands downwards.",
type = "text",
event = {
render = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
mouse_up = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
txtcolor = 256,
input = false,
x2 = 30,
border = {
color = 0,
type = 1,
},
},
{
x2 = 30,
y2 = 15,
border = {
color = 0,
type = 1,
},
x1 = 30,
txt = "×",
type = "text",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
},
txtcolor = 256,
input = false,
color = 0,
y1 = 15,
},
},
w = 32,
h = 19,
},
}
for s=1,#slides do
local slide = slides[s]
for o=1,#slide.objs do
local obj = slide.objs[o]
for key,value in pairs(obj.event) do
if assets[ value[2] ] then
lUtils.shapescape.addScript(obj,value[2],key,assets,LevelOS,slides)
else
obj.event[key] = {function() end,-1}
end
end
end
end
local tArgs = {...}
if tArgs[1] and tArgs[1] == "load" then
return {assets=assets,slides=slides}
end
lUtils.shapescape.run(slides,...)

327
LevelOS/Start_Menu.sgui Normal file
View File

@@ -0,0 +1,327 @@
local assets = {
[ "programs.lua" ] = {
id = 0,
content = "local scrollY = 0\
local programs = {}\
local found = fs.list(\"Program_Files\")\
local icons = lUtils.asset.load(\"LevelOS/assets/Compact_Icons.limg\")\
local A = string.byte(\"A\")\
local Z = string.byte(\"Z\")\
for f=1,#found do\
local l = string.byte(found[f]:sub(1,1):upper())\
local dest\
if l >= A and l <= Z then\
if not programs[l] then programs[l] = {} end\
dest = programs[l]\
else\
if not programs[A-1] then programs[A-1] = {} end\
dest = programs[A-1]\
end\
local program = {path=fs.combine(\"Program_Files\",found[f]),name=found[f]:sub(1,1):upper()..lUtils.getFileName(found[f]:sub(2))}\
--program.icon = whatever\
table.insert(dest,program)\
end\
local function render()\
local y = 2\
term.setBackgroundColor(colors.gray)\
term.setTextColor(colors.white)\
term.clear()\
for l=A-1,Z do\
if programs[l] then\
local letter\
if l == A-1 then\
letter = \"#\"\
else\
letter = string.char(l)\
end\
term.setCursorPos(1,y)\
term.write(letter)\
y = y+2\
for t=1,#programs[l] do\
lUtils.renderImg(icons[8],1,y)\
term.setCursorPos(5,y)\
term.setTextColor(colors.white)\
term.write(programs[l][t].name)\
y = y+1\
term.setTextColor(colors.lightGray)\
term.write( -- creator\
end\
end\
end",
name = "programs.lua",
},
}
local nAssets = {}
for key,value in pairs(assets) do nAssets[key] = value nAssets[assets[key].id] = assets[key] end
assets = nAssets
nAssets = nil
local slides = {
{
y = 21,
x = 61,
w = 51,
h = 19,
objs = {
{
color = 128,
y2 = 19,
border = {
color = 0,
type = 1,
},
x1 = 1,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
x2 = 5,
y1 = 1,
snap = {
Top = "Snap top",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap bottom",
},
oy2 = 0,
},
{
color = 128,
y2 = 18,
border = {
color = 0,
type = 1,
},
x1 = 2,
image = {
{
"”•”",
"000",
"TTT",
},
{
"Œ…",
"000",
"TTT",
},
},
oy1 = 2,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
oy2 = 1,
x2 = 4,
y1 = 17,
snap = {
Top = "Snap bottom",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap bottom",
},
},
{
color = 128,
y2 = 15,
border = {
color = 0,
type = 1,
},
x1 = 2,
image = {
{
"‡’",
"TT0",
"00T",
},
{
"‚‡€",
"00T",
"TTT",
},
},
oy1 = 5,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
oy2 = 4,
x2 = 4,
y1 = 14,
snap = {
Top = "Snap bottom",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap bottom",
},
},
{
color = 128,
y2 = 12,
border = {
color = 0,
type = 1,
},
x1 = 2,
image = {
{
"‘€„",
"TT0",
"00T",
},
{
"ˆ€",
"00T",
"TTT",
},
},
oy1 = 8,
type = "rect",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
oy2 = 7,
x2 = 4,
y1 = 11,
snap = {
Top = "Snap bottom",
Right = "Snap left",
Left = "Snap left",
Bottom = "Snap bottom",
},
},
{
color = 128,
y2 = 19,
y1 = 1,
x1 = 6,
type = "window",
event = {
mouse_up = {
[ 2 ] = -1,
},
mouse_click = {
[ 2 ] = -1,
},
focus = {
[ 2 ] = -1,
},
render = {
[ 2 ] = -1,
},
update = {
[ 2 ] = -1,
},
Coroutine = {
[ 2 ] = -1,
},
},
ox2 = 0,
x2 = 51,
border = {
color = 0,
type = 1,
},
snap = {
Top = "Snap top",
Right = "Snap right",
Left = "Snap left",
Bottom = "Snap bottom",
},
oy2 = 0,
},
},
c = 1,
},
}
for s=1,#slides do
local slide = slides[s]
for o=1,#slide.objs do
local obj = slide.objs[o]
for key,value in pairs(obj.event) do
if assets[ value[2] ] then
lUtils.shapescape.addScript(obj,value[2],key,assets,LevelOS,slides)
else
obj.event[key] = {function() end,-1}
end
end
end
end
local tArgs = {...}
if tArgs[1] and tArgs[1] == "load" then
return {assets=assets,slides=slides}
end
lUtils.shapescape.run(slides,...)

1970
LevelOS/SystemUI.lua Normal file

File diff suppressed because it is too large Load Diff

451
LevelOS/Task_Manager.lua Normal file
View File

@@ -0,0 +1,451 @@
local scroll = 0
local procs = lOS.processes
local sel = {}
local pSel = {}
local expanded = {}
local cEnd = false
local scrollable = false
local display = 1
local function percentage(part,full)
if display == 1 then
local f = math.min(math.ceil((part/full)*1000)/10,100)
return f.."%"
else
return math.floor(part+0.5).." ms"
end
end
function _G.invWrite(txt)
local fg = lUtils.toBlit(term.getTextColor()):rep(#txt)
local bg = lUtils.toBlit(term.getBackgroundColor()):rep(#txt)
term.blit(txt,bg,fg)
end
local function drawProcs(x1,y1,x2,y2,e)
if e[1] == "mouse_scroll" then
if scroll+e[2] >= 0 and (e[2] <= -1 or scrollable) then
scroll = scroll+e[2]
end
end
term.setBackgroundColor(colors.yellow)
term.setTextColor(colors.lightGray)
--lOS.boxClear(x2-9,y1,x2,y2-2)
for y=y1,y2-2 do
term.setBackgroundColor(colors.white)
term.setCursorPos(x2-10,y)
invWrite("\149")
term.setBackgroundColor(colors.yellow)
term.write(string.rep(" ",10))
term.setBackgroundColor(colors.white)
term.write("\149")
end
scrollable = false
cY = y1-scroll
local pr = {}
local bg = {}
y2 = y2-2
for p=1,#procs do
if procs[p].path then
if procs[p].win and procs[p].winMode ~= "background" then
if not pr[procs[p].path] then
if expanded[procs[p].path] == nil then
expanded[procs[p].path] = false
end
pr[#pr+1] = {expanded=expanded[procs[p].path],path=procs[p].path,pr={procs[p]},yieldTime=procs[p].yieldTime}
pr[procs[p].path] = pr[#pr]
else
for t=1,#pr do
if pr[t].path == procs[p].path then
pr[t].pr[#pr[t].pr+1] = procs[p]
if procs[p].yieldTime then
pr[t].yieldTime = pr[t].yieldTime+procs[p].yieldTime
end
end
end
end
else
bg[#bg+1] = procs[p]
end
end
end
local clickmenu = {}
-- TEMP
if type(pSel) == "table" then
sel = pSel
elseif type(pSel) == "number" then
sel = pr[pSel]
else
sel = {}
end
--if pr[2] then
--pr[2].expanded = true
--end
if cY+1 >= y1 and cY+1 <= y2 then
term.setTextColor(colors.blue)
term.setBackgroundColor(colors.white)
term.setCursorPos(x1,cY+1)
term.write("Programs ("..#pr..")")
end
cY = cY+2
local previousColor1
local previousColor2
for p=1,#pr+1 do
local fg1
local bg1
local fg2
local bg2
local WARN = colors.yellow
if p <= #pr and pr[p].yieldTime then
local f = pr[p].yieldTime/lOS.yieldTime
if f > 0.7 then
WARN = colors.red
elseif f > 0.4 then
WARN = colors.orange
end
end
fg1 = previousColor1 or colors.white
fg2 = previousColor2 or colors.yellow
if p > #pr or sel ~= pr[p] then
bg1 = colors.white
bg2 = WARN
else
bg1 = colors.lightBlue
bg2 = colors.cyan
end
previousColor1 = bg1
previousColor2 = bg2
if cY >= y1 and cY <= y2 then
term.setTextColor(fg1)
term.setBackgroundColor(bg1)
term.setCursorPos(x1,cY)
term.write(string.rep("\131",x2-(x1-1)-11))
term.setTextColor(colors.lightGray)
term.setBackgroundColor(colors.white)
invWrite("\149")
term.setBackgroundColor(bg1)
term.setTextColor(fg2)
term.setBackgroundColor(bg2)
term.write(string.rep("\131",10))
end
term.setTextColor(fg1)
term.setBackgroundColor(bg1)
if p > #pr then
break
end
cY = cY+1
if cY >= y1 and cY <= y2 then
--term.setTextColor(colors.black)
clickmenu[cY] = p
term.setCursorPos(x1,cY)
term.write(string.rep(" ",x2-(x1-1)-11))
term.setTextColor(colors.lightGray)
term.setBackgroundColor(colors.white)
invWrite("\149")
term.setBackgroundColor(bg2)
term.write(string.rep(" ",10))
term.setCursorPos(x1+1,cY)
term.setBackgroundColor(bg1)
if not pr[p].expanded then
term.setTextColor(colors.lightGray)
term.write("\16 ")
else
term.setTextColor(colors.gray)
term.write("\31 ")
end
term.setTextColor(colors.black)
local path = pr[p].path
if fs.getName(path) == "main.lua" then
path = fs.getDir(path)
end
local t = lUtils.getFileName(path)
t = t:sub(1,1):upper()..t:sub(2)
term.write(t.." ("..#pr[p].pr..")")
local txt
if pr[p].yieldTime then
txt = percentage(pr[p].yieldTime,lOS.yieldTime)
else
txt = "???"
end
term.setCursorPos(x2-#txt,cY)
term.setBackgroundColor(bg2)
term.write(txt)
end
cY = cY+1
if pr[p].expanded then
for t=1,#pr[p].pr do
if cY >= y1 and cY <= y2 then
clickmenu[cY] = pr[p].pr[t]
local bg3
local bg4
if sel == pr[p].pr[t] or sel == pr[p] then
bg3 = colors.lightBlue
bg4 = colors.cyan
else
bg3 = colors.white
bg4 = WARN
end
term.setBackgroundColor(bg3)
if not (sel == pr[p]) then
term.setCursorPos(x1+3,cY)
term.write(string.rep(" ",(x2)-(x1+2)-11))
else
term.setCursorPos(x1,cY)
term.write(string.rep(" ",x2-(x1-1)-11))
end
term.setTextColor(colors.lightGray)
term.setBackgroundColor(colors.white)
invWrite("\149")
term.setBackgroundColor(bg4)
term.write(string.rep(" ",10))
term.setBackgroundColor(bg3)
term.setTextColor(colors.black)
term.setCursorPos(x1+4,cY)
term.write(pr[p].pr[t].title)
local txt
if pr[p].pr[t].yieldTime then
txt = percentage(pr[p].pr[t].yieldTime,lOS.yieldTime)
else
txt = "???"
end
term.setCursorPos(x2-#txt,cY)
term.setBackgroundColor(bg4)
term.write(txt)
end
cY = cY+1
end
end
end
-- draw bg processes (no extended)
if cY+1 >= y1 and cY+1 <= y2 then
term.setTextColor(colors.blue)
term.setBackgroundColor(colors.white)
term.setCursorPos(x1,cY+1)
term.write("Background Processes ("..#bg..")")
end
cY = cY+2
local previousColor1
local previousColor2
for p=1,#bg+1 do
local fg1
local bg1
local fg2
local bg2
local WARN = colors.yellow
if p <= #bg and bg[p].yieldTime then
local f = bg[p].yieldTime/lOS.yieldTime
if f > 0.7 then
WARN = colors.red
elseif f > 0.4 then
WARN = colors.orange
end
end
fg1 = previousColor1 or colors.white
fg2 = previousColor2 or colors.yellow
if p > #bg or sel ~= bg[p] then
bg1 = colors.white
bg2 = WARN
else
bg1 = colors.lightBlue
bg2 = colors.cyan
end
previousColor1 = bg1
previousColor2 = bg2
if cY >= y1 and cY <= y2 then
term.setTextColor(fg1)
term.setBackgroundColor(bg1)
term.setCursorPos(x1,cY)
term.write(string.rep("\131",x2-(x1-1)-11))
term.setTextColor(colors.lightGray)
term.setBackgroundColor(colors.white)
invWrite("\149")
term.setBackgroundColor(bg1)
term.setTextColor(fg2)
term.setBackgroundColor(bg2)
term.write(string.rep("\131",10))
end
term.setTextColor(fg1)
term.setBackgroundColor(bg1)
if p > #bg then
break
end
cY = cY+1
if cY >= y1 and cY <= y2 then
--term.setTextColor(colors.black)
clickmenu[cY] = bg[p]
term.setCursorPos(x1,cY)
term.write(string.rep(" ",x2-(x1-1)-11))
term.setTextColor(colors.lightGray)
term.setBackgroundColor(colors.white)
invWrite("\149")
term.setBackgroundColor(bg2)
term.write(string.rep(" ",10))
term.setCursorPos(x1+1,cY)
term.setBackgroundColor(bg1)
if sel ~= bg[p] then
term.setBackgroundColor(colors.white)
else
term.setBackgroundColor(colors.lightBlue)
end
term.write(" ")
term.setTextColor(colors.black)
local t = ""
if bg[p].title then
t = bg[p].title
else
t = bg[p].path
end
term.write(t)
local txt
if bg[p].yieldTime then
txt = percentage(bg[p].yieldTime,lOS.yieldTime)
else
txt = "???"
end
term.setCursorPos(x2-#txt,cY)
term.setBackgroundColor(bg2)
term.write(txt)
end
cY = cY+1
end
if cY > y2 then
scrollable = true
end
term.setCursorPos(1,y2+1)
term.setBackgroundColor(colors.white)
term.setTextColor(colors.gray)
local w,h = term.getSize()
term.write(string.rep("\131",w))
--term.setCursorPos(x1,y2+2)
local txt = "End Task"
term.setCursorPos(x2-(string.len(txt)),y2+2)
if sel.path then
if not cEnd then
term.setTextColor(colors.blue)
else
term.setTextColor(colors.lightBlue)
end
else
term.setTextColor(colors.lightGray)
end
term.write(txt)
if e[1] == "mouse_click" then
if e[3] >= x1 and e[3] <= x2 and e[4] >= y1 and e[4] <= y2 then
sel = {}
pSel = {}
end
if sel.path and e[4] == y2+2 and e[3] >= x2-string.len(txt) and e[3] <= x2-1 then
term.setCursorPos(x2-(string.len(txt)),y2+2)
term.setTextColor(colors.lightBlue)
term.write(txt)
cEnd = true
end
if clickmenu[e[4]] then
pSel = clickmenu[e[4]]
if type(pSel) == "number" and e[3] == x1+1 then
if expanded[pr[pSel].path] == false then
expanded[pr[pSel].path] = true
else
expanded[pr[pSel].path] = false
end
end
end
elseif e[1] == "mouse_up" then
cEnd = false
if sel.path and e[4] == y2+2 and e[3] >= x2-string.len(txt) and e[3] <= x2-1 then
local t = 1
while true do
if lOS.processes[t] == nil then break end
if type(sel[1]) == "thread" then
if lOS.processes[t] == sel then
for i=1,#lOS.wins do
if lOS.wins[i] == lOS.processes[t] then
table.remove(lOS.wins,i)
end
end
table.remove(lOS.processes,t)
break
else
t = t+1
end
else
if lOS.processes[t].path == sel.path then
for i=1,#lOS.wins do
if lOS.wins[i] == lOS.processes[t] then
table.remove(lOS.wins,i)
end
end
table.remove(lOS.processes,t)
else
t = t+1
end
end
end
sel = {}
pSel = {}
end
end
end
-- sel wont work since pr gets regenerated every time
-- it will work for subprocesses tho
local w,h = term.getSize()
term.setBackgroundColor(colors.white)
term.clear()
while true do
e = {os.pullEvent()}
term.setBackgroundColor(colors.white)
term.clear()
local w,h = term.getSize()
term.setCursorPos(2,3)
term.setTextColor(colors.blue)
term.write("Name")
term.setCursorPos(w-6,3)
term.write("Yield")
term.setTextColor(colors.black)
local txt
if lOS.yieldTime then
txt = math.ceil(lOS.yieldTime).." ms"
else
txt = "???"
end
term.setCursorPos((w-1)-#txt,2)
term.write(txt)
term.setCursorPos(1,4)
term.setTextColor(colors.lightGray)
term.setBackgroundColor(colors.white)
term.write(string.rep("\131",w))
for y=1,3 do
term.setCursorPos(w-11,y)
invWrite("\149")
term.setCursorPos(w,y)
term.write("\149")
end
term.setCursorPos(w-11,4)
invWrite("\148")
term.setBackgroundColor(colors.yellow)
term.write(string.rep("\131",10))
term.setBackgroundColor(colors.white)
term.setCursorPos(w,4)
term.write("\151")
drawProcs(2,5,w-1,h,e)
if e[1] == "key_up" and e[2] == keys.t and lUtils.isHolding(keys.leftShift) then
term.setBackgroundColor(colors.black)
term.clear()
term.setCursorPos(1,1)
term.setTextColor(colors.red)
print("Terminated")
return
elseif e[1] == "mouse_click" and e[2] == 2 and lUtils.isInside(e[3],e[4],{x1=w-10,y1=1,x2=w-1,y2=4}) then
if display == 1 then
lOS.contextmenu(e[3],e[4],0,{{txt="Switch to ms",action=function() display = 2 end}})
else
lOS.contextmenu(e[3],e[4],0,{{txt="Switch to %",action=function() display = 1 end}})
end
end
end

View File

@@ -0,0 +1,37 @@
{
{
{
"‡€”‚",
"TT0Tb",
"bbbbT",
},
{
"€‰•",
"T000b",
"bbbbT",
},
{
"‹ˆŒŸ",
"b00bb",
"TbbTT",
},
},
{
{
"‡€€‚",
"TTTTb",
"bbbbT",
},
{
"€˜•",
"T000b",
"bbbbT",
},
{
"‹‚€Ÿ",
"b0Tbb",
"TbbTT",
},
},
type = "lImg",
}

View File

@@ -0,0 +1,110 @@
{
{
{
"—‹",
"TT0",
"00T",
},
{
"Š…",
"000",
"TTT",
},
},
{
{
"‡‹",
"TT0",
"00T",
},
{
"ƒ‡",
"000",
"TTT",
},
},
{
{
"‡ƒ‹",
"TTT",
"000",
},
{
"›‡",
"000",
"TTT",
},
},
{
{
"‡‹ƒ",
"TTT",
"000",
},
{
"‹‡€",
"00T",
"TTT",
},
},
{
{
"ˆ€",
"00T",
"TTT",
},
{
"‚ˆ„",
"000",
"TTT",
},
},
{
{
"Ÿœ’",
"T00",
"0TT",
},
{
"‚",
"000",
"TTT",
},
},
{
{
"•ƒ•",
"TT0",
"00T",
},
{
"Š…",
"000",
"TTT",
},
},
{
{
"œ“ƒ",
"0TT",
"T00",
},
{
"Ž",
"000",
"TTT",
},
},
{
{
"€‘‹",
"TTT",
"T00",
},
{
"˜",
"000",
"TTT",
},
},
}

View File

@@ -0,0 +1 @@
{{{"€•‹"," 9 ","9bb",},{"€€€"," ","999",},{"€€€"," ","999",},},{{"€•‹"," 9 ","9bb",},{"€€€"," ","999",},{"lua","000","bbb",},},{{""," ","777",},{"••€","8b ","b88",},{"ƒƒƒ","888"," ",},},{{"€•‹"," 8 ","877",},{"€€€"," ","888",},{"€€€"," ","888",},},{{"€•‹"," 8 ","877",},{"€€€"," ","888",},{"txt","000","777",},},{{"€•‹"," 8 ","877",},{"€€€"," ","888",},{"cfg","000","777",},},{{"€€•"," 4","44 ",},{"€€‚"," ","444",},{"€€€"," ","444",},},{{"€•‹"," e ","e11",},{"€€€"," ","eee",},{"gui","000","111",},},{{"€•‹"," 5 ","5dd",},{"€€€"," ","555",},{"sml","000","ddd",},},{{""," ","ccc",},{"•‹•","c43","3dc",},{"ƒƒƒ","ccc"," ",},},{{"","afa","faf",},{"ƒƒƒ","faf","afa",},{"","faf"," ",},},{{"˜ƒ›","bb "," b",},{"‰†","b b"," b ",},{"˜Œ›","bb "," b",},},{{""," ","888",},{"•€•","8 b","bb8",},{"Œ€Œ"," ","888",},},{{"Ÿ•‹","00 ","988",},{"ˆŒ„","999","000",},{"ŠŠ…","999","000",},},{{"€ƒ€"," "," b ",},{"€"," ","bbb",},{"‚","bbb"," ",},},{{"Ÿ‹€"," ","88 ",},{"Ÿ…","888"," ",},{"‚ƒ€","88 "," ",},},{{""," ","000",},{"•‡•","03d","3d0",},{"ƒƒƒ","000"," ",},},{{"€•”"," b"," b ",},{"€•Š"," b"," b ",},{"‘Ÿ€"," b ","b ",},},{{"Ÿ€"," 9","9 ",},{"•€•","9 "," 9",},{"‚€","9 9"," ",},},{{"Ÿ•","4b4","b4 ",},{"ƒ","bb9","494",},{"€€€"," ","444",},},{{"€€€"," "," ",},{"Š…","888","eee",},{"•Œ•","e78","88e",},},}

View File

@@ -0,0 +1 @@
{{{"€€Ÿ€€•"," 000b b00 b 000b0","0bbb000bb000bbb0b",},{"€•ƒ”•Šƒ”‰†•ƒ”••"," b0bb00b0bbbb0bb0","00b00bb0b0000b00b",},{"€ŠŒŽŠ……ˆƒŒŽŠŒŽ••"," 00000000000000b0","0bbbbbbbbbbbbbb0b",},{"€›•‚–œˆ‚ˆ›˜ƒ€•"," 0bbbb0bbbbb0b0 0","0b0000b00000b0b0b",},{"€†–˜€Œ•Ÿ€€–ŒˆŒ€•"," b00 bb0 0b0b b0","00bbb00900b0b000b",},{"€“•‰••€™‹™–‘•"," 0b0bbb00 0bbbbb0","0b0b000990b00000b",},{"€ƒž™ŠŽŠ„€ž‰”•"," 0b00000b00 b0bb0","0b0bbbbb0bb00b00b",},{"€…ŠŽŸˆ™›ƒ‚†Œ‹Œ„•"," bbbb0b0b0bbb0bb0","00000b0b0b000b00b",},{"€—Œ“•‚Ž…œŽ”ŠŽˆ‰€•"," b0bbb00000000b 0","00b000bbbbbbbb00b",},{"€•…•Š–†‹Š–ŒŸ•"," bbbbb000bb0b0bb0","000000bbb00b0b00b",},{"€ƒƒƒ€€€ƒ‚ƒ€•"," bbbbb b bbbbb 0","0000000000000000b",},},{{"€€ŸŸ€€"," 000bb 00b b000b ","0bbb000bb000bbb00",},{"€•ƒ”•‚’•Šƒš…•ƒ”•€"," b0bb0bb0bbbb0bb ","00b00b00b0000b000",},{"€ŠŒŽ•ž•“‘œ”ŠŒŽ•€"," 000bbbbbbbb000b ","0bbb00000000bbb00",},{"€œƒ„‡›ƒ•Ÿ‡˜œ„€"," b00bbb0bb000bbb ","00bb000b00bbb0000",},{"€†›œ“Žž‘–Ž—Ž”ށ€"," bbbbb00b000000b ","000000bb0bbbbbb00",},{"€‚ž–Ž‘‚‡”Ž‹‘‡’€€"," bb0b00bb00bbb0 ","000b0bb00bb000b00",},{"€„Œœ›”–‡†š˜›‰€„€"," bbbbbb00bbbb0 b ","0000000bb0000bb00",},{"€Œ‰…ŒšŒŠŸ–‘ŸŒ‹’€€"," bbbbbb00b0bb0b ","0000000bb0b00b000",},{"€—Œ“•ƒŸ—•Œ’ŠŽˆ‘€"," b0bb0b0bb0000bb ","00b00b0b00bbbb000",},{"€•…•š—Ÿ…›’‚Œ‰Ÿ„€"," bbbbb0bb00b00bb ","000000b00bb0bb000",},{"€ƒƒƒ€€ƒƒ‚€€"," bbbbb bbbbbbb ","00000000000000000",},},}

View File

@@ -0,0 +1,172 @@
{
{
{
"ŸŒ›€",
"T8TT",
"8T8T",
},
{
"•€€•",
"8TT8",
"TTTT",
},
{
"‚Œ†€",
"888T",
"TTTT",
},
},
{
{
"ŸŒ›€",
"T0TT",
"8T8T",
},
{
"•€€•",
"8TT8",
"TTTT",
},
{
"‚Œ†€",
"888T",
"TTTT",
},
},
{
{
"ŸŒ›€",
"T0TT",
"8T0T",
},
{
"•€€•",
"8TT8",
"TTTT",
},
{
"‚Œ†€",
"888T",
"TTTT",
},
},
{
{
"ŸŒ›€",
"T0TT",
"8T0T",
},
{
"•€€•",
"8TT0",
"TTTT",
},
{
"‚Œ†€",
"888T",
"TTTT",
},
},
{
{
"ŸŒ›€",
"T0TT",
"8T0T",
},
{
"•€€•",
"8TT0",
"TTTT",
},
{
"‚Œ†€",
"880T",
"TTTT",
},
},
{
{
"ŸŒ›€",
"T0TT",
"8T0T",
},
{
"•€€•",
"8TT0",
"TTTT",
},
{
"‚Œ†€",
"800T",
"TTTT",
},
},
{
{
"ŸŒ›€",
"T0TT",
"8T0T",
},
{
"•€€•",
"8TT0",
"TTTT",
},
{
"‚Œ†€",
"000T",
"TTTT",
},
},
{
{
"ŸŒ›€",
"T0TT",
"8T0T",
},
{
"•€€•",
"0TT0",
"TTTT",
},
{
"‚Œ†€",
"000T",
"TTTT",
},
},
{
{
"ŸŒ›€",
"T0TT",
"0T0T",
},
{
"•€€•",
"0TT0",
"TTTT",
},
{
"‚Œ†€",
"000T",
"TTTT",
},
},
{
{
"Ÿƒ‹€",
"TTTT",
"bbbT",
},
{
"€›†•",
"Tb0b",
"b0bT",
},
{
"‚‡€",
"bbbT",
"TTTT",
},
},
}

View File

@@ -1,241 +1,241 @@
{
{
{
"-ƒ-Η-Η-Η",
"Ÿ€€€",
"TTTT",
"0TTT",
},
{
"-ς-Η-Η-Η",
"•€€€",
"0TTT",
"TTTT",
},
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
},
{
{
"-Η-δ-Η-Η",
"€„€€",
"T0TT",
"TTTT",
},
{
"-ς-Η-Η-Η",
"•€€€",
"0TTT",
"TTTT",
},
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
},
{
{
"-ƒ-κ-Η-Η",
"Ÿˆ€€",
"T0TT",
"0TTT",
},
{
"-φ-Η-Η-Η",
"”€€€",
"0TTT",
"TTTT",
},
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
},
{
{
"-Η-δ-δ-Η",
"€„„€",
"T00T",
"TTTT",
},
{
"-ΰ-Η-Η-Η",
"…€€€",
"0TTT",
"TTTT",
},
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
},
{
{
"-ƒ-κ-ƒ-Η",
"ŸˆŸ€",
"T0TT",
"0T0T",
},
{
"-ό-Η-Η-Η",
"€€€",
"0TTT",
"TTTT",
},
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
},
{
{
"-ƒ-κ-ƒ-Η",
"ŸˆŸ€",
"T0TT",
"0T0T",
},
{
"-Η-Η-Η",
"€€€„",
"TTT0",
"TTTT",
},
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
},
{
{
"-Η-δ-δ-Η",
"€„„€",
"T00T",
"TTTT",
},
{
"-Η-Η-Η",
"€€€",
"TTT0",
"TTTT",
},
{
"-Η-Η-ι-Η",
"€€‚€",
"TT0T",
"TTTT",
},
},
{
{
"-Η-κ-ƒ-Η",
"€ˆŸ€",
"T0TT",
"TT0T",
},
{
"-Η-Η-Η-Ι",
"€€€",
"TTT0",
"TTTT",
},
{
"-Η-Η-δ-Η",
"€€„€",
"TT0T",
"TTTT",
},
},
{
{
"-Η-Η-ƒ-Η",
"€€Ÿ€",
"TTTT",
"TT0T",
},
{
"-Η-Η-Η-Ι",
"€€€",
"TTT0",
"TTTT",
},
{
"-ι-Η-δ-Η",
"‚€„€",
"0T0T",
"TTTT",
},
},
{
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
{
"-Ι-Η-Η",
"€€„",
"0TT0",
"TTTT",
},
{
"-Η-δ-δ-Η",
"€„„€",
"T00T",
"TTTT",
},
},
{
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
{
"-δ-Η-Η-Η",
"„€€€",
"0TTT",
"TTTT",
},
{
"-ι-κ-ι-Η",
"‚ˆ‚€",
"000T",
"TTTT",
},
},
{
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
{
"-ΰ-Η-Η-Η",
"…€€€",
"0TTT",
"TTTT",
},
{
"-ι-κ-Η-Η",
"‚ˆ€€",
"00TT",
"TTTT",
},
},
{
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
{
"-ς-Η-Η-Η",
"•€€€",
"0TTT",
"TTTT",
},
{
"-Η-δ-Η-Η",
"€„€€",
"T0TT",
"TTTT",
},
},
{
{
"-Η-Η-Η-Η",
"€€€€",
"TTTT",
"TTTT",
},
{
"-ς-Η-Η-Η",
"•€€€",
"0TTT",
"TTTT",
},
{
"-ι-Η-Η-Η",
"‚€€€",
"0TTT",
"TTTT",
},
},
type = "lImg",
}
}

View File

@@ -0,0 +1,40 @@
{
{
{
"€•€€€€€€",
"TeTTTTTT",
"eTTTTTTT",
},
{
"€•€€€€€€",
"TeTTTTTT",
"eTTTTTTT",
},
{
"€•€€€€€€",
"TdTTTTTT",
"dTTTTTTT",
},
{
"€•€€€€€€",
"TdTTTTTT",
"dTTTTTTT",
},
{
"€•€€€€€€",
"TeTTTTTT",
"eTTTTTTT",
},
{
"€•€€€€€€",
"TeTTTTTT",
"eTTTTTTT",
},
{
"€€•€€€€•",
"TTdTTTTd",
"ddeeeddT",
},
},
type = "lImg",
}

View File

@@ -0,0 +1,40 @@
{
{
{
"€•€€€€€€",
"TeTTTTTT",
"eTTTTTTT",
},
{
"€•€€€€€€",
"TeTTTTTT",
"eTTTTTTT",
},
{
"€•€€€€€€",
"T1TTTTTT",
"1TTTTTTT",
},
{
"€•€€€€€€",
"T1TTTTTT",
"1TTTTTTT",
},
{
"€•€€€€€€",
"T4TTTTTT",
"4TTTTTTT",
},
{
"€•€€€€€€",
"T4TTTTTT",
"4TTTTTTT",
},
{
"€€•€€€€•",
"TTdTTTTa",
"ddbbbaaT",
},
},
type = "lImg",
}

71
LevelOS/assets/wifi.limg Normal file
View File

@@ -0,0 +1,71 @@
{
{
{
"Œ›€",
"0TT",
"T0T",
},
{
"“”•",
"000",
"TTT",
},
{
"€€€",
"TTT",
"TTT",
},
},
{
{
"Œ›€",
"8TT",
"T8T",
},
{
"“”•",
"008",
"TTT",
},
{
"€€€",
"TTT",
"TTT",
},
},
{
{
"Œ›€",
"8TT",
"T8T",
},
{
"“”•",
"888",
"TTT",
},
{
"€€€",
"TTT",
"TTT",
},
},
{
{
"Œ›€",
"eTT",
"TeT",
},
{
"“”•",
"eee",
"TTT",
},
{
"€€€",
"TTT",
"TTT",
},
},
type = "lImg",
}

View File

@@ -0,0 +1,324 @@
{
{
date = "01-06-2021",
version = "2.2.5",
description = "It's pride month! To show support, the LevelOS logo has been replaced by a rainbow variant throughout June.",
added = {
"Added changelog",
},
fixed = {
"lOS.execute now properly takes a window mode argument",
"Loading assets through lUtils no longer errors on invalid file path",
"lUtils.renderImg now handles transparency slightly better",
},
},
{
date = "01-06-2021",
version = "2.2.6",
fixed = {
"Modified changelog design and resizing",
"Fixed startup erroring after update",
},
},
{
date = "02-06-2021",
version = "2.2.7",
added = {
"Integrated global login into the LevelOS system",
},
},
{
date = "02-06-2021",
version = "2.2.8",
fixed = {
"Global login now only appears when LevelCloud is enabled, as was intended",
"Shapescape programs no longer crash on versions with mouse_move events",
},
},
{
date = "03-06-2021",
version = "2.2.9",
description = "The LevelOS search feature is currently disabled until input boxes are added.",
added = {
"LevelOS start menu is now an overlay and can be opened by both mouse buttons",
"Shapescape programs now clear their window when exited",
},
fixed = {
"Fixed LevelOS infinite-looping when booted without internet",
},
},
{
date = "03-06-2021",
version = "2.2.10",
description = "Mouse simulator will be added to LevelOS in the future",
added = {
"LevelOS can now run on classic computers when an external mouse simulator is used",
},
fixed = {
"Fixed the login screen getting stuck on boot until it received an event",
"Fixed the LevelCloud GUI showing an error when booted without internet",
},
},
{
date = "16-06-2021",
version = "2.2.11",
description = "This took too long but I finally fixed a bunch of issues in the OS. Input boxes coming soon.",
fixed = {
"Shutdown fade restored (broke in 2.2.9)",
"Fixed startup processes not being able to execute programs before their first yield",
"Fixed term_resize events being sent to every process instead of only the resizing one",
"Only the focused window has constant thread resuming now to improve performance",
"LevelOS now properly reports errors in System and SystemUI processes",
},
},
{
date = "19-06-2021",
version = "2.2.12",
description = "Some temporary fixes until the desktop and system are rewritten",
added = {
"New desktop icons for .lua files, files without extension, files with unknown extensions and LevelOS executables",
},
fixed = {
"LevelOS can now resize itself",
"Desktop no longer has weird dragging limits",
"Icon creation from the explorer and using lOS.genIco now works properly",
"Pigeon icon has been restored",
},
},
{
date = "22-11-2021",
version = "2.3.0",
description = "It's been a while, but LevelOS is back. And it's better than ever! Sorry for the long wait! The window manager has been rewritten entirely, and all sorts of cool functionality has been added. Desktop icons have been renewed but don't refresh automatically, so if you want those you have to delete desktop.lconf in LevelOS/data and hold ctrl + r.",
added = {
"The window manager now has animations on resizing, closing, opening and minimizing of windows",
"A tab menu (like Window's alt tab) has been added. Instead of alt, ctrl is used in LevelOS",
"Shell and Lua have new icons",
"Windows can now be in fullscreen mode by pressing f5",
"There's a new login screen and register screen, remember me can be toggled by logging out through the LevelCloud interface and pressing remember me in the prompt that comes up",
"Taskbar icons are now actual icons. Custom icons coming soon",
"When multiple windows of a certain program are open, they appear in the same taskbar icon",
"Taskbar icons can now be right clicked",
"Right click menu's are now overlays meaning they can go beyond their window's border",
"Bootup now displays what it's currently doing",
"The pride LevelOS icon is back due to popular demand",
},
fixed = {
"Desktop auto generation now works properly, may require deleting desktop.lconf in LevelOS/data and holding ctrl + r to work",
"The LevelOS start menu (opened by clicking the L in the bottom left corner) now appears on top of other windows",
},
major = true,
},
{
date = "26-12-2021",
version = "2.3.1",
description = "Merry Christmas! More changes are on the way for premium users.",
added = {
"Premium users now have an auto updater for dev builds",
"LevelOS now has an integrity check at startup",
"Replaced asterisks in login screen with circles",
},
fixed = {
"Minimizing widgets no longer causes a bluescreen",
"Clicks on the taskbar now also close widgets",
"Desktop shortcuts to program folders now execute properly",
"Start screen now properly resizes",
},
},
{
date = "22-05-2022",
version = "2.3.2",
description = "I seem to make a habit out of incredibly long delays between updates. Sorry about that. This update contains some very necessary bugfixes and some API rewrites, in wait of a bigger update with rewritten GUIs for several components in LevelOS. Stay tuned!",
added = {
"Redesigned and improved notifications",
"The clock now has a calendar as well",
"The window manager now uses a window_focus event",
"Shapescape now displays proper error messages when a script errors",
},
fixed = {
"Improved lUtils.renderImg transparency handling",
"Cursor no longer displays outside of window",
"The certificate error in the login screen has been fixed",
"Cursor no longer keeps blinking when a popup opens",
},
},
{
date = "22-05-2022",
version = "2.3.3",
description = "Wow! Two updates in one day!",
fixed = {
"Fixed another occurence of the certificate error in lUtils.login that I missed earlier",
},
},
{
major = true,
date = "04-08-2022",
version = "2.4.0",
description = "Version 2.4 is here! This version is all about the rewrites. LevelOS has gotten a completely new and rewritten desktop, which is now bound to the actual folder User/Desktop. There is also a completely new explorer, which together with the desktop supports a new shortcut system. Alongside with these big new changes, there have also been several fixes and other new features, and more will follow.",
added = {
"Rewrote the desktop, now has custom background support (right click any .nfp, .bimg or .limg image using explorer)",
"There is now a new shortcut system (right click any file or folder using explorer and click create shortcut)",
"Rewrote the explorer, now comes with a file tree, search function, icon view (icon in the bottom right) and more",
"Created the advanced lOS.contextmenu function, documentation will come soon",
"Made better taskbar icons",
"Changed the LevelOS file structure, LevelOS programs are now in Program_Files/LevelOS",
"Replaced openWith.lconf with formats.lconf, which has a better stucture",
"There is now a 'Yield' column in Task Manager",
"Added 'abort()' function to the LevelOS.close() callback function, to abort closing the program",
"Shutting down/rebooting now shows an interface to be able to save your work if apps have LevelOS.close() set",
"Added an early version of the Store",
"Replaced the lua repl with a custom version",
"Added 1 character icon support to the window manager",
"Added bimg support across LevelOS",
"Added a new program folder structure which is HIGHLY recommended you use for LevelOS programs as it allows setting custom icons: main.lua for file that gets executed when the program is ran, taskbar.bimg for the icon appearing on the taskbar (must be mostly white!) and icon.bimg for the icon appearing on desktop and more"
},
fixed = {
"Shapescape windows now resize properly",
"Fixed numerous bugs with CraftOS-PC",
"Solved some incompatibility issues with 1.12.2 (may not have caught all, please report if there are more)",
"Fixed some bugs in the login screen",
}
},
{
date = "08-08-2022",
version = "2.4.1",
description = "Thanks for the bug reports everyone! All bugs reported have been fixed, and the desktop got some necessary additions as well.",
added = {
"Right clicking an empty space on the desktop now opens a context menu for creating files and refreshing",
"Files can now be renamed directly from the desktop",
},
fixed = {
"Changed fs.combine into a vararg function on 1.12.2 to fix compatibility issues",
"Modified lUtils.wordwrap to account for the extra empty line that appears on CraftOS-PC",
"Prepared URLs for porting to a different server",
}
},
{
date = "11-08-2022",
version = "2.4.2",
added = {
"The text color of icons on the desktop can now be changed through the desktop context menu",
},
fixed = {
"Trying to perform operations on a shortcut of a deleted file no longer errors"
}
},
{
date = "01-09-2022",
version = "2.4.3",
description = "The new servers are finally here! Expect a lot of new features to follow soon that have become possible thanks to the migration.",
added = {
"Added 3x3 icons to some system folders",
"Migrated to new servers",
},
fixed = {
"Improved LevelCloud efficiency",
"Fixed a number of issues in the login screen",
}
},
{
date = "17-09-2022",
version = "2.4.4",
description = "Finally implemented some much needed LevelCloud features. Sync conflicts now have a proper interface and you can see the status of file synchronization in the LevelOS file explorer.",
added = {
"Explorer now shows synchronization status of cloud files",
"Sync conflicts in LevelCloud can now be resolved through the interface",
"Old context menus in LevelOS now have scrolling like the new ones",
}
},
{
date = "18-09-2022",
version = "2.4.5",
description = "It seems I broke something big last update. Sorry guys, fixed it now.",
fixed = {
"Fixed a recursion issue in the LevelOS Desktop generation that caused a crash on startup",
},
},
{
date = "12-02-2023",
version = "2.4.6",
description = "This update is all about bugfixes. The entire list of bugs has been worked through except for one, so thanks for all of the reports!",
fixed = {
"Explorer no longer crashes when the opened folder is deleted",
"LevelOS no longer displays a warning about LuaJIT when not using LuaJIT",
"LevelOS no longer crashes when being ran again after being terminated",
"Pressing space during a blue screen actually restarts now",
"The Lua REPL no longer crashes when documentation is not found",
"Icons no longer go under the taskbar",
},
added = {
"The store now displays icons of apps that use the recommended LevelOS program structure (a main.lua file with a 3x3 icon.bimg file in a folder)",
},
},
{
date = "25-11-2023",
version = "2.4.7",
description = "A small update to fix some things in the lUtils API. LevelOS 3 is in development and coming soon!",
fixed = {
"The lUtils text editor (used by the Lua REPL and Slime Text) now recognizes indenting as a change to be saved and undone",
"The lUtils.popup function now automatically sets width and/or height if not provided",
"The lUtils.popup function now uses a better word wrapping algorithm so text doesn't go outside of the box anymore",
"The start menu on the taskbar now opens instantly without having to receive another event",
},
},
{
date = "28-11-2023",
version = "2.4.8",
description = "Another small update with some bugfixes that were reported a while ago.",
fixed = {
"Resizing the entirety of LevelOS now works correctly",
"Trying to execute LevelOS within itself no longer causes a bluescreen",
},
},
{
date = "09-12-2023",
version = "2.4.9",
added = {
"You can now copy/paste text within the lUtils text editor using ctrl+c and ctrl+v outside of emulators as well, as long as you have some kind of text in your clipboard",
"Autocomplete in the lUtils text editor can now list nil values",
"Added lOS.getRunningProcess()",
}
},
{
date = "09-04-2024",
version = "2.5.0",
major = true,
description = "LevelOS 2 is finally completely compatible with CC: Tweaked 1.109! Apologies it took so long!",
added = {
"HTTP requests are now private to the programs sending them and can't conflict with eachother",
"The tabs and search in the store are now functional, and creator names are displayed below the program titles",
},
fixed = {
"LevelOS is now compatible with CC 1.109 and above",
"lOS.getRunningProcess() now returns the correct process at all times",
}
},
{
date = "11-04-2024",
version = "2.5.1",
fixed = {
"Restored compatibility with 1.12.2 versions of CC: Tweaked",
},
},
{
date = "18-04-2024",
version = "2.5.2",
fixed = {
"Added compatibility with the newest CraftOS-PC Accelerated",
},
},
{
date = "10-08-2024",
version = "2.5.3",
fixed = {
"Fixed the bluescreen upon closing the changelog on newer versions of ComputerCraft",
"Fixed a bug with UTF-8 decoding",
},
},
{
date = "11-08-2024",
version = "2.5.4",
fixed = {
"Resolved an error in the updater with the newer versions of ComputerCraft",
},
},
}

View File

@@ -0,0 +1,3 @@
{
package = "Full",
}

1
LevelOS/data/version.txt Normal file
View File

@@ -0,0 +1 @@
1723386918734

1608
LevelOS/desktop.lua Normal file

File diff suppressed because it is too large Load Diff

85
LevelOS/imageviewer.lua Normal file
View File

@@ -0,0 +1,85 @@
local format
local function getLines(str)
local lines = {}
local w = 0
for potato in str:gmatch("[^\n]+") do
table.insert(lines,potato)
if #potato > w then
w = #potato
end
end
return lines,w
end
--[[local function render(spr)
term.setBackgroundColor(colors.black)
term.clear()
if format == "lImg" then
local sW,sH = #spr[1][1],#spr
local w,h = term.getSize()
for l=1,#spr do
term.setCursorPos(math.ceil(w/2)-math.floor(sW/2),math.ceil(h/2)-math.floor(sH/2)+(l-1))
local bl = {}
bl[1] = spr[l][1]
bl[2] = string.gsub(spr[l][2],"T",lUtils.toBlit(term.getBackgroundColor()))
bl[3] = string.gsub(spr[l][3],"T",lUtils.toBlit(term.getBackgroundColor()))
term.blit(unpack(bl))
end
elseif format == "nfp" or format == "nfg" then
local b,e = string.find(spr,"\n")
local sW,sH
local w,h = term.getSize()
local lines,sW = getLines(spr)
sH = #lines
for l=1,sH do
term.setCursorPos(math.ceil(w/2)-math.floor(sW/2),math.ceil(h/2)-math.floor(sH/2)+(l-1))
term.blit(string.rep(" ",#lines[l]),lines[l],lines[l])
end
end
end]]
local render = lUtils.renderImg
local tArgs = {...}
local filepath
if tArgs[1] ~= nil and fs.exists(tArgs[1]) then
filepath = tArgs[1]
end
while not filepath do
filepath = lUtils.explorer("User","SelFile false")
end
local sprite = {}
local ext = lUtils.getFileType(filepath)
if ext == ".nfp" then
format = "nfp"
sprite[1] = lUtils.fread(filepath)
elseif ext == ".nfg" then
format = "nfg"
sprite = lUtils.asset.load(filepath)
elseif ext == ".limg" or ext == ".bimg" then
format = "lImg"
sprite = lUtils.asset.load(filepath)
else
lUtils.popup("Error","This file type is not supported!",22,9,{"OK"})
return
end
local tID = os.startTimer(0.5)
render(sprite[1])
local spr = 1
while true do
local e = {os.pullEvent()}
if #sprite > 1 and e[1] == "timer" and e[2] == tID then
tID = os.startTimer(0.1)
spr = spr+1
if spr > #sprite then
spr = 1
end
term.clear()
render(sprite[spr])
elseif e[1] == "term_resize" then
term.clear()
render(sprite[spr])
end
end

258
LevelOS/lStore.lua Normal file
View File

@@ -0,0 +1,258 @@
local cookie
if lOS and lOS.userID then
cookie = {Cookie=lOS.userID}
end
local function printUsage()
local programName = arg[0] or fs.getName(shell.getRunningProgram())
print("Usages:")
print(programName .. " put <path> <project name> [listing]")
print(programName .. " get <project name> <path>")
print(programName .. " run <project name> <arguments>")
end
local tArgs = { ... }
if #tArgs < 2 then
printUsage()
return
end
if not http then
printError("LevelStore requires the http API")
printError("Set http.enabled to true in CC: Tweaked's config")
return
end
local function fread(file)
local f = fs.open(file,"r")
local o = f.readAll()
f.close()
return o
end
local function fwrite(file,content)
local f = fs.open(file,"w")
f.write(content)
f.close()
return true
end
local hpost = http.post
local function getField(thing,fieldname)
if string.find(thing,"<"..fieldname..">",1,true) ~= nil and string.find(thing,"</"..fieldname..">",1,true) ~= nil then
begin = nil
ending = nil
trash,begin = string.find(thing,"<"..fieldname..">",1,true)
ending,ending2 = string.find(thing,"</"..fieldname..">",begin+1,true)
if begin ~= nil and ending ~= nil then
return string.sub(thing,begin+1,ending-1),string.sub(thing,1,trash-1)..string.sub(thing,ending2+1,string.len(thing))
end
end
return nil
end
local rType
local function download(name,pth,saveto,run)
local f = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode(pth).."&"..rType.."="..textutils.urlEncode(name),cookie).readAll()
if f and f ~= "409" and f ~= "403" and f ~= "401" then
if run then
return f
else
fwrite(saveto,f)
return true
end
else
return false
end
end
local function get(name)
write("Connecting to LevelStore... ")
rType = "code"
local response, err = http.post("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode("").."&code="..textutils.urlEncode(name),cookie)
if not response then
rType = "name"
response, err = http.post("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode("").."&name="..textutils.urlEncode(name),cookie)
end
if response then
local tree = {}
local folders = {}
local function searchFolder(folder)
--print("Searching folder root/"..folder)
local f = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode(folder).."&"..rType.."="..textutils.urlEncode(name),cookie).readAll()
--print(f)
local f2 = f
while true do
local file = nil
file,f = getField(f,"file")
if not file then
break
else
local name = getField(file,"name")
tree[#tree+1] = fs.combine(folder,name)
--print("Found "..fs.combine(folder,name))
end
end
f = f2
while true do
local file = nil
file,f = getField(f,"folder")
if not file then
break
else
local name = getField(file,"name")
--if not fs.exists(fs.combine(folder,name)) then
--fs.makeDir(fs.combine(folder,name))
--end
folders[#folders+1] = fs.combine(folder,name)
searchFolder(fs.combine(folder,name))
end
end
return true
end
searchFolder("")
print("Success.")
return tree,folders
else
printError("Failed.")
print(err)
end
end
local sCommand = tArgs[1]
if sCommand == "put" then
if #tArgs < 3 then
printUsage()
return
end
local listings = {"unlisted","public"}
for t=1,#listings do
listings[listings[t]] = true
end
local listing
if tArgs[4] then
if not listings[tArgs[4]] then
error(tArgs[4].." is not a valid listing. Choose one of the following: "..table.concat( listings, ", "),0)
else
listing = tArgs[4]
end
end
if not lOS.userID then
print("Not logged in")
print("Please have an active instance of LevelCloud running")
return
end
local sFile = tArgs[2]
local sPath = shell.resolve(fs.combine("User/Cloud",sFile))
if not fs.exists(sPath) or not string.find(sPath,"User/Cloud") then
print("Path not found")
print("Note: provide a relative path to a file or folder starting from cloud")
return
end
local sName = string.gsub(tArgs[3]," ","_")
local list = ""
if listing then
list = "&listing="..textutils.urlEncode(listing)
end
write("Connecting to LevelStore... ")
local response = http.post(
"https://os.leveloper.cc/sProject.php",
"path="..textutils.urlEncode(tArgs[2])..
"&title="..textutils.urlEncode(sName)..
"&timestamp="..textutils.urlEncode(tostring(os.epoch("utc")))..
"&direct="..textutils.urlEncode("false")..
list,
{
Cookie = lOS.userID
}
)
if response then
print("Success.")
local sResponse = response.readAll()
response.close()
print("Uploaded as " .. sResponse)
print("Run \"lStore get " .. sName .. "\" or \"lStore get " .. sResponse .. "\" to download anywhere")
else
printError("Failed.")
end
elseif sCommand == "get" then
if #tArgs < 3 then
printUsage()
return
end
-- Determine file to download
local sCode = tArgs[2]
local sFile = tArgs[3]
local sPath = shell.resolve(sFile)
if fs.exists(sPath) then
print("Path already exists")
return
end
local tree,folders = get(sCode)
if not tree then return end
term.write("Downloading... ")
local x,y = term.getCursorPos()
term.write("0%")
if #tree > 1 or #folders > 0 then
fs.makeDir(sPath)
for f=1,#folders do
fs.makeDir(fs.combine(sPath,folders[f]))
end
for f=1,#tree do
download(sCode,tree[f],fs.combine(sPath,tree[f]))
term.setCursorPos(x,y)
term.write(math.ceil((f/#tree)*100+0.5).."%")
end
else
download(sCode,tree[1],sPath)
end
term.setCursorPos(x,y)
print("100%")
print("Downloaded as " .. sFile)
elseif sCommand == "run" then
local sCode = tArgs[2]
local res
local tree,folders = get(sCode)
if not tree then return end
if #tree > 1 or #folders > 0 then
print("This project must be downloaded to run.")
return
else
--print(textutils.serialize(tree))
res = download(sCode,tree[1],"",true)
end
if res then
local func, err = load(res, sCode, "t", _ENV)
if not func then
printError(err)
return
end
local success, msg = pcall(func, select(3, ...))
if not success then
printError(msg)
end
end
else
printUsage()
return
end

396
LevelOS/login.lua Normal file
View File

@@ -0,0 +1,396 @@
local bg = term.getBackgroundColor()
local fg = term.getTextColor()
if fs.exists("bigfont") then
os.loadAPI("bigfont")
end
local register = false
local rememberme = false
local w,h = term.getSize()
local userbox = lUtils.makeEditBox("username",w,1)
local pwbox = lUtils.makeEditBox("password",w,1)
local pwconfirm = lUtils.makeEditBox("pwconfirm",w,1)
if fs.exists("LevelOS/data/account.txt") then
userbox.lines[1] = lUtils.fread("LevelOS/data/account.txt")
end
if fs.exists("LevelOS/data/account2.txt") then
--pwbox.lines[1] = lUtils.fread("LevelOS/data/account2.txt")
token = lUtils.fread("LevelOS/data/account2.txt")
--rememberme = true
local res = http.post("https://www.old.leveloper.cc/auth.php","username="..userbox.lines[1].."&token="..token)
local str = res.readAll()
if str:find("Welcome") then
local userID = res.getResponseHeaders()["Set-Cookie"]
return userID,userbox.lines[1]
end
end
local trysub = false
local continue = true
local boxes = {}
local e = {}
local webresponse
local userID = ""
local pause = false
local function submit()
trysub = true
continue = true
os.sleep(0.5)
if continue == true then
saveuser = fs.open("LevelOS/data/account.txt","w")
saveuser.write(userbox.lines[1])
saveuser.close()
if rememberme then
--lUtils.fwrite("LevelOS/data/account2.txt",pwbox.lines[1])
else
fs.delete("LevelOS/data/account2.txt")
end
if register then
response = {http.post("https://www.old.leveloper.cc/register.php","username="..userbox.lines[1].."&password="..pwbox.lines[1])}
local webres = response[1].readAll()
if webres == "200" then
local xtra = ""
if rememberme then
xtra = "&rememberme=true"
end
response2 = {http.post("https://www.old.leveloper.cc/auth.php","username="..userbox.lines[1].."&password="..pwbox.lines[1]..xtra)}
userID = response2[1].getResponseHeaders()["Set-Cookie"]
webresponse = webres
if rememberme then
token = lUtils.getField(response2[1].readAll(),"token")
lUtils.fwrite("LevelOS/data/account2.txt",token)
end
end
else
local xtra = ""
if rememberme then
xtra = "&rememberme=true"
end
response = {http.post("https://www.old.leveloper.cc/auth.php","username="..userbox.lines[1].."&password="..pwbox.lines[1]..xtra)}
webresponse = response[1].readAll()
userID = response[1].getResponseHeaders()["Set-Cookie"]
if rememberme then
token = lUtils.getField(webresponse,"token")
lUtils.fwrite("LevelOS/data/account2.txt",token)
end
end
--print("username="..userbox.lines[1].."&password="..pwbox.lines[1])
-- check if things are present communicate with PHP
end
end
local regsel = false
local function draw()
boxes = {}
local cY = 1
local w,h = term.getSize()
term.setBackgroundColor(colors.white)
term.clear()
term.setBackgroundColor(colors.white)
if h < 19 then
-- absolutely fkin nothin
elseif h < 25 or w < 26 or not bigfont then
for t=0,2 do
term.setCursorPos(1,cY+t)
term.clearLine()
end
term.setCursorPos(2,cY+2)
term.setTextColor(colors.white)
term.setBackgroundColor(colors.lightGray)
term.write(string.rep("\143",w-2))
term.setTextColor(colors.blue)
term.setBackgroundColor(colors.white)
cY = cY+1
term.setCursorPos(1,cY)
if register then
lUtils.centerText("Register")
else
lUtils.centerText("Log in")
end
cY = cY+2
else
if h < 50 or w < 90 then
for t=0,4 do
term.setCursorPos(1,cY+t)
term.clearLine()
end
term.setCursorPos(2,cY+4)
else
for t=0,10 do
term.setCursorPos(1,cY+t)
term.clearLine()
end
term.setCursorPos(2,cY+10)
end
term.setTextColor(colors.white)
term.setBackgroundColor(colors.lightGray)
term.write(string.rep("\143",w-2))
term.setTextColor(colors.blue)
term.setBackgroundColor(colors.white)
cY = cY+1
local size = 1
--cY = cY+4
if h >= 50 and w >= 90 then
size = 2
cY = cY+10
else
cY = cY+4
end
if register then
bigfont.writeOn(term.current(),size,"Register",nil,2)
else
bigfont.writeOn(term.current(),size,"Log in",nil,2)
end
end
term.setBackgroundColor(colors.white)
for y=cY,h do
term.setCursorPos(1,y)
term.clearLine()
end
cY = cY+1
term.setTextColor(colors.lightGray)
local offset = math.ceil(w/30)
local spacing = 0
if h > 50 then
spacing = 5
elseif h > 45 then
spacing = 4
elseif h > 40 then
spacing = 3
elseif h > 35 then
spacing = 2
elseif h > 30 then
spacing = 1
end
cY = cY+spacing
if (register and trysub and userbox.lines[1] and userbox.lines[1] ~= "" and string.len(userbox.lines[1]) >= 3 and #userbox.lines[1] <= 15 and not string.find(userbox.lines[1],"[^a-zA-Z0-9]")) then -- also check for special characters
term.setTextColor(colors.lime)
elseif register and trysub then
term.setTextColor(colors.red)
term.setCursorPos(1,cY+3)
if #userbox.lines[1] < 3 or #userbox.lines[1] > 15 then
lUtils.centerText("Username must be between 3-15 characters.")
else
lUtils.centerText("Username can not contain special characters.")
end
continue = false
else
term.setTextColor(colors.lightGray)
end
lUtils.border(1+offset,cY,w-offset,cY+2)
userbox.x = 2+offset
userbox.y = cY+1
userbox.width = ((w-offset)-1)-(1+offset)
boxes[#boxes+1] = {x1=1+offset,y1=cY,x2=w-offset,y2=cY+2,func=function() lUtils.drawEditBox(userbox,nil,nil,nil,nil,nil,nil,true,false) end}
cY = cY+1
term.setCursorPos(2+offset,cY)
if userbox.lines[1] and userbox.lines[1] ~= "" then
term.setTextColor(colors.gray)
term.write(string.sub(userbox.lines[1],1,userbox.width))
else
term.write("Username")
end
cY = cY+3+spacing
if (register and trysub and pwbox.lines[1] and pwbox.lines[1] ~= "" and string.len(pwbox.lines[1]) >= 5) then
term.setTextColor(colors.lime)
elseif register and trysub then
term.setTextColor(colors.red)
continue = false
else
term.setTextColor(colors.lightGray)
end
lUtils.border(1+offset,cY,w-offset,cY+2)
pwbox.x = 2+offset
pwbox.y = cY+1
pwbox.width = ((w-offset)-1)-(1+offset)
boxes[#boxes+1] = {x1=1+offset,y1=cY,x2=w-offset,y2=cY+2,func=function() lUtils.drawEditBox(pwbox,nil,nil,nil,nil,nil,nil,true,false,"*") end}
cY = cY+1
term.setCursorPos(2+offset,cY)
if pwbox.lines[1] and pwbox.lines[1] ~= "" then
term.setTextColor(colors.gray)
term.write(string.rep("*",string.len(string.sub(pwbox.lines[1],1,pwbox.width))))
else
term.write("Password")
end
if register then
cY = cY+3+spacing
if (register and trysub and pwconfirm.lines[1] and pwconfirm.lines[1] ~= "" and string.len(pwconfirm.lines[1]) > 3 and pwconfirm.lines[1] == pwbox.lines[1]) then
term.setTextColor(colors.lime)
elseif register and trysub then
term.setTextColor(colors.red)
if spacing > 0 then
term.setCursorPos(1,cY+3)
lUtils.centerText("Passwords don't match.")
end
continue = false
else
term.setTextColor(colors.lightGray)
end
lUtils.border(1+offset,cY,w-offset,cY+2)
pwconfirm.x = 2+offset
pwconfirm.y = cY+1
pwconfirm.width = ((w-offset)-1)-(1+offset)
boxes[#boxes+1] = {x1=1+offset,y1=cY,x2=w-offset,y2=cY+2,func=function() lUtils.drawEditBox(pwconfirm,nil,nil,nil,nil,nil,nil,true,false,"*") end}
cY = cY+1
term.setCursorPos(2+offset,cY)
if pwconfirm.lines[1] and pwconfirm.lines[1] ~= "" then
term.setTextColor(colors.gray)
term.write(string.rep("*",string.len(string.sub(pwconfirm.lines[1],1,pwconfirm.width))))
else
term.write("Confirm Password")
end
end
cY = cY+3+spacing
term.setTextColor(colors.white)
if e[1] == "mouse_click" and e[3] >= 1+(offset+2) and e[4] >= cY and e[3] <= w-(offset+2) and e[4] <= cY+2 then
regsel = true
elseif e[1] == "mouse_up" then
regsel = false
end
if regsel or trysub then
term.setBackgroundColor(colors.lightBlue)
else
term.setBackgroundColor(colors.blue)
end
lUtils.border(1+(offset+2),cY,w-(offset+2),cY+2,"fill")
boxes[#boxes+1] = {x1=1+(offset+2),y1=cY,x2=w-(offset+2),y2=cY+2,func=submit}
cY = cY+1
term.setCursorPos(1,cY)
if register then
lUtils.centerText("Register")
term.setBackgroundColor(colors.white)
term.setTextColor(colors.lightBlue)
term.setCursorPos(1,cY-2)
local w,h = term.getSize()
if w < string.len("Already have an account? Log in.") then
lUtils.centerText("Log in")
else
lUtils.centerText("Already have an account? Log in.")
end
boxes[#boxes+1] = {x1=math.ceil(w/2)-16,x2=math.ceil(w/2)+16,y1=cY-2,y2=cY-2,func=function() register = false end}
else
lUtils.centerText("Log in")
term.setBackgroundColor(colors.white)
term.setTextColor(colors.lightBlue)
term.setCursorPos(1,cY+2)
local w,h = term.getSize()
if w < string.len("Don't have an account yet? Register.") then
lUtils.centerText("Register")
else
lUtils.centerText("Don't have an account yet? Register.")
end
boxes[#boxes+1] = {x1=math.ceil(w/2)-18,x2=math.ceil(w/2)+18,y1=cY+2,y2=cY+2,func=function() register = true end}
end
cY = cY+4
local bl = {
{
"Ÿ",
"00f",
"ff0",
},
{
"• •",
"0ff",
"f00",
},
{
"‚ƒ",
"fff",
"000",
},
}
if rememberme then
bl[2][1] = "•x•"
end
local txt = " Auto-login" -- 4 spaces for the box
local rX = math.ceil(w/2)-math.floor(#txt/2)
term.setCursorPos(rX,cY)
term.setBackgroundColor(colors.white)
term.setTextColor(colors.gray)
term.write(txt)
for b=1,#bl do
term.setCursorPos(rX,(cY-2)+b)
term.blit(unpack(bl[b]))
end
table.insert(boxes,{x1=rX,y1=cY,x2=rX+2,y2=cY,func=function() local f = function() rememberme = not rememberme end pause = true f() pause = false end})
end
local function textboxes()
while true do
local e = {os.pullEvent()}
term.setCursorPos(1,1)
term.setBackgroundColor(colors.white)
term.setTextColor(colors.black)
--term.write(table.concat(e,", "))
if e[1] == "mouse_up" and e[2] == 1 then
for b=1,#boxes do
local box = boxes[b]
if e[3] >= box.x1 and e[4] >= box.y1 and e[3] <= box.x2 and e[4] <= box.y2 then
trysub = false
box.func()
os.startTimer(0.1)
end
end
end
end
end
local txtbox = coroutine.create(textboxes)
if rememberme then submit() end
draw()
while true do
e = {os.pullEvent()}
local w,h = term.getSize()
local pW,pH
if w < 29 then
pW = 19
pH = 15
else
pW = 29
pH = 9
end
if not webresponse then
if not pause then
draw()
end
coroutine.resume(txtbox,table.unpack(e))
while pause do
local e = {os.pullEvent()}
coroutine.resume(txtbox,table.unpack(e))
end
else
if (register and webresponse ~= "200") or (not register and not string.find(webresponse,"Welcome")) then
lUtils.popup("LevelOS",lUtils.getField(webresponse,"msg"),pW,pH,{"OK"})
term.setTextColor(fg)
term.setBackgroundColor(bg)
if rememberme then
rememberme = false
fs.delete("LevelOS/data/account2.txt")
end
return false
elseif register then
lUtils.popup("LevelOS","You have successfully registered! You are now logged in.",pW,pH,{"OK"})
term.setTextColor(fg)
term.setBackgroundColor(bg)
return userID,userbox.lines[1]
else
term.setTextColor(fg)
term.setBackgroundColor(bg)
return userID,userbox.lines[1]
end
end
end

713
LevelOS/modules/lex.lua Normal file
View File

@@ -0,0 +1,713 @@
-- Lex, by LoganDark
-- Can be loaded using os.loadAPI, has only a single function: lex.lex('code here')
-- If loaded using dofile(), it returns the lex function (for environments outside ComputerCraft)
-- It returns a list of lists, where each list is one line.
-- Each line contains tokens (in the order they are found), where each token is formatted like this:
-- {
-- type = one of the token types below,
-- data = the source code that makes up the token,
-- posFirst = the position (inclusive) within THAT LINE that the token starts
-- posLast = the position (inclusive) within THAT LINE that the token ends
-- }
-- Possible token types:
-- whitespace: Self-explanatory. Can match spaces, newlines, tabs, and carriage returns (although I don't know why anyone would use those... WINDOWS)
-- comment: Either multi-line or single-line comments.
-- string: A string. Usually the part of the string that is not an escape.
-- escape: Can only be found within strings (although they are separate tokens)
-- keyword: Keywords. Like "while", "end", "do", etc
-- value: Special values. Only true, false, and nil.
-- ident: Identifier. Variables, function names, etc..
-- number: Numbers!
-- symbol: Symbols, like brackets, parenthesis, ., .., ... etc
-- operator: Operators, like =, ==, >=, <=, ~=, etc
-- unidentified: Anything that isn't one of the above tokens. Consider them ERRORS.
local chars = {
whitespace = {
[' '] = true,
['\n'] = true,
['\t'] = true,
['\r'] = true
},
validEscapes = {
['a'] = true,
['b'] = true,
['f'] = true,
['n'] = true,
['r'] = true,
['t'] = true,
['v'] = true,
['"'] = true,
['\''] = true,
['\\'] = true,
['\n'] = true
},
ident = {
['a'] = true,
['b'] = true,
['c'] = true,
['d'] = true,
['e'] = true,
['f'] = true,
['g'] = true,
['h'] = true,
['i'] = true,
['j'] = true,
['k'] = true,
['l'] = true,
['m'] = true,
['n'] = true,
['o'] = true,
['p'] = true,
['q'] = true,
['r'] = true,
['s'] = true,
['t'] = true,
['u'] = true,
['v'] = true,
['w'] = true,
['x'] = true,
['y'] = true,
['z'] = true,
['A'] = true,
['B'] = true,
['C'] = true,
['D'] = true,
['E'] = true,
['F'] = true,
['G'] = true,
['H'] = true,
['I'] = true,
['J'] = true,
['K'] = true,
['L'] = true,
['M'] = true,
['N'] = true,
['O'] = true,
['P'] = true,
['Q'] = true,
['R'] = true,
['S'] = true,
['T'] = true,
['U'] = true,
['V'] = true,
['W'] = true,
['X'] = true,
['Y'] = true,
['Z'] = true,
['_'] = true,
['0'] = true,
['1'] = true,
['2'] = true,
['3'] = true,
['4'] = true,
['5'] = true,
['6'] = true,
['7'] = true,
['8'] = true,
['9'] = true,
start = {
['a'] = true,
['b'] = true,
['c'] = true,
['d'] = true,
['e'] = true,
['f'] = true,
['g'] = true,
['h'] = true,
['i'] = true,
['j'] = true,
['k'] = true,
['l'] = true,
['m'] = true,
['n'] = true,
['o'] = true,
['p'] = true,
['q'] = true,
['r'] = true,
['s'] = true,
['t'] = true,
['u'] = true,
['v'] = true,
['w'] = true,
['x'] = true,
['y'] = true,
['z'] = true,
['A'] = true,
['B'] = true,
['C'] = true,
['D'] = true,
['E'] = true,
['F'] = true,
['G'] = true,
['H'] = true,
['I'] = true,
['J'] = true,
['K'] = true,
['L'] = true,
['M'] = true,
['N'] = true,
['O'] = true,
['P'] = true,
['Q'] = true,
['R'] = true,
['S'] = true,
['T'] = true,
['U'] = true,
['V'] = true,
['W'] = true,
['X'] = true,
['Y'] = true,
['Z'] = true,
['_'] = true
},
},
digits = {
['0'] = true,
['1'] = true,
['2'] = true,
['3'] = true,
['4'] = true,
['5'] = true,
['6'] = true,
['7'] = true,
['8'] = true,
['9'] = true,
hex = {
['0'] = true,
['1'] = true,
['2'] = true,
['3'] = true,
['4'] = true,
['5'] = true,
['6'] = true,
['7'] = true,
['8'] = true,
['9'] = true,
['a'] = true,
['b'] = true,
['c'] = true,
['d'] = true,
['e'] = true,
['f'] = true,
['A'] = true,
['B'] = true,
['C'] = true,
['D'] = true,
['E'] = true,
['F'] = true
}
},
symbols = {
['+'] = true,
['-'] = true,
['*'] = true,
['/'] = true,
['^'] = true,
['%'] = true,
[','] = true,
['{'] = true,
['}'] = true,
['['] = true,
[']'] = true,
['('] = true,
[')'] = true,
[';'] = true,
['#'] = true,
['.'] = true,
[':'] = true,
equality = {
['~'] = true,
['='] = true,
['>'] = true,
['<'] = true
},
operators = {
['+'] = true,
['-'] = true,
['*'] = true,
['/'] = true,
['^'] = true,
['%'] = true,
['#'] = true
}
}
}
local keywords = {
structure = {
['and'] = true,
['break'] = true,
['do'] = true,
['else'] = true,
['elseif'] = true,
['end'] = true,
['for'] = true,
['function'] = true,
['goto'] = true,
['if'] = true,
['in'] = true,
['local'] = true,
['not'] = true,
['or'] = true,
['repeat'] = true,
['return'] = true,
['then'] = true,
['until'] = true,
['while'] = true
},
values = {
['true'] = true,
['false'] = true,
['nil'] = true,
['self'] = true,
}
}
function lex(text)
local pos = 1
local start = 1
local len = #text
local buffer = {}
local lines = {}
local function look(delta)
delta = pos + (delta or 0)
return text:sub(delta, delta)
end
local function get()
local char = text:sub(pos, pos)
pos = pos + 1
return char
end
local function getLevel()
local num = 0
while look(num) == '=' do
num = num + 1
end
if look(num) == '[' then
pos = pos + num
return num
else
return nil
end
end
local function getToken()
return text:sub(start, pos - 1)
end
local currentLineLength = 0
local lineoffset = 0
local function token(type, text)
local tk = buffer[#buffer]
if not tk or tk.type ~= type then
local tk = {
type = type,
data = text or getToken(),
posFirst = start - lineoffset,
posLast = pos - 1 - lineoffset
}
if tk.data ~= '' then
buffer[#buffer + 1] = tk
end
else
tk.data = tk.data .. (text or getToken())
tk.posLast = tk.posFirst + #tk.data - 1
--tk.posLast = getCol(pos - 1)
end
currentLineLength = currentLineLength + (text or getToken()):len()
start = pos
return tk
end
local function newline()
lines[#lines + 1] = buffer
buffer = {}
get()
token('newline')
buffer[1] = nil
lineoffset = lineoffset + currentLineLength
currentLineLength = 0
end
local function getData(level, type)
while true do
local char = get()
if char == '' then
return
elseif char == '\n' then
pos = pos - 1
token(type)
newline()
elseif char == ']' then
local valid = true
for i = 1, level do
if look() == '=' then
pos = pos + 1
else
valid = false
break
end
end
if valid and look() == ']' then
pos = pos + 1
return
end
end
end
end
while true do
while true do
local char = look()
if char == '\n' then
token('whitespace')
newline()
elseif chars.whitespace[char] then
pos = pos + 1
else
break
end
end
token('whitespace')
local char = get()
if char == '' then
break
elseif char == '-' and look() == '-' then
pos = pos + 1
if look() == '[' then
pos = pos + 1
local level = getLevel()
if level then
getData(level, 'comment')
else
while true do
local char2 = get()
if char2 == '' or char2 == '\n' then
pos = pos - 1
token('comment')
if char2 == '\n' then
newline()
end
break
end
end
end
else
while true do
local char2 = get()
if char2 == '' or char2 == '\n' then
pos = pos - 1
token('comment')
if char2 == '\n' then
newline()
end
break
end
end
end
token('comment')
elseif char == '\'' or char == '"' then
local cbuf = #buffer
while true do
if not buffer[cbuf] then
break
elseif buffer[cbuf].type == "whitespace" then
cbuf = cbuf-1
elseif buffer[cbuf].type == "ident" then
buffer[cbuf].type = "function"
break
else
break
end
end
while true do
local char2 = get()
if char2 == '\\' then
pos = pos - 1
token('string')
get()
local char3 = get()
if chars.digits[char3] then
for i = 1, 2 do
if chars.digits[look()] then
pos = pos + 1
end
end
elseif char3 == 'x' then
if chars.digits.hex[look()] and chars.digits.hex[look(1)] then
pos = pos + 2
else
token('unidentified')
end
elseif char3 == '\n' then
pos = pos - 1
token('escape')
newline()
elseif not chars.validEscapes[char3] then
token('unidentified')
end
token('escape')
elseif char2 == '\n' then
pos = pos - 1
token('string')
newline()
break
elseif char2 == char or char2 == '' then
break
end
end
token('string')
elseif chars.ident.start[char] then
while chars.ident[look()] do
pos = pos + 1
end
local word = getToken()
if word == 'self' or word == '_ENV' or word == "_G" then
token('arg')
elseif word == 'function' then
local findBracket = false
local c = 0
while true do
_G.debugstr = ""
local lChar = look(c)
_G.debugstr = debugstr..lChar
if lChar == " " or lChar == "\t" then
c = c+1
elseif lChar == "(" then
findBracket = true
break
else
break
end
end
if findBracket then
local cbuf = #buffer
local findEquals = false
while true do
--_G.debugstr = debugstr..buffer[cbuf].type
if not buffer[cbuf] then
break
elseif buffer[cbuf].type == "whitespace" then
cbuf = cbuf-1
elseif buffer[cbuf].data == "=" and not findEquals then
cbuf = cbuf-1
findEquals = true
elseif buffer[cbuf].type == "ident" and findEquals then
buffer[cbuf].type = "nfunction"
break
else
break
end
end
end
token('function')
elseif keywords.structure[word] then
token('keyword')
elseif keywords.values[word] then
token('value')
else
local findBracket = false
local c = 0
while true do
local lChar = look(c)
if lChar == " " or lChar == "\t" then
c = c+1
elseif lChar == "(" then
findBracket = true
break
else
break
end
end
if findBracket then
if buffer[#buffer-1] and buffer[#buffer-1].data == "function" and buffer[#buffer].type == "whitespace" then
token('nfunction')
else
token('function')
end
else
local b = #buffer
local isArg = true
local closedArgs = false
while true do
local buf = buffer[b]
if not buf then
isArg = false
break
elseif buf.data == "(" or buf.type == "whitespace" or buf.data == "," or buf.type == "arg" then
if buf.data == "(" then
closedArgs = true
end
b = b-1
elseif (buf.data == "function" or buf.type == "nfunction") and closedArgs then
token('arg')
break
else
isArg = false
break
end
end
if not isArg then
token('ident')
end
end
end
elseif chars.digits[char] or (char == '.' and chars.digits[look()]) then
if char == '0' and look() == 'x' then
pos = pos + 1
while chars.digits.hex[look()] do
pos = pos + 1
end
else
while chars.digits[look()] do
pos = pos + 1
end
if look() == '.' then
pos = pos + 1
while chars.digits[look()] do
pos = pos + 1
end
end
if look():lower() == 'e' then
pos = pos + 1
if look() == '-' then
pos = pos + 1
end
while chars.digits[look()] do
pos = pos + 1
end
end
end
token('number')
elseif char == '[' then
local level = getLevel()
if level then
local cbuf = #buffer
while true do
if not buffer[cbuf] then
break
elseif buffer[cbuf].type == "whitespace" then
cbuf = cbuf-1
elseif buffer[cbuf].type == "ident" then
buffer[cbuf].type = "function"
break
else
break
end
end
getData(level, 'string')
token('string')
else
token('symbol')
end
elseif char == '.' then
if look() == '.' then
pos = pos + 1
if look() == '.' then
pos = pos + 1
token('value')
else
token('operator')
end
else
token('symbol')
end
elseif chars.symbols.equality[char] then
if look() == '=' then
pos = pos + 1
else
end
token('operator')
elseif chars.symbols[char] then
if chars.symbols.operators[char] then
token('operator')
else
if char == "{" then
local cbuf = #buffer
while true do
if not buffer[cbuf] then
break
elseif buffer[cbuf].type == "whitespace" then
cbuf = cbuf-1
elseif buffer[cbuf].type == "ident" then
buffer[cbuf].type = "function"
break
else
break
end
end
end
token('symbol')
end
else
token('unidentified')
end
end
lines[#lines + 1] = buffer
return lines
end
return lex

View File

View File

@@ -0,0 +1,147 @@
local class = {}
local tAPI = {} -- local class API for objects
local shapescape
class.init = function(api)
shapescape = api
setmetatable(tAPI, {__index=api.group})
api.generic.convertToClass = class.convertToClass
end
tAPI.initialize = function(obj)
local scape = obj:getScape()
local publicProperties = obj.publicProperties or {}
setmetatable(obj, {__index=tAPI})
obj.isClass = true
local str = ""
for k,v in pairs(publicProperties) do
if v == "" then
table.remove(publicProperties,k)
end
end
if not shapescape.utils.locateEntry(publicProperties, "properties") then
table.insert(publicProperties,"properties")
end
for i,p in ipairs(publicProperties) do
if p == "width" then
str = str.."instance:resize(width or instance.width)\n"
elseif p == "height" then
str = str.."instance:resize(nil, height or instance.height)\n"
elseif p == "x" then
str = str.."instance:move(x or instance.x)\n" -- "or instance.x1" is already done by API when provided with nil value
elseif p == "y" then
str = str.."instance:move(nil, y or instance.y)\n"
else
str = str.."instance."..p.." = "..p.." or instance."..p.."\n"
end
end
table.insert(publicProperties,1,"self")
local fStr = [[
return function(]]..table.concat(publicProperties,",")..[[)
local instance = shapescape.utils.instantiate(self)
if instance.name then
instance.class = instance.name
instance.name = nil
end
]]..str..[[
for k,v in pairs(properties or {}) do
instance[k] = v
end
instance.isClass = nil
return instance
end]]
local func,err = load(fStr,"@instantiate",nil,{shapescape=shapescape,pairs=pairs})
if func then
obj.instantiate = func()
else
_G.debugstr = fStr
error(err,0)
end
if obj.name then
scape.variables[obj.name] = obj
end
end
tAPI.instantiateTo = function(self, target, ...)
if not self.instantiate then
self:initialize()
end
return target:addObject(self:instantiate(...))
end
class.convertToClass = function(self, publicProperties, posProperties)
publicProperties = publicProperties or {}
if self.active then
error("Cannot convert active objects",2)
end
local sl = self:getSlide()
if sl then
-- remove obj from slide
self:destroy(false)
end
setmetatable(self, {__index=tAPI})
self.isClass = true
self.publicProperties = publicProperties
local coords = {}
if posProperties == 1 or posProperties == nil then -- if posProperties is false then no position
coords = {"x1","y1","x2","y2"}
elseif posProperties == 2 then
coords = {"x","y","width","height"}
elseif posProperties == 3 then
coords = {"x","y"}
elseif posProperties == 4 then
coords = {"width","height"}
end
for i,c in ipairs(coords) do
if not shapescape.utils.locateEntry(publicProperties, c) then
table.insert(publicProperties, i, c)
end
end
table.insert(self:getScape().classes,self)
if self:getScape().active then
self:initialize()
end
end
tAPI.convertToObject = function(self,slide)
self.publicProperties = nil
self.isClass = nil
for k,v in ipairs(self:getScape().classes) do
if v == self then
table.remove(self:getScape().classes,k)
end
end
slide:addObject(self)
end
tAPI.destroy = function(self)
-- remove from classes
for k,v in ipairs(scape.classes) do
if v == self then
table.remove(scape.classes,k)
end
end
shapescape.generic.destroy(self)
end
class.load = function(classObj)
setmetatable(classObj, {__index=tAPI})
if classObj.children then
for i,child in ipairs(classObj.children) do
shapescape.loadObject(child)
child.parent = classObj
child.id = i
end
end
end
return class

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

121
LevelOS/settings.lua Normal file
View File

@@ -0,0 +1,121 @@
--ccvs = mwm.newCvs() -- config canvas aka settings canvas
btns = {}
function _G.btn(x,y,width,lines)
btns[#btns+1] = {}
thebtn = btns[#btns]
thebtn.x = x
thebtn.y = y
thebtn.w = width
thebtn.h = #lines+2
function thebtn.render(px,py)
if px == nil then
px,py = thebtn.x,thebtn.y
end
thebtn.blit = {{"\151",tostring(lUtils.toBlit(colors.gray)),tostring(lUtils.toBlit(term.getBackgroundColor()))}}
for t=1,thebtn.w-2 do
thebtn.blit[1][1] = thebtn.blit[1][1].."\131"
thebtn.blit[1][2] = thebtn.blit[1][2]..lUtils.toBlit(colors.gray)
thebtn.blit[1][3] = thebtn.blit[1][3]..lUtils.toBlit(term.getBackgroundColor())
end
thebtn.blit[1][1] = thebtn.blit[1][1].."\148"
thebtn.blit[1][2] = thebtn.blit[1][2]..lUtils.toBlit(term.getBackgroundColor())
thebtn.blit[1][3] = thebtn.blit[1][3]..lUtils.toBlit(colors.gray)
for t=1,#lines do
thebtn.blit[t+1] = {"\149",tostring(lUtils.toBlit(colors.gray)),tostring(lUtils.toBlit(term.getBackgroundColor()))}
for w=1,width-2 do
thebtn.blit[t+1][1] = thebtn.blit[t+1][1].." "
if t == 1 then
thebtn.blit[t+1][2] = thebtn.blit[t+1][2]..lUtils.toBlit(term.getTextColor())
else
thebtn.blit[t+1][2] = thebtn.blit[t+1][2]..lUtils.toBlit(colors.lightGray)
end
thebtn.blit[t+1][3] = thebtn.blit[t+1][3]..lUtils.toBlit(term.getBackgroundColor())
end
local thetxt = ""
if string.len(lines[t]) > thebtn.w-2 then
thetxt = string.sub(lines[t],thebtn.w-2)
else
thetxt = lines[t]
end
thebtn.blit[t+1][1] = "\149"..thetxt..string.sub(thebtn.blit[t+1][1],2+string.len(thetxt),string.len(thebtn.blit[t+1][1]))
thebtn.blit[t+1][1] = thebtn.blit[t+1][1].."\149"
thebtn.blit[t+1][2] = thebtn.blit[t+1][2]..tostring(lUtils.toBlit(term.getBackgroundColor()))
thebtn.blit[t+1][3] = thebtn.blit[t+1][3]..lUtils.toBlit(colors.gray)
end
thebtn.blit[#thebtn.blit+1] = {"\138",tostring(lUtils.toBlit(term.getBackgroundColor())),tostring(lUtils.toBlit(colors.gray))}
local tempblit = thebtn.blit[#thebtn.blit]
for t=1,thebtn.w-2 do
tempblit[1] = tempblit[1].."\143"
tempblit[2] = tempblit[2]..lUtils.toBlit(term.getBackgroundColor())
tempblit[3] = tempblit[3]..lUtils.toBlit(colors.gray)
end
tempblit[1] = tempblit[1].."\133"
tempblit[2] = tempblit[2]..lUtils.toBlit(term.getBackgroundColor())
tempblit[3] = tempblit[3]..lUtils.toBlit(colors.gray)
for t=1,#thebtn.blit do
term.setCursorPos(px,py+(t-1))
term.blit(table.unpack(thebtn.blit[t]))
end
end
return thebtn
end
lSettings = {{"Peripherals","Monitors, Speakers,","Printers"},{"Personal Settings","Background, Welcome","Screen"},{"E","Fookin nonsense","aha"},{"Hello","How are you","Mr Valentine"},{"Hey","I am good thank",":)"}}
btnW = 21
btnH = 5
scrl = 0
function setrender(scr) -- settings render, scroll (Y)
if scr == nil then
scr = 0
end
term.setBackgroundColor(colors.black)
term.clear()
local w,h = term.getSize()
term.setCursorPos(math.ceil(w/2)-math.floor(string.len("Settings")/2),2-scr)
term.setTextColor(colors.white)
term.write("Settings")
local cX = math.ceil(w/2)+1
local cY = 4
while cX-(btnW+1) > 1 do
cX = cX-(btnW+1)
end
local OGcX = cX
btns = {}
for t=1,#lSettings do
--term.setCursorPos(cX,cY-scr)
btn(cX,cY-scr,btnW,lSettings[t]).render()
if cX+(btnW*2+2) <= w then
cX = cX+(btnW+1)
else
cX = OGcX
cY = cY+btnH+1
end
end
end
setrender()
local aw,ah = term.getSize()
local ow,oh = aw,ah
while true do
e = {os.pullEvent()}
if e[1] == "mouse_scroll" then
scrl = scrl+e[2]
setrender(scrl)
elseif e[1] == "mouse_click" then
for t=1,#btns do
if e[3] >= btns[t].x and e[4] >= btns[t].y and e[3] <= btns[t].x+(btns[t].w-1) and e[4] <= btns[t].y+(btns[t].h-1) then
term.setCursorPos(1,1)
print("Yey")
term.setBackgroundColor(colors.gray)
btns[t].render(btns[t].x,btns[t].y)
end
end
elseif e[1] == "mouse_up" then
term.setBackgroundColor(colors.black)
setrender(scrl)
end
aw,ah = term.getSize()
if aw ~= ow or ah ~= oh then
setrender(scrl)
ow,oh = aw,ah
end
end
os.sleep(3)

176
LevelOS/startup/MwMRender Normal file
View File

@@ -0,0 +1,176 @@
if mwm == nil then _G.mwm = {} end
function tabletext(text)
local tTable = {}
for a=1,string.len(text) do
tTable[a] = string.sub(text,a,a)
end
return tTable
end
to_colors, to_blit = {}, {}
for i = 1, 16 do
to_blit[2^(i-1)] = ("0123456789abcdef"):sub(i, i)
to_colors[("0123456789abcdef"):sub(i, i)] = 2^(i-1)
end
function mwm.newCvs(tX,tY)
local cvs = {}
cvs.rCvs = {}
cvs.oCvs = {}
cvs.orCvs = {}
cvs.color = colors.white
if tX == nil or tY == nil then
tX,tY = term.getSize()
end
for x=1,tX do
cvs.rCvs[x] = {}
for y=1,tY do
cvs.rCvs[x][y] = {"",term.getBackgroundColor()} -- empty pixel = ""
end
end
cvs.width = tX
cvs.height = tY
local function genCvs()
cvs.rCvs = {}
local tX,tY = cvs.width,cvs.height
for x=1,tX do
cvs.rCvs[x] = {}
for y=1,tY do
cvs.rCvs[x][y] = {"",term.getBackgroundColor()} -- empty pixel = ""
end
end
end
function cvs.setColor(color)
cvs.color = color
end
function cvs.rect(x,y,w,h,text,txtcolor)
if tonumber(x) == nil or tonumber(y) == nil or tonumber(w) == nil or tonumber(h) == nil then
return
end
if text ~= nil then
if txtcolor == nil then
txtcolor = colors.white
end
if type(text) == "string" then
text = {text}
end
for t=1,#text do
if string.len(text[t]) > w then
string.sub(text[t],1,w)
end
end
end
cvs.oCvs[#cvs.oCvs+1] = {type="rect",x=x,y=y,width=w,height=h,color=cvs.color,txt=text,txtcolor=txtcolor,ref=#cvs.oCvs+1}
return cvs.oCvs[#cvs.oCvs],true
end
function cvs.print(text,x,y)
if text == nil or tonumber(x) == nil or tonumber(y) == nil then
return
end
cvs.oCvs[#cvs.oCvs+1] = {type="text",txt=text,x=x,y=y,color=cvs.color}
return cvs.oCvs[#cvs.oCvs],true
end
cvs.write = cvs.print
function cvs.sprite(file,x,y,w,h)
if fs.exists(file) == false then
return
end
opensprite = fs.open(file,"r")
local sprite = opensprite.readAll()
opensprite.close()
sprite = textutils.unserialize(sprite)
if sprite == nil then return end
cvs.oCvs[#cvs.oCvs+1] = {type="sprite",texture=sprite,x=x,y=y,width=w,height=h}
return cvs.oCvs[#cvs.oCvs]
end
-- Support circle rendering. This can be done by calculating with math.cos how many pixels it is from one side of one y coord to the other side of the same y coord and putting that in a string. repeat this for every y coord then draw
function cvs.clear()
cvs.oCvs = {}
end
function cvs.render(trans,x1,y1,x2,y2)
if x1 == nil then x1 = 1 end
if y1 == nil then y1 = 1 end
if x2 == nil then x2 = cvs.width end
if y2 == nil then y2 = cvs.height end
genCvs()
bgcolor = term.getBackgroundColor()
for a=1,#cvs.oCvs do
local o = cvs.oCvs[a]
cvs.oCvs[a].ref = a
o.x = math.floor(o.x+0.5)
o.y = math.floor(o.y+0.5)
if o.type == "rect" then
for b=1,o.height do
for c=1,o.width do
local tX,tY = term.getSize()
if o.x+(c-1) <= tX and o.y+(b-1) <= tY and o.x+(c-1) > 0 and o.y+(b-1) > 0 then
cvs.rCvs[o.x+(c-1)][o.y+(b-1)] = {" ",o.color}
end
end
end
if o.txt ~= nil and o.txtcolor ~= nil then
for b=1,o.height do
if o.txt[b] ~= nil then
dObj = tabletext(o.txt[b])
for c=1,string.len(o.txt[b]) do
cvs.rCvs[o.x+(c-1)][o.y+(b-1)] = {dObj[c],o.color,o.txtcolor}
end
end
end
end
elseif o.type == "sprite" then
for b=1,o.height do
for c=1,o.width do
if o.texture[c] ~= nil then
local tX,tY = term.getSize()
if o.x+(c-1) <= tX and o.y+(b-1) <= tY and o.x+(c-1) > 0 and o.y+(b-1) > 0 and o.texture[c][b] ~= nil then
cvs.rCvs[o.x+(c-1)][o.y+(b-1)] = o.texture[c][b]
end
end
end
end
elseif o.type == "text" then
dObj = tabletext(o.txt)
for b=1,#dObj do
local tX,tY = term.getSize()
if o.x+(b-1) <= tX and o.y <= tY and o.x+(b-1) > 0 and o.y > 0 then
cvs.rCvs[o.x+(b-1)][o.y][1] = dObj[b]
cvs.rCvs[o.x+(b-1)][o.y][3] = o.color
end
end
end
end
for y=y1,y2 do
bl1 = ""
bl2 = ""
bl3 = ""
for x=x1,x2 do
if not (cvs.orCvs[x] ~= nil and cvs.orCvs[x][y] == cvs.rCvs[x][y]) then
if cvs.rCvs[x][y][1] == "" then
if term.current().getLine and trans then
local theline = {term.current().getLine(y)}
bl1 = bl1..string.sub(theline[1],x,x)
bl2 = bl2..string.sub(theline[2],x,x)
bl3 = bl3..string.sub(theline[3],x,x)
else
bl1 = bl1.." "
bl2 = bl2..0
bl3 = bl3..to_blit[cvs.rCvs[x][y][2]]
end
else
if cvs.rCvs[x][y][3] ~= nil then
bl2 = bl2..to_blit[cvs.rCvs[x][y][3]]
else
bl2 = bl2..0
end
bl1 = bl1..tostring(cvs.rCvs[x][y][1])
bl3 = bl3..to_blit[cvs.rCvs[x][y][2]]
end
end
end
term.setCursorPos(x1,y)
term.blit(bl1,bl2,bl3)
end
cvs.orCvs = cvs.rCvs
term.setBackgroundColor(bgcolor)
end
return cvs
end

View File

@@ -4384,9 +4384,9 @@ function lUtils.openWin(title,filepath,x,y,width,height,canresize,canmaximize)
end
term.setTextColor(colors.white)
if canmaximize == false then
term.write(" × ")
term.write(" × ")
else
term.write(" + × ")
term.write(" + × ")
end
term.setCursorPos(x+1,y)
term.write(title)
@@ -4501,7 +4501,7 @@ function lUtils.openWin(title,filepath,x,y,width,height,canresize,canmaximize)
term.setTextColor(colors.white)
term.setBackgroundColor(colors.red)
term.setCursorPos(x+(width-3),y)
term.write(" × ")
term.write(" × ")
elseif e[1] == "mouse_up" then
stop = true
return false
@@ -4618,7 +4618,7 @@ function lUtils.popup(title,msg,width,height,buttons,redrawscreen,colorScheme)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
write(" "..title)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
write(" × ")
write(" × ")
-- The line below is unreadable now but it just makes the text box for the popup message and then prints it
term.setBackgroundColor(bg)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+1,math.ceil(h/2)-math.floor(height/2)+1)
@@ -4698,7 +4698,7 @@ function lUtils.popup(title,msg,width,height,buttons,redrawscreen,colorScheme)
term.setTextColor(colors.white)
term.setBackgroundColor(colors.red)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
write(" × ")
write(" × ")
elseif event == "mouse_up" then
if redrawscreen ~= nil and redrawscreen == true then
OGwin.render()
@@ -4721,7 +4721,7 @@ function lUtils.popup(title,msg,width,height,buttons,redrawscreen,colorScheme)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
write(" "..title)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
write(" × ")
write(" × ")
os.sleep(0.1)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
term.setBackgroundColor(tbbg)
@@ -4730,7 +4730,7 @@ function lUtils.popup(title,msg,width,height,buttons,redrawscreen,colorScheme)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
write(" "..title)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
write(" × ")
write(" × ")
os.sleep(0.1)
end
end
@@ -4772,7 +4772,7 @@ function lUtils.inputbox(title,msg,width,height,buttons)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
write(" "..title)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
write(" × ")
write(" × ")
-- The line below is unreadable now but it just makes the text box for the popup message and then prints it
term.setBackgroundColor(colors.white)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+1,math.ceil(h/2)-math.floor(height/2)+1)
@@ -4871,7 +4871,7 @@ function lUtils.inputbox(title,msg,width,height,buttons)
term.setTextColor(colors.white)
term.setBackgroundColor(colors.red)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
write(" × ")
write(" × ")
elseif event == "mouse_up" then
return false,0,""
end
@@ -4892,7 +4892,7 @@ function lUtils.inputbox(title,msg,width,height,buttons)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
write(" "..title)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
write(" × ")
write(" × ")
os.sleep(0.1)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
term.setBackgroundColor(colors.gray)
@@ -4901,7 +4901,7 @@ function lUtils.inputbox(title,msg,width,height,buttons)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
write(" "..title)
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
write(" × ")
write(" × ")
os.sleep(0.1)
end
end
@@ -5377,4 +5377,4 @@ function lUtils.isInside(x,y,object)
else
return false
end
end
end

1505
LevelOS/system.lua Normal file

File diff suppressed because it is too large Load Diff