v0.10.0 - Added text editor (which took me way too long) and too many other tweaks to name.
This commit is contained in:
+1
-1
@@ -24,6 +24,6 @@ else
|
|||||||
if fs.exists(directory) and fs.isDirectory(directory) or fs.exists(shell.workingDirectory .. directory) and fs.isDirectory(shell.workingDirectory .. directory) then
|
if fs.exists(directory) and fs.isDirectory(directory) or fs.exists(shell.workingDirectory .. directory) and fs.isDirectory(shell.workingDirectory .. directory) then
|
||||||
shell.workingDirectory = directory
|
shell.workingDirectory = directory
|
||||||
else
|
else
|
||||||
print("error: no such directory")
|
print("\27[91mNo such directory.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,321 @@
|
|||||||
|
local args = {...}
|
||||||
|
local file = args[1]
|
||||||
|
args = nil
|
||||||
|
local fs = import("filesystem")
|
||||||
|
local event = import("event")
|
||||||
|
local gpu = component.proxy(component.list("gpu")())
|
||||||
|
local width, height = gpu.getResolution()
|
||||||
|
local scrollPosX, scrollPosY = 1, 1
|
||||||
|
local cursorPosX, cursorPosY = 1, 1
|
||||||
|
local cursorWhite = true
|
||||||
|
local changesMade = false
|
||||||
|
local renderBuffer = gpu.allocateBuffer()
|
||||||
|
local scrollSpeed = 5
|
||||||
|
--local ocelot = component.proxy(component.list("ocelot")())
|
||||||
|
|
||||||
|
local function rawset(x, y, text)
|
||||||
|
termlib.cursorPosX = x
|
||||||
|
termlib.cursorPosY = y
|
||||||
|
print(text, false, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
local filestring, filepath, handle, data, tmpdata
|
||||||
|
if file then
|
||||||
|
if file:sub(1, 1) == "/" then
|
||||||
|
filepath = file
|
||||||
|
else
|
||||||
|
filepath = shell.workingDirectory .. file
|
||||||
|
end
|
||||||
|
handle, data, tmpdata = fs.open(filepath, "r"), "", nil
|
||||||
|
if fs.exists(filepath) then
|
||||||
|
filestring = filepath
|
||||||
|
repeat
|
||||||
|
tmpdata = handle:read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
tmpdata = {}
|
||||||
|
if data:gmatch("(.-)\n")() then
|
||||||
|
for line in data:gmatch("(.-)\n") do
|
||||||
|
local newLine = line:gsub("\r", "") -- this took me SO LONG TO FIGURE OUT AAAAAAAA I HATE CRLF I HATE CRLF I HATE CRLF
|
||||||
|
table.insert(tmpdata, newLine)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
tmpdata = {data}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
filepath = shell.workingDirectory .. file
|
||||||
|
filestring = "[NEW FILE]"
|
||||||
|
tmpdata = {""}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
filepath = ""
|
||||||
|
filestring = "[NEW FILE]"
|
||||||
|
tmpdata = {""}
|
||||||
|
end
|
||||||
|
local function render()
|
||||||
|
gpu.setActiveBuffer(renderBuffer)
|
||||||
|
clear()
|
||||||
|
local realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2)
|
||||||
|
if realCursorX < 1 then
|
||||||
|
scrollPosX = scrollPosX + realCursorX - 1
|
||||||
|
cursorPosX = 1
|
||||||
|
realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2)
|
||||||
|
end
|
||||||
|
for i = scrollPosY, height + scrollPosY - 3 do
|
||||||
|
rawset(1, i - scrollPosY + 1, (tmpdata[i] or ""):sub(scrollPosX))
|
||||||
|
end
|
||||||
|
rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width))
|
||||||
|
rawset(1, height, "\27[107m\27[30m^X\27[0m Exit \27[107m\27[30m^S\27[0m Save" .. string.rep(" ", width))
|
||||||
|
local char = gpu.get(realCursorX, cursorPosY)
|
||||||
|
if cursorWhite then
|
||||||
|
rawset(realCursorX, cursorPosY, "\27[107m\27[30m" .. char .. "\27[0m")
|
||||||
|
else
|
||||||
|
rawset(realCursorX, cursorPosY, char)
|
||||||
|
end
|
||||||
|
gpu.bitblt()
|
||||||
|
gpu.setActiveBuffer(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local renderFlag, cursorRenderFlag = false, false
|
||||||
|
|
||||||
|
local function scrollUp()
|
||||||
|
cursorPosY = cursorPosY - 1
|
||||||
|
cursorRenderFlag = true
|
||||||
|
cursorWhite = true
|
||||||
|
if cursorPosY < 1 then
|
||||||
|
renderFlag = true
|
||||||
|
scrollPosY = scrollPosY - 1
|
||||||
|
cursorPosY = 1
|
||||||
|
end
|
||||||
|
if scrollPosY < 1 then
|
||||||
|
renderFlag = false
|
||||||
|
scrollPosY = 1
|
||||||
|
end
|
||||||
|
if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2) < 1 then
|
||||||
|
renderFlag = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function scrollDown()
|
||||||
|
cursorPosY = cursorPosY + 1
|
||||||
|
cursorRenderFlag = true
|
||||||
|
cursorWhite = true
|
||||||
|
if cursorPosY + scrollPosY - 1 > #tmpdata then
|
||||||
|
renderFlag = false
|
||||||
|
cursorPosY = #tmpdata - scrollPosY + 1
|
||||||
|
end
|
||||||
|
if cursorPosY > height - 2 then
|
||||||
|
renderFlag = true
|
||||||
|
scrollPosY = scrollPosY + 1
|
||||||
|
cursorPosY = height - 2
|
||||||
|
end
|
||||||
|
if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2) < 1 then
|
||||||
|
renderFlag = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function scrollLeft()
|
||||||
|
cursorRenderFlag = true
|
||||||
|
cursorWhite = true
|
||||||
|
if cursorPosX > 1 then
|
||||||
|
if cursorPosX <= unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2 then
|
||||||
|
cursorPosX = cursorPosX - 1
|
||||||
|
elseif unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 1 > 1 then
|
||||||
|
cursorPosX = unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 1
|
||||||
|
end
|
||||||
|
elseif scrollPosX > 1 then
|
||||||
|
scrollPosX = scrollPosX - 1
|
||||||
|
renderFlag = true
|
||||||
|
end
|
||||||
|
if math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2) < 1 then
|
||||||
|
renderFlag = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function scrollRight()
|
||||||
|
cursorRenderFlag = true
|
||||||
|
cursorWhite = true
|
||||||
|
if cursorPosX <= unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 1 then
|
||||||
|
cursorPosX = cursorPosX + 1
|
||||||
|
end
|
||||||
|
if cursorPosX > width then
|
||||||
|
cursorPosX = width
|
||||||
|
scrollPosX = scrollPosX + 1
|
||||||
|
renderFlag = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function processEvent(args)
|
||||||
|
renderFlag, cursorRenderFlag = false, false
|
||||||
|
if args[1] == "key_down" then
|
||||||
|
local keycode = args[4]
|
||||||
|
local key = keyboard.keys[keycode]
|
||||||
|
if keyboard.ctrlDown then
|
||||||
|
return false, false, key
|
||||||
|
end
|
||||||
|
if key == "down" and cursorPosY < #tmpdata then
|
||||||
|
scrollDown()
|
||||||
|
end
|
||||||
|
if key == "up" then
|
||||||
|
scrollUp()
|
||||||
|
end
|
||||||
|
if key == "left" then
|
||||||
|
scrollLeft()
|
||||||
|
end
|
||||||
|
if key == "right" then
|
||||||
|
scrollRight()
|
||||||
|
end
|
||||||
|
if key == "enter" then
|
||||||
|
changesMade = true
|
||||||
|
renderFlag = true
|
||||||
|
cursorWhite = true
|
||||||
|
table.insert(tmpdata, cursorPosY + 1, tmpdata[cursorPosY]:sub(cursorPosX))
|
||||||
|
tmpdata[cursorPosY] = tmpdata[cursorPosY]:sub(1, cursorPosX - 1)
|
||||||
|
cursorPosX = 1
|
||||||
|
cursorPosY = cursorPosY + 1
|
||||||
|
scrollPosX = 1
|
||||||
|
if cursorPosY > height - 2 then
|
||||||
|
scrollPosY = scrollPosY + 1
|
||||||
|
cursorPosY = height - 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if key == "back" then
|
||||||
|
changesMade = true
|
||||||
|
cursorRenderFlag = true
|
||||||
|
cursorWhite = true
|
||||||
|
if cursorPosY + scrollPosY - 1 > 1 then
|
||||||
|
cursorPosY = cursorPosY - 1
|
||||||
|
if cursorPosY < 1 then
|
||||||
|
scrollPosY = scrollPosY - 1
|
||||||
|
cursorPosY = 1
|
||||||
|
end
|
||||||
|
if scrollPosY < 1 then
|
||||||
|
scrollPosY = 1
|
||||||
|
end
|
||||||
|
cursorPosX = unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2
|
||||||
|
if cursorPosX > width then
|
||||||
|
scrollPosX = cursorPosX - width + 1
|
||||||
|
cursorPosX = width
|
||||||
|
end
|
||||||
|
tmpdata[cursorPosY] = tmpdata[cursorPosY] .. tmpdata[cursorPosY + 1]
|
||||||
|
table.remove(tmpdata, cursorPosY + 1)
|
||||||
|
renderFlag = true
|
||||||
|
else
|
||||||
|
tmpdata[cursorPosY] = tmpdata[cursorPosY]:sub(1, cursorPosX + scrollPosX - 3) .. tmpdata[cursorPosY]:sub(cursorPosX + scrollPosX - 1)
|
||||||
|
cursorPosX = math.min(cursorPosX - 1, unicode.wlen(tmpdata[cursorPosY]) + 1)
|
||||||
|
if cursorPosX < 1 then
|
||||||
|
cursorPosX = 1
|
||||||
|
scrollPosX = scrollPosX - 1
|
||||||
|
renderFlag = true
|
||||||
|
else
|
||||||
|
rawset(1, cursorPosY - scrollPosY + 1, tmpdata[cursorPosY]:sub(scrollPosX) .. " ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if args[3] >= 32 and args[3] <= 126 then
|
||||||
|
changesMade = true
|
||||||
|
cursorRenderFlag = true
|
||||||
|
cursorWhite = true
|
||||||
|
tmpdata[cursorPosY] = tmpdata[cursorPosY]:sub(1, cursorPosX + scrollPosX - 2) .. unicode.char(args[3]) .. tmpdata[cursorPosY]:sub(cursorPosX + scrollPosX - 1)
|
||||||
|
cursorPosX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY])) + 1
|
||||||
|
--ocelot.log(tostring(cursorPosX))
|
||||||
|
if cursorPosX > width then
|
||||||
|
cursorPosX = width
|
||||||
|
scrollPosX = scrollPosX + 1
|
||||||
|
renderFlag = true
|
||||||
|
else
|
||||||
|
rawset(1, cursorPosY - scrollPosY + 1, tmpdata[cursorPosY]:sub(scrollPosX))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif args[1] == "scroll" then
|
||||||
|
if args[5] == 1 then
|
||||||
|
for i = 1, scrollSpeed do
|
||||||
|
scrollUp()
|
||||||
|
end
|
||||||
|
elseif args[5] == -1 and cursorPosY < #tmpdata then
|
||||||
|
for i = 1, scrollSpeed do
|
||||||
|
scrollDown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return renderFlag, cursorRenderFlag
|
||||||
|
end
|
||||||
|
|
||||||
|
local function save()
|
||||||
|
rawset(1, height - 1, "\27[107m\27[30m" .. string.rep(" ", width))
|
||||||
|
termlib.cursorPosX = 1
|
||||||
|
termlib.cursorPosY = height - 1
|
||||||
|
local savepath = read(nil, "\27[107m\27[30mSave location: ", filepath)
|
||||||
|
if fs.exists(savepath) then
|
||||||
|
rawset(1, height - 1, "\27[107m\27[30m" .. string.rep(" ", width))
|
||||||
|
local answer = read(nil, "\27[107m\27[30mFile already exists. Overwrite it? [Y/n] ")
|
||||||
|
if answer:lower() == "n" then
|
||||||
|
rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local handle, errorMessage = fs.open(savepath, "w")
|
||||||
|
if handle then
|
||||||
|
handle:write(table.concat(tmpdata, "\n"))
|
||||||
|
handle:close()
|
||||||
|
rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width))
|
||||||
|
else
|
||||||
|
rawset(1, height - 1, "\27[107m\27[30mERROR: " .. errorMessage:gsub("\n", "") .. string.rep(" ", width))
|
||||||
|
end
|
||||||
|
changesMade = false
|
||||||
|
end
|
||||||
|
|
||||||
|
render()
|
||||||
|
while true do
|
||||||
|
local args = {event.pull(0.5)}
|
||||||
|
local renderFlag, cursorRenderFlag, specialKey = false, false, nil
|
||||||
|
local previousCursorX, previousCursorY = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2), cursorPosY
|
||||||
|
if args and args[1] then
|
||||||
|
cursorWhite = true
|
||||||
|
renderFlag, cursorRenderFlag, specialKey = processEvent(args)
|
||||||
|
if specialKey == "x" then
|
||||||
|
if changesMade then
|
||||||
|
termlib.cursorPosX = 1
|
||||||
|
termlib.cursorPosY = height - 1
|
||||||
|
local response = read(nil, "\27[107m\27[30mWould you like to save changes? [Y/n] ")
|
||||||
|
if response:lower() ~= "n" then
|
||||||
|
save()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
gpu.freeAllBuffers()
|
||||||
|
clear()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if specialKey == "s" then
|
||||||
|
save()
|
||||||
|
end
|
||||||
|
repeat
|
||||||
|
args = {event.pull("key_down", 0)}
|
||||||
|
if args and args[1] then
|
||||||
|
processEvent(args)
|
||||||
|
end
|
||||||
|
until not args or not args[1]
|
||||||
|
else
|
||||||
|
cursorWhite = not cursorWhite
|
||||||
|
cursorRenderFlag = true
|
||||||
|
end
|
||||||
|
if cursorRenderFlag then
|
||||||
|
local char = gpu.get(previousCursorX, previousCursorY)
|
||||||
|
rawset(previousCursorX, previousCursorY, char)
|
||||||
|
local realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2)
|
||||||
|
if realCursorX < 1 then
|
||||||
|
scrollPosX = scrollPosX + realCursorX - 1
|
||||||
|
cursorPosX = 1
|
||||||
|
realCursorX = math.min(cursorPosX, unicode.wlen(tmpdata[cursorPosY]) - scrollPosX + 2)
|
||||||
|
end
|
||||||
|
local char = gpu.get(realCursorX, cursorPosY)
|
||||||
|
if cursorWhite then
|
||||||
|
rawset(realCursorX, cursorPosY, "\27[107m\27[30m" .. char .. "\27[0m")
|
||||||
|
else
|
||||||
|
rawset(realCursorX, cursorPosY, char)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if renderFlag then
|
||||||
|
render()
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -21,6 +21,18 @@ if fs.exists("/halyde/apps/helpdb/" .. command .. ".txt") then
|
|||||||
data = data .. (tmpdata or "")
|
data = data .. (tmpdata or "")
|
||||||
until not tmpdata
|
until not tmpdata
|
||||||
print(data)
|
print(data)
|
||||||
|
local aliases = table.copy(shell.aliases)
|
||||||
|
if table.find(aliases, command) then
|
||||||
|
local aliasIndex = table.find(aliases, command)
|
||||||
|
local aliasString = "Aliases:\n " .. aliasIndex
|
||||||
|
aliases[aliasIndex] = nil
|
||||||
|
while table.find(aliases, command) do
|
||||||
|
aliasIndex = table.find(aliases, command)
|
||||||
|
aliasString = aliasString .. ", " .. aliasIndex
|
||||||
|
aliases[aliasIndex] = nil
|
||||||
|
end
|
||||||
|
print(aliasString)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
print("Could not find help file for: " .. command .. ".")
|
print("Could not find help file for: " .. command .. ".")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ Usage: cp [FLAGS] [SOURCE] [DESTINATION]
|
|||||||
Copies a file.
|
Copies a file.
|
||||||
|
|
||||||
-o, --overwrite Allows any file that might be at the destination to be overwritten.
|
-o, --overwrite Allows any file that might be at the destination to be overwritten.
|
||||||
SOURCE Specifies the file to be copied.
|
SOURCE Specifies the file to be copied.
|
||||||
DESTINATION Specifies the path to copy the file to.
|
DESTINATION Specifies the path to copy the file to.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
cp /home/a.txt /b.txt Copies the file at /home/a.txt to /b.txt.
|
cp /home/a.txt /b.txt Copies the file at /home/a.txt to /b.txt.
|
||||||
|
|||||||
@@ -13,3 +13,6 @@ All current Halyde shell commands:
|
|||||||
|
|
||||||
You can get additional information on any app or command by running:
|
You can get additional information on any app or command by running:
|
||||||
help [COMMAND]
|
help [COMMAND]
|
||||||
|
|
||||||
|
In the help documentation, an asterisk (*) next to an argument means it is optional.
|
||||||
|
This is excluding flags, which are all optional.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Usage: help [COMMAND]
|
Usage: help [COMMAND]
|
||||||
Displays info on the command specified, or a list of commands if one is not specified.
|
Displays info on the command specified, or a list of commands if one is not specified.
|
||||||
|
|
||||||
COMMAND Command to display information on.
|
COMMAND* Command to display information on.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
help Displays a list of all default commands available.
|
help Displays a list of all default commands available.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Usage: ls [PATH]
|
|||||||
Lists all files and directories in the specified path, or in the shell working directory if the path isn't specified.
|
Lists all files and directories in the specified path, or in the shell working directory if the path isn't specified.
|
||||||
Directories are shown in [93myellow[0m, executable files are shown in [92mgreen[0m, and other files are shown in white.
|
Directories are shown in [93myellow[0m, executable files are shown in [92mgreen[0m, and other files are shown in white.
|
||||||
|
|
||||||
PATH Path to the folder to list files and directories from.
|
PATH* Path to the folder to list files and directories from.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
ls Lists all files and directories from the current shell working directory.
|
ls Lists all files and directories from the current shell working directory.
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ Removes files and directories.
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
rm a.txt Removes a.txt in the current shell working directory.
|
rm a.txt Removes a.txt in the current shell working directory.
|
||||||
rm -r -f /halyde/core/ Removes everything in /halyde/core forcedly and recursively. Note that trying this on a real machine will remove critical Halyde system files and cause it to stop working.
|
rm -r -f /halyde/core/ Removes everything in /halyde/core/ forcedly and recursively.
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
local raster = import("raster")
|
||||||
|
local event = import("event")
|
||||||
|
|
||||||
|
-- Initialize the 3D renderer for a spinning cube
|
||||||
|
-- Using the raster library for drawing
|
||||||
|
|
||||||
|
-- Screen dimensions
|
||||||
|
local SCREEN_WIDTH, SCREEN_HEIGHT = component.invoke(component.list("gpu")(), "getResolution")
|
||||||
|
SCREEN_WIDTH, SCREEN_HEIGHT = SCREEN_WIDTH * 2, SCREEN_HEIGHT * 4
|
||||||
|
local CENTER_X = SCREEN_WIDTH / 2
|
||||||
|
local CENTER_Y = SCREEN_HEIGHT / 2
|
||||||
|
|
||||||
|
-- Cube properties
|
||||||
|
local CUBE_SIZE = 10
|
||||||
|
local increment = 0
|
||||||
|
local WHITE = 0xFFFFFF
|
||||||
|
local ROTATION_SPEED = 0.1
|
||||||
|
|
||||||
|
-- 3D cube vertices (centered at origin)
|
||||||
|
local vertices = {
|
||||||
|
{-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 0: left bottom back
|
||||||
|
{CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 1: right bottom back
|
||||||
|
{CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 2: right top back
|
||||||
|
{-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 3: left top back
|
||||||
|
{-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 4: left bottom front
|
||||||
|
{CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 5: right bottom front
|
||||||
|
{CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, -- 6: right top front
|
||||||
|
{-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} -- 7: left top front
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Cube edges defined by vertex indices
|
||||||
|
local edges = {
|
||||||
|
{0, 1}, {1, 2}, {2, 3}, {3, 0}, -- back face
|
||||||
|
{4, 5}, {5, 6}, {6, 7}, {7, 4}, -- front face
|
||||||
|
{0, 4}, {1, 5}, {2, 6}, {3, 7} -- connecting edges
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Projection parameters
|
||||||
|
local FOV = 256 -- Field of view (distance from camera to screen)
|
||||||
|
local Z_OFFSET = 300 -- Distance from camera to cube center
|
||||||
|
|
||||||
|
-- Initialize rotation angles
|
||||||
|
local angleX, angleY, angleZ = 0, 0, 0
|
||||||
|
|
||||||
|
-- Matrix multiplication function (apply rotation to a 3D point)
|
||||||
|
local function rotatePoint(x, y, z)
|
||||||
|
-- Rotation around X axis
|
||||||
|
local cosX, sinX = math.cos(angleX), math.sin(angleX)
|
||||||
|
local y1 = y * cosX - z * sinX
|
||||||
|
local z1 = y * sinX + z * cosX
|
||||||
|
|
||||||
|
-- Rotation around Y axis
|
||||||
|
local cosY, sinY = math.cos(angleY), math.sin(angleY)
|
||||||
|
local x1 = x * cosY + z1 * sinY
|
||||||
|
local z2 = -x * sinY + z1 * cosY
|
||||||
|
|
||||||
|
-- Rotation around Z axis
|
||||||
|
local cosZ, sinZ = math.cos(angleZ), math.sin(angleZ)
|
||||||
|
local x2 = x1 * cosZ - y1 * sinZ
|
||||||
|
local y2 = x1 * sinZ + y1 * cosZ
|
||||||
|
|
||||||
|
return x2, y2, z2
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Perspective projection function (3D to 2D)
|
||||||
|
local function projectPoint(x, y, z)
|
||||||
|
-- Apply perspective projection
|
||||||
|
local scale = FOV / (z + Z_OFFSET)
|
||||||
|
local x2d = x * scale + CENTER_X
|
||||||
|
local y2d = y * scale + CENTER_Y
|
||||||
|
|
||||||
|
return x2d, y2d
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Render a single frame
|
||||||
|
local function renderFrame()
|
||||||
|
increment = increment + 0.05
|
||||||
|
CUBE_SIZE = (math.sin(increment) + 1) * 25
|
||||||
|
vertices = {
|
||||||
|
{-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 0: left bottom back
|
||||||
|
{CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, -- 1: right bottom back
|
||||||
|
{CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 2: right top back
|
||||||
|
{-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, -- 3: left top back
|
||||||
|
{-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 4: left bottom front
|
||||||
|
{CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, -- 5: right bottom front
|
||||||
|
{CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, -- 6: right top front
|
||||||
|
{-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} -- 7: left top front
|
||||||
|
}
|
||||||
|
-- Update rotation angles
|
||||||
|
raster.clear()
|
||||||
|
angleX = angleX + ROTATION_SPEED
|
||||||
|
angleY = angleY + ROTATION_SPEED * 0.7
|
||||||
|
angleZ = angleZ + ROTATION_SPEED * 0.5
|
||||||
|
|
||||||
|
-- Project all vertices
|
||||||
|
local projectedPoints = {}
|
||||||
|
for i, vertex in ipairs(vertices) do
|
||||||
|
-- Rotate the point
|
||||||
|
local x, y, z = rotatePoint(vertex[1], vertex[2], vertex[3])
|
||||||
|
|
||||||
|
-- Project the point to 2D
|
||||||
|
local x2d, y2d = projectPoint(x, y, z)
|
||||||
|
projectedPoints[i] = {x2d, y2d}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Draw all edges
|
||||||
|
for _, edge in ipairs(edges) do
|
||||||
|
local p1 = projectedPoints[edge[1] + 1] -- +1 because Lua indices start at 1
|
||||||
|
local p2 = projectedPoints[edge[2] + 1]
|
||||||
|
|
||||||
|
-- Draw the line
|
||||||
|
raster.drawLine(p1[1], p1[2], p2[1], p2[2], WHITE)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Render the frame
|
||||||
|
raster.update()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Main program
|
||||||
|
function main()
|
||||||
|
-- Initialize raster engine
|
||||||
|
raster.init()
|
||||||
|
|
||||||
|
-- Main loop (assume this is called repeatedly by the host environment)
|
||||||
|
while true do
|
||||||
|
renderFrame()
|
||||||
|
if event.pull("key_down", 0) then
|
||||||
|
raster.free()
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Return a reference to renderFrame so it can be called for animation
|
||||||
|
return renderFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Start the program
|
||||||
|
return main()
|
||||||
@@ -9,8 +9,11 @@ local shellcfg = {
|
|||||||
["rename"] = "mv",
|
["rename"] = "mv",
|
||||||
["ren"] = "mv",
|
["ren"] = "mv",
|
||||||
["dir"] = "ls",
|
["dir"] = "ls",
|
||||||
|
["list"] = "ls",
|
||||||
["man"] = "help",
|
["man"] = "help",
|
||||||
["del"] = "rm",
|
["del"] = "rm",
|
||||||
|
["delete"] = "rm",
|
||||||
|
["remove"] = "rm",
|
||||||
[".."] = "cd .."
|
[".."] = "cd .."
|
||||||
}, ["defaultWorkingDirectory"] = "/home/" -- the working directory that gets set when halyde starts
|
}, ["defaultWorkingDirectory"] = "/home/" -- the working directory that gets set when halyde starts
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local loadfile = ...
|
local loadfile = ...
|
||||||
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
|
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
|
||||||
|
|
||||||
_G._OSVERSION = "Halyde 0.9.0"
|
_G._OSVERSION = "Halyde 0.10.0"
|
||||||
|
|
||||||
function _G.import(module, ...)
|
function _G.import(module, ...)
|
||||||
local args = table.pack(...)
|
local args = table.pack(...)
|
||||||
|
|||||||
+30
-11
@@ -4,10 +4,25 @@ _G.cormgr.corList = {}
|
|||||||
--local ocelot = component.proxy(component.list("ocelot")())
|
--local ocelot = component.proxy(component.list("ocelot")())
|
||||||
|
|
||||||
local filesystem = import("filesystem")
|
local filesystem = import("filesystem")
|
||||||
|
local gpu = component.proxy(component.list("gpu")())
|
||||||
|
|
||||||
function _G.cormgr.loadCoroutine(path)
|
function _G.cormgr.loadCoroutine(path, ...)
|
||||||
|
local args = {...}
|
||||||
local cor = coroutine.create(function()
|
local cor = coroutine.create(function()
|
||||||
import(path)
|
local result, errorMessage = xpcall(function(...)
|
||||||
|
import(...)
|
||||||
|
end, function(errorMessage)
|
||||||
|
return errorMessage .. "\n \n" .. debug.traceback()
|
||||||
|
end, path, table.unpack(args))
|
||||||
|
if not result then
|
||||||
|
if print then
|
||||||
|
gpu.freeAllBuffers()
|
||||||
|
print("\n\27[91m" .. errorMessage)
|
||||||
|
else
|
||||||
|
error(errorMessage)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--import(path, table.unpack(args))
|
||||||
end)
|
end)
|
||||||
table.insert(_G.cormgr.corList, cor)
|
table.insert(_G.cormgr.corList, cor)
|
||||||
end
|
end
|
||||||
@@ -22,16 +37,20 @@ end
|
|||||||
|
|
||||||
local function runCoroutines()
|
local function runCoroutines()
|
||||||
for i = 1, #_G.cormgr.corList do
|
for i = 1, #_G.cormgr.corList do
|
||||||
local result, errorMessage = coroutine.resume(_G.cormgr.corList[i])
|
if cormgr.corList[i] then
|
||||||
if not result then
|
local result, errorMessage = coroutine.resume(cormgr.corList[i])
|
||||||
handleError(errorMessage)
|
if cormgr.corList[i] then
|
||||||
|
if not result then
|
||||||
|
handleError(errorMessage)
|
||||||
|
end
|
||||||
|
if coroutine.status(cormgr.corList[i]) == "dead" then
|
||||||
|
table.remove(cormgr.corList, i)
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
--computer.pullSignal(0)
|
||||||
|
--coroutine.yield()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if coroutine.status(_G.cormgr.corList[i]) == "dead" then
|
|
||||||
table.remove(_G.cormgr.corList, i)
|
|
||||||
i = i - 1
|
|
||||||
end
|
|
||||||
--computer.pullSignal(0)
|
|
||||||
--coroutine.yield()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+28
-1
@@ -2,6 +2,9 @@ _G.evmgr = {}
|
|||||||
_G.evmgr.eventQueue = {}
|
_G.evmgr.eventQueue = {}
|
||||||
local maxEventQueueLength = 10 -- increase if events start getting dropped
|
local maxEventQueueLength = 10 -- increase if events start getting dropped
|
||||||
|
|
||||||
|
keyboard.ctrlDown = false
|
||||||
|
keyboard.altDown = false
|
||||||
|
|
||||||
--local ocelot = component.proxy(component.list("ocelot")())
|
--local ocelot = component.proxy(component.list("ocelot")())
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
@@ -11,6 +14,30 @@ while true do
|
|||||||
if args and args[1] then
|
if args and args[1] then
|
||||||
--ocelot.log("Sending signal "..args..","..computer.uptime())
|
--ocelot.log("Sending signal "..args..","..computer.uptime())
|
||||||
table.insert(evmgr.eventQueue, args)
|
table.insert(evmgr.eventQueue, args)
|
||||||
|
if keyboard then
|
||||||
|
if args[1] == "key_down" then
|
||||||
|
local keycode = args[4]
|
||||||
|
local key = keyboard.keys[keycode]
|
||||||
|
if key == "lcontrol" then
|
||||||
|
keyboard.ctrlDown = true
|
||||||
|
elseif key == "lmenu" then
|
||||||
|
keyboard.altDown = true
|
||||||
|
elseif key == "c" and keyboard.ctrlDown and keyboard.altDown then
|
||||||
|
if print then
|
||||||
|
print("\n\27[91mCoroutine "..tostring(#cormgr.corList).." killed.")
|
||||||
|
end
|
||||||
|
cormgr.corList[#cormgr.corList] = nil
|
||||||
|
end
|
||||||
|
elseif args[1] == "key_up" then
|
||||||
|
local keycode = args[4]
|
||||||
|
local key = keyboard.keys[keycode]
|
||||||
|
if key == "lcontrol" then
|
||||||
|
keyboard.ctrlDown = false
|
||||||
|
elseif key == "lmenu" then
|
||||||
|
keyboard.altDown = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
while #evmgr.eventQueue > maxEventQueueLength do
|
while #evmgr.eventQueue > maxEventQueueLength do
|
||||||
--ocelot.log("Queue length breach, removing first signal")
|
--ocelot.log("Queue length breach, removing first signal")
|
||||||
table.remove(evmgr.eventQueue, 1)
|
table.remove(evmgr.eventQueue, 1)
|
||||||
@@ -19,4 +46,4 @@ while true do
|
|||||||
until not args or not args[1]
|
until not args or not args[1]
|
||||||
--ocelot.log("done")
|
--ocelot.log("done")
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
_G.keyboard = {pressedChars = {}, pressedCodes = {}}
|
_G.keyboard = {["keys"] = {}}
|
||||||
_G.keyboard.keys = {}
|
|
||||||
|
|
||||||
keyboard.keys["1"] = 0x02
|
keyboard.keys["1"] = 0x02
|
||||||
keyboard.keys["2"] = 0x03
|
keyboard.keys["2"] = 0x03
|
||||||
@@ -141,4 +140,4 @@ setmetatable(keyboard.keys,
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|||||||
+17
-13
@@ -3,11 +3,22 @@ import("/halyde/core/termlib.lua")
|
|||||||
local event = import("event")
|
local event = import("event")
|
||||||
--local ocelot = component.proxy(component.list("ocelot")())
|
--local ocelot = component.proxy(component.list("ocelot")())
|
||||||
local filesystem = import("filesystem")
|
local filesystem = import("filesystem")
|
||||||
|
local gpu = component.proxy(component.list("gpu")())
|
||||||
|
|
||||||
_G.shell = {}
|
_G.shell = {}
|
||||||
_G.shell.workingDirectory = shellcfg["defaultWorkingDirectory"]
|
_G.shell.workingDirectory = shellcfg["defaultWorkingDirectory"]
|
||||||
_G.shell.aliases = shellcfg["aliases"]
|
_G.shell.aliases = shellcfg["aliases"]
|
||||||
|
|
||||||
|
local function runAsCoroutine(path, ...)
|
||||||
|
--ocelot.log("running " .. path .. " as coroutine")
|
||||||
|
cormgr.loadCoroutine(path, ...)
|
||||||
|
local corIndex = #cormgr.corList
|
||||||
|
local cor = cormgr.corList[#cormgr.corList]
|
||||||
|
repeat
|
||||||
|
coroutine.yield()
|
||||||
|
until cormgr.corList[corIndex] ~= cor
|
||||||
|
end
|
||||||
|
|
||||||
function _G.shell.run(command)
|
function _G.shell.run(command)
|
||||||
checkArg(1, command, "string")
|
checkArg(1, command, "string")
|
||||||
if shell.aliases[command:match("[^ ]+")] then
|
if shell.aliases[command:match("[^ ]+")] then
|
||||||
@@ -48,14 +59,14 @@ function _G.shell.run(command)
|
|||||||
foundfile = true
|
foundfile = true
|
||||||
local path = args[1]
|
local path = args[1]
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
import(path, table.unpack(args))
|
runAsCoroutine(path, table.unpack(args))
|
||||||
else
|
else
|
||||||
for _, item in pairs(shellcfg["path"]) do
|
for _, item in pairs(shellcfg["path"]) do
|
||||||
if filesystem.exists(item..args[1]) then
|
if filesystem.exists(item..args[1]) then
|
||||||
foundfile = true
|
foundfile = true
|
||||||
local path = item..args[1]
|
local path = item..args[1]
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
import(path, table.unpack(args))
|
runAsCoroutine(path, table.unpack(args))
|
||||||
break
|
break
|
||||||
else -- try to look for it without the file extension
|
else -- try to look for it without the file extension
|
||||||
local files = filesystem.list(item)
|
local files = filesystem.list(item)
|
||||||
@@ -63,15 +74,7 @@ function _G.shell.run(command)
|
|||||||
if args[1] == file:match("(.+)%.[^%.]+$") then
|
if args[1] == file:match("(.+)%.[^%.]+$") then
|
||||||
foundfile = true
|
foundfile = true
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
local function runCommand()
|
runAsCoroutine(item..file, table.unpack(args))
|
||||||
import(item..file, table.unpack(args))
|
|
||||||
end
|
|
||||||
local result, reason = xpcall(runCommand, function(errMsg)
|
|
||||||
return errMsg .. "\n\n" .. debug.traceback()
|
|
||||||
end)
|
|
||||||
if not result then
|
|
||||||
print("\27[91m" .. reason)
|
|
||||||
end
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -87,9 +90,10 @@ print(shellcfg["startupMessage"])
|
|||||||
while true do
|
while true do
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
-- print(shell.workingDirectory .. " >")
|
-- print(shell.workingDirectory .. " >")
|
||||||
print(shellcfg["prompt"]:format(shell.workingDirectory),false)
|
--print(shellcfg["prompt"]:format(shell.workingDirectory),false)
|
||||||
-- termlib.cursorPosX = #(shell.workingDirectory .. " > ")
|
-- termlib.cursorPosX = #(shell.workingDirectory .. " > ")
|
||||||
-- termlib.cursorPosY = termlib.cursorPosY - 1
|
-- termlib.cursorPosY = termlib.cursorPosY - 1
|
||||||
local shellCommand = read("shell")
|
local shellCommand = read("shell", shellcfg["prompt"]:format(shell.workingDirectory))
|
||||||
shell.run(shellCommand)
|
shell.run(shellCommand)
|
||||||
|
gpu.freeAllBuffers()
|
||||||
end
|
end
|
||||||
|
|||||||
+43
-32
@@ -1,6 +1,7 @@
|
|||||||
local event = import("event")
|
local event = import("event")
|
||||||
--local keyboard = import("keyboard")
|
--local keyboard = import("keyboard")
|
||||||
|
|
||||||
|
--local ocelot = component.proxy(component.list("ocelot")())
|
||||||
local gpu = component.proxy(component.list("gpu")()) -- replace with component.gpu once implemented
|
local gpu = component.proxy(component.list("gpu")()) -- replace with component.gpu once implemented
|
||||||
_G.termlib = {}
|
_G.termlib = {}
|
||||||
termlib.cursorPosX = 1
|
termlib.cursorPosX = 1
|
||||||
@@ -41,7 +42,7 @@ gpu.setForeground(defaultForegroundColor)
|
|||||||
gpu.setBackground(defaultBackgroundColor)
|
gpu.setBackground(defaultBackgroundColor)
|
||||||
|
|
||||||
local function scrollDown()
|
local function scrollDown()
|
||||||
if gpu.copy(0,1,width,height,0,-1) then
|
if gpu.copy(1,1,width,height,0,-1) then
|
||||||
local prevForeground = gpu.getForeground()
|
local prevForeground = gpu.getForeground()
|
||||||
local prevBackground = gpu.getBackground()
|
local prevBackground = gpu.getBackground()
|
||||||
gpu.setForeground(defaultForegroundColor)
|
gpu.setForeground(defaultForegroundColor)
|
||||||
@@ -61,7 +62,7 @@ local function newLine()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function parseCodeNumbers(code)
|
local function parseCodeNumbers(code)
|
||||||
o = {}
|
o = {}
|
||||||
for num in code:sub(3,-2):gmatch("[^;]+") do
|
for num in code:sub(3,-2):gmatch("[^;]+") do
|
||||||
table.insert(o,tonumber(num))
|
table.insert(o,tonumber(num))
|
||||||
@@ -69,13 +70,16 @@ function parseCodeNumbers(code)
|
|||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function _G.print(text,endNewLine)
|
function _G.print(text, endNewLine, wordWrap)
|
||||||
|
|
||||||
-- you don't know how tiring this was just for ANSI escape code support
|
-- you don't know how tiring this was just for ANSI escape code support
|
||||||
|
|
||||||
if endNewLine==nil then
|
if endNewLine == nil then
|
||||||
endNewLine = true
|
endNewLine = true
|
||||||
end
|
end
|
||||||
|
if wordWrap == nil then
|
||||||
|
wordWrap = true
|
||||||
|
end
|
||||||
|
|
||||||
if not text or not tostring(text) then
|
if not text or not tostring(text) then
|
||||||
return
|
return
|
||||||
@@ -93,7 +97,7 @@ function _G.print(text,endNewLine)
|
|||||||
end
|
end
|
||||||
gpu.set(termlib.cursorPosX,termlib.cursorPosY,section)
|
gpu.set(termlib.cursorPosX,termlib.cursorPosY,section)
|
||||||
termlib.cursorPosX = termlib.cursorPosX+unicode.wlen(section)
|
termlib.cursorPosX = termlib.cursorPosX+unicode.wlen(section)
|
||||||
if termlib.cursorPosX>width then
|
if termlib.cursorPosX>width and wordWrap then
|
||||||
newLine()
|
newLine()
|
||||||
end
|
end
|
||||||
section=""
|
section=""
|
||||||
@@ -162,13 +166,18 @@ end
|
|||||||
|
|
||||||
function _G.clear()
|
function _G.clear()
|
||||||
local xRes, yRes = gpu.getResolution()
|
local xRes, yRes = gpu.getResolution()
|
||||||
|
gpu.setForeground(defaultForegroundColor)
|
||||||
|
gpu.setBackground(defaultBackgroundColor)
|
||||||
gpu.fill(1,1,xRes,yRes," ")
|
gpu.fill(1,1,xRes,yRes," ")
|
||||||
termlib.cursorPosX, termlib.cursorPosY = 1, 1
|
termlib.cursorPosX, termlib.cursorPosY = 1, 1
|
||||||
end
|
end
|
||||||
|
|
||||||
function _G.read(readHistoryType)
|
function _G.read(readHistoryType, prefix, defaultText)
|
||||||
checkArg(1, readHistoryType, "string", "nil")
|
checkArg(1, readHistoryType, "string", "nil")
|
||||||
local curtext = ""
|
checkArg(2, prefix, "string", "nil")
|
||||||
|
checkArg(3, defaultText, "string", "nil")
|
||||||
|
local curtext = defaultText or ""
|
||||||
|
local prefix = prefix or ""
|
||||||
local RHIndex
|
local RHIndex
|
||||||
if readHistoryType then
|
if readHistoryType then
|
||||||
if not termlib.readHistory[readHistoryType] then
|
if not termlib.readHistory[readHistoryType] then
|
||||||
@@ -179,13 +188,10 @@ function _G.read(readHistoryType)
|
|||||||
RHIndex = #termlib.readHistory[readHistoryType] -- read history index
|
RHIndex = #termlib.readHistory[readHistoryType] -- read history index
|
||||||
end
|
end
|
||||||
local cursorPosX, cursorPosY = termlib.cursorPosX, termlib.cursorPosY
|
local cursorPosX, cursorPosY = termlib.cursorPosX, termlib.cursorPosY
|
||||||
|
print(prefix .. curtext .. "\27[107m ", false)
|
||||||
local cursorWhite = true
|
local cursorWhite = true
|
||||||
while true do
|
while true do
|
||||||
if cursorWhite then
|
--ocelot.log(curtext)
|
||||||
print("\27[107m ", false)
|
|
||||||
else
|
|
||||||
print(" ", false)
|
|
||||||
end
|
|
||||||
termlib.cursorPosX = termlib.cursorPosX - 1
|
termlib.cursorPosX = termlib.cursorPosX - 1
|
||||||
local args = {event.pull("key_down", 0.5)}
|
local args = {event.pull("key_down", 0.5)}
|
||||||
if args[4] then
|
if args[4] then
|
||||||
@@ -194,51 +200,56 @@ function _G.read(readHistoryType)
|
|||||||
local key = keyboard.keys[keycode]
|
local key = keyboard.keys[keycode]
|
||||||
if key == "up" and readHistoryType then
|
if key == "up" and readHistoryType then
|
||||||
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
||||||
print(curtext .. " ", false)
|
print(prefix .. curtext .. " ", false)
|
||||||
RHIndex = RHIndex - 1
|
RHIndex = RHIndex - 1
|
||||||
if RHIndex <= 0 then
|
if RHIndex <= 0 then
|
||||||
RHIndex = 1
|
RHIndex = 1
|
||||||
end
|
end
|
||||||
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
||||||
print(termlib.readHistory[readHistoryType][RHIndex] .. string.rep(" ", unicode.wlen(curtext) - unicode.wlen(termlib.readHistory[readHistoryType][RHIndex])), false)
|
print(prefix .. termlib.readHistory[readHistoryType][RHIndex] .. string.rep(" ", unicode.wlen(curtext) - unicode.wlen(termlib.readHistory[readHistoryType][RHIndex])), false)
|
||||||
curtext = termlib.readHistory[readHistoryType][RHIndex]
|
curtext = termlib.readHistory[readHistoryType][RHIndex]
|
||||||
end
|
end
|
||||||
if key == "down" and readHistoryType then
|
if key == "down" and readHistoryType then
|
||||||
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
||||||
print(curtext .. " ", false)
|
print(prefix .. curtext .. " ", false)
|
||||||
RHIndex = RHIndex + 1
|
RHIndex = RHIndex + 1
|
||||||
if RHIndex > #termlib.readHistory[readHistoryType] then
|
if RHIndex > #termlib.readHistory[readHistoryType] then
|
||||||
RHIndex = #termlib.readHistory[readHistoryType]
|
RHIndex = #termlib.readHistory[readHistoryType]
|
||||||
end
|
end
|
||||||
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
||||||
print(termlib.readHistory[readHistoryType][RHIndex] .. string.rep(" ", unicode.wlen(curtext) - unicode.wlen(termlib.readHistory[readHistoryType][RHIndex])), false)
|
print(prefix .. termlib.readHistory[readHistoryType][RHIndex] .. string.rep(" ", unicode.wlen(curtext) - unicode.wlen(termlib.readHistory[readHistoryType][RHIndex])), false)
|
||||||
curtext = termlib.readHistory[readHistoryType][RHIndex]
|
curtext = termlib.readHistory[readHistoryType][RHIndex]
|
||||||
end
|
end
|
||||||
|
if key == "back" then
|
||||||
|
curtext = curtext:sub(1, #curtext-1)
|
||||||
|
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
||||||
|
print(prefix .. curtext.." ", false)
|
||||||
|
end
|
||||||
|
if key == "enter" then
|
||||||
|
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
||||||
|
print(prefix .. curtext .. " ")
|
||||||
|
if readHistoryType then
|
||||||
|
while #termlib.readHistory[readHistoryType] > 50 do
|
||||||
|
table.remove(termlib.readHistory[readHistoryType], 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return curtext
|
||||||
|
end
|
||||||
if args[3] >= 32 and args[3] <= 126 then
|
if args[3] >= 32 and args[3] <= 126 then
|
||||||
curtext = curtext .. (unicode.char(args[3]) or "")
|
curtext = curtext .. (unicode.char(args[3]) or "")
|
||||||
if readHistoryType then
|
if readHistoryType then
|
||||||
termlib.readHistory[readHistoryType][RHIndex] = curtext
|
termlib.readHistory[readHistoryType][RHIndex] = curtext
|
||||||
end
|
end
|
||||||
else
|
|
||||||
if key == "back" then
|
|
||||||
curtext = curtext:sub(1, #curtext-1)
|
|
||||||
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
|
||||||
print(curtext.." ", false)
|
|
||||||
elseif key == "enter" then
|
|
||||||
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
|
||||||
print(curtext .. " ")
|
|
||||||
if readHistoryType then
|
|
||||||
while #termlib.readHistory[readHistoryType] > 50 do
|
|
||||||
table.remove(termlib.readHistory[readHistoryType], 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return curtext
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY
|
||||||
print(curtext, false)
|
print(prefix .. curtext, false)
|
||||||
else
|
else
|
||||||
cursorWhite = not cursorWhite
|
cursorWhite = not cursorWhite
|
||||||
end
|
end
|
||||||
|
if cursorWhite then
|
||||||
|
print("\27[107m ", false)
|
||||||
|
else
|
||||||
|
print(" ", false)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -48,7 +48,12 @@ function filesystem.open(path, mode) -- opens a file and returns its handle
|
|||||||
return nil, "invalid handle type"
|
return nil, "invalid handle type"
|
||||||
end
|
end
|
||||||
local address, absPath = filesystem.processPath(path)
|
local address, absPath = filesystem.processPath(path)
|
||||||
local handle = component.invoke(address, "open", absPath, mode)
|
local handleArgs = {component.invoke(address, "open", absPath, mode)}
|
||||||
|
local handle = handleArgs[1]
|
||||||
|
if not handle then
|
||||||
|
return table.unpack(handleArgs)
|
||||||
|
end
|
||||||
|
handleArgs = nil
|
||||||
local properHandle = {}
|
local properHandle = {}
|
||||||
properHandle.handle = handle
|
properHandle.handle = handle
|
||||||
properHandle.address = address
|
properHandle.address = address
|
||||||
|
|||||||
+321
-316
@@ -1,11 +1,11 @@
|
|||||||
local raster = {
|
local raster = {
|
||||||
["units"]={},
|
["units"]={},
|
||||||
["defaultBackgroundColor"]=0x000000,
|
["defaultBackgroundColor"]=0x000000,
|
||||||
["defaultForegroundColor"]=0xFFFFFF,
|
["defaultForegroundColor"]=0xFFFFFF,
|
||||||
["displayWidth"]=0,
|
["displayWidth"]=0,
|
||||||
["displayHeight"]=0,
|
["displayHeight"]=0,
|
||||||
["charWidth"]=0,
|
["charWidth"]=0,
|
||||||
["charHeight"]=0
|
["charHeight"]=0
|
||||||
}
|
}
|
||||||
|
|
||||||
-- local ocelot = component.proxy(component.list("ocelot")())
|
-- local ocelot = component.proxy(component.list("ocelot")())
|
||||||
@@ -19,393 +19,398 @@ local renderBuffer = nil
|
|||||||
-- braille rendering
|
-- braille rendering
|
||||||
|
|
||||||
function raster.units.charToBraille(x,y)
|
function raster.units.charToBraille(x,y)
|
||||||
return x*2,y*4
|
return x*2,y*4
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.units.brailleToChar(x,y)
|
function raster.units.brailleToChar(x,y)
|
||||||
return math.ceil(x/2),math.ceil(y/4)
|
return math.ceil(x/2),math.ceil(y/4)
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.init(width, height, bgcolor)
|
function raster.init(width, height, bgcolor)
|
||||||
-- NOTE: Width and height are in characters, not pixels in braille.
|
-- NOTE: Width and height are in characters, not pixels in braille.
|
||||||
-- If the width and height are nil, the entire screen will be used.
|
-- If the width and height are nil, the entire screen will be used.
|
||||||
if width==nil and height==nil then
|
if width==nil and height==nil then
|
||||||
width, height = gpu.getResolution()
|
width, height = gpu.getResolution()
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, width*height do
|
for i = 1, width*height do
|
||||||
chunksAffected[i] = true
|
chunksAffected[i] = true
|
||||||
end
|
end
|
||||||
raster.charWidth = width
|
raster.charWidth = width
|
||||||
raster.charHeight = height
|
raster.charHeight = height
|
||||||
|
|
||||||
width, height = raster.units.charToBraille(width, height)
|
width, height = raster.units.charToBraille(width, height)
|
||||||
|
|
||||||
bgcolor = bgcolor or raster.defaultBackgroundColor;
|
bgcolor = bgcolor or raster.defaultBackgroundColor
|
||||||
|
|
||||||
for i = 1, width*height do
|
raster.displayWidth = width
|
||||||
display[i] = bgcolor
|
raster.displayHeight = height
|
||||||
end
|
|
||||||
raster.displayWidth = width
|
|
||||||
raster.displayHeight = height
|
|
||||||
|
|
||||||
pcall(function()
|
pcall(function()
|
||||||
renderBuffer = gpu.allocateBuffer()
|
renderBuffer = gpu.allocateBuffer()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.set(x, y, color)
|
function raster.set(x, y, color)
|
||||||
if x<1 or x>raster.displayWidth or y<1 or y>raster.displayHeight then
|
if x<1 or x>raster.displayWidth or y<1 or y>raster.displayHeight then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
color = color or raster.defaultForegroundColor
|
color = color or raster.defaultForegroundColor
|
||||||
local i = x+y*raster.displayWidth
|
local i = x+y*raster.displayWidth
|
||||||
display[i] = color
|
display[i] = color
|
||||||
|
|
||||||
local ci = math.floor((x-1)/2)+math.floor((y-1)/4)*raster.charWidth+1
|
local ci = math.floor((x-1)/2)+math.floor((y-1)/4)*raster.charWidth+1
|
||||||
-- ocelot.log(x..","..y..":"..ci)
|
-- ocelot.log(x..","..y..":"..ci)
|
||||||
chunksAffected[ci] = true
|
chunksAffected[ci] = true
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.get(x, y)
|
function raster.get(x, y)
|
||||||
local i = x+y*raster.displayWidth
|
local i = x+y*raster.displayWidth
|
||||||
return display[i] or 0
|
return display[i] or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local function stats(arr)
|
local function stats(arr)
|
||||||
local out = {}
|
local out = {}
|
||||||
for i=1,#arr do
|
for i=1,#arr do
|
||||||
local v = arr[i]
|
local v = arr[i]
|
||||||
if out[v]==nil then
|
if out[v]==nil then
|
||||||
out[v]=1
|
out[v]=1
|
||||||
else
|
else
|
||||||
out[v] = out[v] + 1
|
out[v] = out[v] + 1
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return out
|
end
|
||||||
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getKeys(t)
|
local function getKeys(t)
|
||||||
local keys = {}
|
local keys = {}
|
||||||
for key, _ in pairs(t) do
|
for key, _ in pairs(t) do
|
||||||
table.insert(keys, key)
|
table.insert(keys, key)
|
||||||
end
|
end
|
||||||
return keys
|
return keys
|
||||||
end
|
end
|
||||||
|
|
||||||
local function colorDifference(a,b)
|
local function colorDifference(a,b)
|
||||||
return ((a>>16)&255)-((b>>16)&255)+((a>>8)&255)-((b>>8)&255)+(a&255)-(b&255)
|
return ((a>>16)&255)-((b>>16)&255)+((a>>8)&255)-((b>>8)&255)+(a&255)-(b&255)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function limitTwoColors(arr)
|
local function limitTwoColors(arr)
|
||||||
local colors = getKeys(stats(arr))
|
local colors = getKeys(stats(arr))
|
||||||
for i=1,#arr do
|
for i=1,#arr do
|
||||||
local v=arr[i]
|
local v=arr[i]
|
||||||
if v==colors[1] then
|
if v==colors[1] then
|
||||||
arr[i]=0
|
arr[i]=0
|
||||||
goto continue
|
goto continue
|
||||||
elseif v==colors[2] then
|
elseif v==colors[2] then
|
||||||
arr[i]=1
|
arr[i]=1
|
||||||
goto continue
|
goto continue
|
||||||
else
|
else
|
||||||
--error("Pixel is not in the two colors (raster.lua:90)")
|
--error("Pixel is not in the two colors (raster.lua:90)")
|
||||||
-- get closest color so atleast it kinda shows
|
-- get closest color so atleast it kinda shows
|
||||||
if colorDifference(v,colors[1])<colorDifference(v,colors[2]) then
|
if colorDifference(v,colors[1])<colorDifference(v,colors[2]) then
|
||||||
arr[i]=0
|
arr[i]=0
|
||||||
else
|
else
|
||||||
arr[i]=1
|
arr[i]=1
|
||||||
end
|
end
|
||||||
end
|
|
||||||
::continue::
|
|
||||||
end
|
end
|
||||||
return arr,colors[1] or 0,colors[2] or 0
|
::continue::
|
||||||
|
end
|
||||||
|
return arr,colors[1] or 0,colors[2] or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local function arrayToBraille(arr)
|
local function arrayToBraille(arr)
|
||||||
local codePoint = 0x2800
|
local codePoint = 0x2800
|
||||||
for i=1,8 do
|
for i=1,8 do
|
||||||
codePoint = codePoint | arr[i]<<(i-1)
|
codePoint = codePoint | arr[i]<<(i-1)
|
||||||
end
|
end
|
||||||
return utf8.char(codePoint)
|
return utf8.char(codePoint)
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.update()
|
function raster.update()
|
||||||
if renderBuffer~=nil then
|
if renderBuffer~=nil then
|
||||||
gpu.setActiveBuffer(renderBuffer)
|
gpu.setActiveBuffer(renderBuffer)
|
||||||
end
|
end
|
||||||
for y=1,raster.displayHeight,4 do
|
for y=1,raster.displayHeight,4 do
|
||||||
-- gpu.set(0,0,tostring(y))
|
-- gpu.set(0,0,tostring(y))
|
||||||
for x=1,raster.displayWidth,2 do
|
for x=1,raster.displayWidth,2 do
|
||||||
local ci = math.floor(x/2)+math.floor(y/4)*raster.charWidth+1
|
local ci = math.floor(x/2)+math.floor(y/4)*raster.charWidth+1
|
||||||
if chunksAffected[ci] then
|
if chunksAffected[ci] then
|
||||||
local chunk = {
|
local chunk = {
|
||||||
raster.get(x,y),
|
raster.get(x,y),
|
||||||
raster.get(x,y+1),
|
raster.get(x,y+1),
|
||||||
raster.get(x,y+2),
|
raster.get(x,y+2),
|
||||||
raster.get(x+1,y),
|
raster.get(x,y+3),
|
||||||
raster.get(x+1,y+1),
|
raster.get(x+1,y),
|
||||||
raster.get(x+1,y+2),
|
raster.get(x+1,y+1),
|
||||||
raster.get(x,y+3),
|
raster.get(x+1,y+2),
|
||||||
raster.get(x+1,y+3)
|
raster.get(x+1,y+3)
|
||||||
}
|
}
|
||||||
local colorA = nil
|
local colorA = nil
|
||||||
local colorB = nil
|
local colorB = nil
|
||||||
chunk,colorA,colorB = limitTwoColors(chunk)
|
chunk,colorA,colorB = limitTwoColors(chunk)
|
||||||
-- print(tostring(colorA)..","..tostring(colorB))
|
-- print(tostring(colorA)..","..tostring(colorB))
|
||||||
cx,cy=raster.units.brailleToChar(x,y)
|
cx,cy=raster.units.brailleToChar(x,y)
|
||||||
gpu.setBackground(colorA)
|
gpu.setBackground(colorA)
|
||||||
gpu.setForeground(colorB)
|
gpu.setForeground(colorB)
|
||||||
-- gpu.set(cx,cy,tostring(colorB/0xFFFFFF))
|
-- gpu.set(cx,cy,tostring(colorB/0xFFFFFF))
|
||||||
gpu.set(cx,cy,arrayToBraille(chunk))
|
gpu.set(cx,cy,arrayToBraille(chunk))
|
||||||
chunksAffected[ci] = false
|
chunksAffected[ci] = false
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
if renderBuffer~=nil then
|
|
||||||
gpu.bitblt()
|
|
||||||
gpu.setActiveBuffer(0)
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
if renderBuffer~=nil then
|
||||||
|
gpu.bitblt()
|
||||||
|
gpu.setActiveBuffer(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function raster.clear()
|
||||||
|
if renderBuffer~=nil then
|
||||||
|
gpu.setActiveBuffer(renderBuffer)
|
||||||
|
end
|
||||||
|
clear()
|
||||||
|
display = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.free()
|
function raster.free()
|
||||||
if renderBuffer==nil then
|
if renderBuffer==nil then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return gpu.freeBuffer(renderBuffer)
|
return gpu.freeBuffer(renderBuffer)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- advanced rendering
|
-- advanced rendering
|
||||||
|
|
||||||
function raster.drawLine(x1, y1, x2, y2, color)
|
function raster.drawLine(x1, y1, x2, y2, color)
|
||||||
x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2)
|
x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2)
|
||||||
|
|
||||||
|
local dx = math.abs(x2 - x1)
|
||||||
|
local dy = math.abs(y2 - y1)
|
||||||
|
|
||||||
|
local sx = x1 < x2 and 1 or -1
|
||||||
|
local sy = y1 < y2 and 1 or -1
|
||||||
|
|
||||||
|
local err = dx - dy
|
||||||
|
|
||||||
|
while true do
|
||||||
|
raster.set(x1, y1, color)
|
||||||
|
|
||||||
local dx = math.abs(x2 - x1)
|
if x1 == x2 and y1 == y2 then
|
||||||
local dy = math.abs(y2 - y1)
|
break
|
||||||
|
|
||||||
local sx = x1 < x2 and 1 or -1
|
|
||||||
local sy = y1 < y2 and 1 or -1
|
|
||||||
|
|
||||||
local err = dx - dy
|
|
||||||
|
|
||||||
while true do
|
|
||||||
raster.set(x1, y1, color)
|
|
||||||
|
|
||||||
if x1 == x2 and y1 == y2 then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
local e2 = 2 * err
|
|
||||||
|
|
||||||
if e2 > -dy then
|
|
||||||
err = err - dy
|
|
||||||
x1 = x1 + sx
|
|
||||||
end
|
|
||||||
|
|
||||||
if e2 < dx then
|
|
||||||
err = err + dx
|
|
||||||
y1 = y1 + sy
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local e2 = 2 * err
|
||||||
|
|
||||||
|
if e2 > -dy then
|
||||||
|
err = err - dy
|
||||||
|
x1 = x1 + sx
|
||||||
|
end
|
||||||
|
|
||||||
|
if e2 < dx then
|
||||||
|
err = err + dx
|
||||||
|
y1 = y1 + sy
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.drawRect(x1,y1,x2,y2,col)
|
function raster.drawRect(x1,y1,x2,y2,col)
|
||||||
x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2)
|
x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2)
|
||||||
if x1 > x2 then x1, x2 = x2, x1 end
|
if x1 > x2 then x1, x2 = x2, x1 end
|
||||||
if y1 > y2 then y1, y2 = y2, y1 end
|
if y1 > y2 then y1, y2 = y2, y1 end
|
||||||
for x=x1,x2 do
|
for x=x1,x2 do
|
||||||
raster.set(x,y1,col)
|
raster.set(x,y1,col)
|
||||||
raster.set(x,y2,col)
|
raster.set(x,y2,col)
|
||||||
end
|
end
|
||||||
for y=y1+1,y2-1 do
|
for y=y1+1,y2-1 do
|
||||||
raster.set(x1,y,col)
|
raster.set(x1,y,col)
|
||||||
raster.set(x2,y,col)
|
raster.set(x2,y,col)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.fillRect(x1,y1,x2,y2,col)
|
function raster.fillRect(x1,y1,x2,y2,col)
|
||||||
x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2)
|
x1, y1, x2, y2 = math.floor(x1), math.floor(y1), math.floor(x2), math.floor(y2)
|
||||||
if x1 > x2 then x1, x2 = x2, x1 end
|
if x1 > x2 then x1, x2 = x2, x1 end
|
||||||
if y1 > y2 then y1, y2 = y2, y1 end
|
if y1 > y2 then y1, y2 = y2, y1 end
|
||||||
for x=x1,x2 do
|
for x=x1,x2 do
|
||||||
for y=y1,y2 do
|
for y=y1,y2 do
|
||||||
raster.set(x,y,col)
|
raster.set(x,y,col)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.drawCircle(xc, yc, radius, color)
|
function raster.drawCircle(xc, yc, radius, color)
|
||||||
xc=math.floor(xc)
|
xc=math.floor(xc)
|
||||||
yc=math.floor(yc)
|
yc=math.floor(yc)
|
||||||
radius=math.floor(radius)
|
radius=math.floor(radius)
|
||||||
local x = 0
|
local x = 0
|
||||||
local y = radius
|
local y = radius
|
||||||
local d = 3 - 2 * radius
|
local d = 3 - 2 * radius
|
||||||
|
|
||||||
|
while y >= x do
|
||||||
|
-- Draw 8 symmetric points
|
||||||
|
raster.set(xc + x, yc + y, color)
|
||||||
|
raster.set(xc - x, yc + y, color)
|
||||||
|
raster.set(xc + x, yc - y, color)
|
||||||
|
raster.set(xc - x, yc - y, color)
|
||||||
|
raster.set(xc + y, yc + x, color)
|
||||||
|
raster.set(xc - y, yc + x, color)
|
||||||
|
raster.set(xc + y, yc - x, color)
|
||||||
|
raster.set(xc - y, yc - x, color)
|
||||||
|
|
||||||
while y >= x do
|
if d < 0 then
|
||||||
-- Draw 8 symmetric points
|
d = d + 4 * x + 6
|
||||||
raster.set(xc + x, yc + y, color)
|
else
|
||||||
raster.set(xc - x, yc + y, color)
|
d = d + 4 * (x - y) + 10
|
||||||
raster.set(xc + x, yc - y, color)
|
y = y - 1
|
||||||
raster.set(xc - x, yc - y, color)
|
|
||||||
raster.set(xc + y, yc + x, color)
|
|
||||||
raster.set(xc - y, yc + x, color)
|
|
||||||
raster.set(xc + y, yc - x, color)
|
|
||||||
raster.set(xc - y, yc - x, color)
|
|
||||||
|
|
||||||
if d < 0 then
|
|
||||||
d = d + 4 * x + 6
|
|
||||||
else
|
|
||||||
d = d + 4 * (x - y) + 10
|
|
||||||
y = y - 1
|
|
||||||
end
|
|
||||||
x = x + 1
|
|
||||||
end
|
end
|
||||||
|
x = x + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.drawEllipse(x1, y1, x2, y2, color)
|
function raster.drawEllipse(x1, y1, x2, y2, color)
|
||||||
if x1 > x2 then x1, x2 = x2, x1 end
|
if x1 > x2 then x1, x2 = x2, x1 end
|
||||||
if y1 > y2 then y1, y2 = y2, y1 end
|
if y1 > y2 then y1, y2 = y2, y1 end
|
||||||
|
|
||||||
local xc = math.floor((x1 + x2) / 2)
|
local xc = math.floor((x1 + x2) / 2)
|
||||||
local yc = math.floor((y1 + y2) / 2)
|
local yc = math.floor((y1 + y2) / 2)
|
||||||
|
|
||||||
local a = math.floor((x2 - x1) / 2)
|
local a = math.floor((x2 - x1) / 2)
|
||||||
local b = math.floor((y2 - y1) / 2)
|
local b = math.floor((y2 - y1) / 2)
|
||||||
|
|
||||||
if a <= 0 or b <= 0 then
|
if a <= 0 or b <= 0 then
|
||||||
return
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if a == b then
|
||||||
|
raster.drawCircle(xc, yc, a, color)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if a <= 1 and b <= 1 then
|
||||||
|
raster.set(xc, yc, color)
|
||||||
|
return
|
||||||
|
elseif a <= 1 then
|
||||||
|
for y = yc - b, yc + b do
|
||||||
|
raster.set(xc, y, color)
|
||||||
end
|
end
|
||||||
|
return
|
||||||
if a == b then
|
elseif b <= 1 then
|
||||||
raster.drawCircle(xc, yc, a, color)
|
for x = xc - a, xc + a do
|
||||||
return
|
raster.set(x, yc, color)
|
||||||
end
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local x = 0
|
||||||
|
local y = b
|
||||||
|
local a2 = a * a
|
||||||
|
local b2 = b * b
|
||||||
|
|
||||||
|
local d1 = b2 - (a2 * b) + (0.25 * a2)
|
||||||
|
local dx = 2 * b2 * x
|
||||||
|
local dy = 2 * a2 * y
|
||||||
|
|
||||||
|
while dx < dy do
|
||||||
|
raster.set(xc + x, yc + y, color)
|
||||||
|
raster.set(xc - x, yc + y, color)
|
||||||
|
raster.set(xc + x, yc - y, color)
|
||||||
|
raster.set(xc - x, yc - y, color)
|
||||||
|
|
||||||
if a <= 1 and b <= 1 then
|
if d1 < 0 then
|
||||||
raster.set(xc, yc, color)
|
x = x + 1
|
||||||
return
|
dx = dx + (2 * b2)
|
||||||
elseif a <= 1 then
|
d1 = d1 + dx + b2
|
||||||
for y = yc - b, yc + b do
|
else
|
||||||
raster.set(xc, y, color)
|
x = x + 1
|
||||||
end
|
y = y - 1
|
||||||
return
|
dx = dx + (2 * b2)
|
||||||
elseif b <= 1 then
|
dy = dy - (2 * a2)
|
||||||
for x = xc - a, xc + a do
|
d1 = d1 + dx - dy + b2
|
||||||
raster.set(x, yc, color)
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local d2 = b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2
|
||||||
|
|
||||||
|
while y >= 0 do
|
||||||
|
raster.set(xc + x, yc + y, color)
|
||||||
|
raster.set(xc - x, yc + y, color)
|
||||||
|
raster.set(xc + x, yc - y, color)
|
||||||
|
raster.set(xc - x, yc - y, color)
|
||||||
|
|
||||||
local x = 0
|
if d2 > 0 then
|
||||||
local y = b
|
y = y - 1
|
||||||
local a2 = a * a
|
dy = dy - (2 * a2)
|
||||||
local b2 = b * b
|
d2 = d2 - dy + a2
|
||||||
|
else
|
||||||
local d1 = b2 - (a2 * b) + (0.25 * a2)
|
y = y - 1
|
||||||
local dx = 2 * b2 * x
|
x = x + 1
|
||||||
local dy = 2 * a2 * y
|
dx = dx + (2 * b2)
|
||||||
|
dy = dy - (2 * a2)
|
||||||
while dx < dy do
|
d2 = d2 + dx - dy + a2
|
||||||
raster.set(xc + x, yc + y, color)
|
|
||||||
raster.set(xc - x, yc + y, color)
|
|
||||||
raster.set(xc + x, yc - y, color)
|
|
||||||
raster.set(xc - x, yc - y, color)
|
|
||||||
|
|
||||||
if d1 < 0 then
|
|
||||||
x = x + 1
|
|
||||||
dx = dx + (2 * b2)
|
|
||||||
d1 = d1 + dx + b2
|
|
||||||
else
|
|
||||||
x = x + 1
|
|
||||||
y = y - 1
|
|
||||||
dx = dx + (2 * b2)
|
|
||||||
dy = dy - (2 * a2)
|
|
||||||
d1 = d1 + dx - dy + b2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local d2 = b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2
|
|
||||||
|
|
||||||
while y >= 0 do
|
|
||||||
raster.set(xc + x, yc + y, color)
|
|
||||||
raster.set(xc - x, yc + y, color)
|
|
||||||
raster.set(xc + x, yc - y, color)
|
|
||||||
raster.set(xc - x, yc - y, color)
|
|
||||||
|
|
||||||
if d2 > 0 then
|
|
||||||
y = y - 1
|
|
||||||
dy = dy - (2 * a2)
|
|
||||||
d2 = d2 - dy + a2
|
|
||||||
else
|
|
||||||
y = y - 1
|
|
||||||
x = x + 1
|
|
||||||
dx = dx + (2 * b2)
|
|
||||||
dy = dy - (2 * a2)
|
|
||||||
d2 = d2 + dx - dy + a2
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.fillCircle(x, y, r, color)
|
function raster.fillCircle(x, y, r, color)
|
||||||
x, y = math.floor(x + 0.5), math.floor(y + 0.5)
|
x, y = math.floor(x + 0.5), math.floor(y + 0.5)
|
||||||
r = math.floor(r + 0.5)
|
r = math.floor(r + 0.5)
|
||||||
|
|
||||||
if r <= 0 then return end
|
if r <= 0 then return end
|
||||||
|
|
||||||
local minX, maxX = x - r, x + r
|
local minX, maxX = x - r, x + r
|
||||||
local minY, maxY = y - r, y + r
|
local minY, maxY = y - r, y + r
|
||||||
|
|
||||||
for py = minY, maxY do
|
for py = minY, maxY do
|
||||||
for px = minX, maxX do
|
for px = minX, maxX do
|
||||||
local dx, dy = px - x, py - y
|
local dx, dy = px - x, py - y
|
||||||
local distSquared = dx*dx + dy*dy
|
local distSquared = dx*dx + dy*dy
|
||||||
|
|
||||||
if distSquared <= r*r then
|
if distSquared <= r*r then
|
||||||
raster.set(px, py, color)
|
raster.set(px, py, color)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function raster.fillEllipse(x1, y1, x2, y2, color)
|
function raster.fillEllipse(x1, y1, x2, y2, color)
|
||||||
local centerX = (x1 + x2) / 2
|
local centerX = (x1 + x2) / 2
|
||||||
local centerY = (y1 + y2) / 2
|
local centerY = (y1 + y2) / 2
|
||||||
|
|
||||||
local a = math.abs(x2 - x1) / 2
|
local a = math.abs(x2 - x1) / 2
|
||||||
local b = math.abs(y2 - y1) / 2
|
local b = math.abs(y2 - y1) / 2
|
||||||
|
|
||||||
centerX = math.floor(centerX + 0.5)
|
centerX = math.floor(centerX + 0.5)
|
||||||
centerY = math.floor(centerY + 0.5)
|
centerY = math.floor(centerY + 0.5)
|
||||||
a = math.floor(a + 0.5)
|
a = math.floor(a + 0.5)
|
||||||
b = math.floor(b + 0.5)
|
b = math.floor(b + 0.5)
|
||||||
|
|
||||||
if a <= 0 or b <= 0 then return end
|
if a <= 0 or b <= 0 then return end
|
||||||
|
|
||||||
if a == b then
|
if a == b then
|
||||||
raster.fillCircle(centerX, centerY, a, color)
|
raster.fillCircle(centerX, centerY, a, color)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local minX = centerX - a
|
local minX = centerX - a
|
||||||
local maxX = centerX + a
|
local maxX = centerX + a
|
||||||
local minY = centerY - b
|
local minY = centerY - b
|
||||||
local maxY = centerY + b
|
local maxY = centerY + b
|
||||||
|
|
||||||
for y = minY, maxY do
|
for y = minY, maxY do
|
||||||
for x = minX, maxX do
|
for x = minX, maxX do
|
||||||
local dx = x - centerX
|
local dx = x - centerX
|
||||||
local dy = y - centerY
|
local dy = y - centerY
|
||||||
local value = (dx*dx)/(a*a) + (dy*dy)/(b*b)
|
local value = (dx*dx)/(a*a) + (dy*dy)/(b*b)
|
||||||
|
|
||||||
if value <= 1 then
|
if value <= 1 then
|
||||||
raster.set(x, y, color)
|
raster.set(x, y, color)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return raster
|
return raster
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
|
||||||
|
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
|
||||||
|
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
|
||||||
|
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
|
||||||
|
This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file! This is a long file!
|
||||||
|
This is a long line! This is a long line! This is a long line! This is a long line! This is a long line! This is a long line! This is a long line! This is a long line! This is a long line!
|
||||||
|
This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line! This is a longer line!
|
||||||
|
|
||||||
|
This is a short line!
|
||||||
|
|
||||||
|
This is a short line!
|
||||||
|
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This has a lot of lines!
|
||||||
|
This is the last line!
|
||||||
Reference in New Issue
Block a user