mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2026-01-08 20:22:38 +01:00
Новое приложение "Graph"
This commit is contained in:
parent
230aed4bc4
commit
406c86c7ee
@ -251,6 +251,12 @@
|
||||
|
||||
----------------------------------------------------- Библиотеки --------------------------------------------------------------------------
|
||||
|
||||
{
|
||||
["name"]="lib/doubleHeight.lua",
|
||||
["url"]="IgorTimofeev/OpenComputers/master/lib/doubleHeight.lua",
|
||||
["type"]="Library",
|
||||
["version"]=1.0,
|
||||
},
|
||||
{
|
||||
["name"]="lib/json.lua",
|
||||
["url"]="IgorTimofeev/OpenComputers/master/lib/json.lua",
|
||||
@ -429,6 +435,14 @@
|
||||
["version"]=1.0,
|
||||
},
|
||||
----------------------------------------------------- Приложения без ресурсов --------------------------------------------------------------------------
|
||||
{
|
||||
["name"]="MineOS/Applications/Graph",
|
||||
["url"]="IgorTimofeev/OpenComputers/master/Applications/Graph/Graph.lua",
|
||||
["type"]="Application",
|
||||
["icon"]="IgorTimofeev/OpenComputers/master/Applications/Graph/Icon.pic",
|
||||
["createShortcut"]="desktop",
|
||||
["version"]=1.0,
|
||||
},
|
||||
{
|
||||
["name"]="MineOS/Applications/FlappyBlock",
|
||||
["url"]="IgorTimofeev/OpenComputers/master/Applications/FlappyBlock/FlappyBlock.lua",
|
||||
|
||||
226
Applications/Graph/Graph.lua
Normal file
226
Applications/Graph/Graph.lua
Normal file
@ -0,0 +1,226 @@
|
||||
|
||||
_G.buffer = require("doubleBuffering")
|
||||
buffer.start()
|
||||
_G.doubleHeight = require("doubleHeight")
|
||||
_G.unicode = require("unicode")
|
||||
_G.event = require("event")
|
||||
_G.ecs = require("ECSAPI")
|
||||
|
||||
local xGraph, yGraph = math.floor(buffer.screen.width / 2), buffer.screen.height
|
||||
local yDependencyString = "math.sin(x) * 5"
|
||||
local graphScale = 4
|
||||
local graphResizeSpeed = 0.4
|
||||
local renderRange = 40
|
||||
local renderAccuracy = 0.4
|
||||
local axisColor = 0x333333
|
||||
local graphColor = 0x88FF88
|
||||
local selectionPointLineColor = 0x555555
|
||||
local selectionPointColor = 0x5555FF
|
||||
local selectionTooltipTextColor = 0xFFFFFF
|
||||
local buttonColor = 0xEEEEEE
|
||||
local backgroundColor = 0x1b1b1b
|
||||
local buttonTextColor = 0x1b1b1b
|
||||
local buttonWidth = 20
|
||||
local selectedPoints = {{x = -5, y = 2}}
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
local buttons = {}
|
||||
|
||||
local function assertString(x, yDependencyString)
|
||||
local stro4ka = "local x = " .. x .. "; local y = " .. yDependencyString .. "; return y"
|
||||
return pcall(load(stro4ka))
|
||||
end
|
||||
|
||||
local function drawButtons()
|
||||
buttons = {}
|
||||
local buttonNames = {"Функция", "Масштаб", "Очистить точки", "Выход"}
|
||||
local x, y = math.floor(buffer.screen.width / 2 - (#buttonNames * (buttonWidth + 2) - 2) / 2), buffer.screen.height - 4
|
||||
|
||||
for i = 1, #buttonNames do
|
||||
buttons[buttonNames[i]] = { buffer.button(x, y, buttonWidth, 3, buttonColor, buttonTextColor, buttonNames[i]) }
|
||||
x = x + buttonWidth + 2
|
||||
end
|
||||
end
|
||||
|
||||
local function drawHorizontalLine(x, y, x2, color)
|
||||
for i = x, x2 do doubleHeight.set(i, y, color) end
|
||||
end
|
||||
|
||||
local function drawVerticalLine(x, y, y2, color)
|
||||
for i = y, y2 do doubleHeight.set(x, i, color) end
|
||||
end
|
||||
|
||||
local function drawAxis()
|
||||
drawHorizontalLine(1, yGraph, buffer.screen.width, axisColor)
|
||||
drawVerticalLine(xGraph, 1, buffer.screen.height * 2, axisColor)
|
||||
end
|
||||
|
||||
local function limit(n)
|
||||
if n > -300 and n < 300 then return true end
|
||||
end
|
||||
|
||||
local function drawGraph()
|
||||
local xOld, yOld, xNew, yNew = math.huge, math.huge
|
||||
for x = -renderRange, renderRange, renderAccuracy do
|
||||
local success, result = assertString(x, yDependencyString)
|
||||
if success then
|
||||
if not (result ~= result) then
|
||||
xNew, yNew = math.floor(xGraph + x * graphScale), math.floor(yGraph - result * graphScale)
|
||||
|
||||
if limit(xOld) and limit(yOld) and limit(xNew) and limit(yNew) then
|
||||
doubleHeight.line(xOld, yOld, xNew, yNew, graphColor)
|
||||
end
|
||||
|
||||
xOld, yOld = xNew, yNew
|
||||
end
|
||||
else
|
||||
error(success, result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function tooltip(x, y, tooltipColor, textColor, ...)
|
||||
local stringArray = {...}
|
||||
local maxTextLength = 0; for i = 1, #stringArray do maxTextLength = math.max(maxTextLength, unicode.len(stringArray[i])) end
|
||||
|
||||
buffer.square(x, y, maxTextLength + 2, #stringArray, tooltipColor, textColor, " ")
|
||||
x = x + 1
|
||||
for i = 1, #stringArray do
|
||||
buffer.text(x, y, textColor, stringArray[i])
|
||||
y = y + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function drawSelectedPoint(x, y, pointNumber)
|
||||
local xOnScreen, yOnScreen = math.floor(xGraph + x * graphScale), math.floor(yGraph - y * graphScale)
|
||||
|
||||
if xOnScreen <= xGraph then drawHorizontalLine(xOnScreen, yOnScreen, xGraph - 1, selectionPointLineColor) else drawHorizontalLine(xGraph + 1, yOnScreen, xOnScreen, selectionPointLineColor) end
|
||||
if yOnScreen <= yGraph then drawVerticalLine(xOnScreen, yOnScreen, yGraph - 1, selectionPointLineColor) else drawVerticalLine(xOnScreen, yGraph + 1, yOnScreen, selectionPointLineColor) end
|
||||
|
||||
doubleHeight.set(xOnScreen, yOnScreen, selectionPointColor)
|
||||
|
||||
yOnScreen = math.ceil(yOnScreen / 2)
|
||||
|
||||
tooltip(xOnScreen + 3, yOnScreen + 2, selectionPointLineColor, selectionTooltipTextColor, "Точка #" .. pointNumber, "x: " .. x, "y: " .. y)
|
||||
end
|
||||
|
||||
local function drawSelectedPoints()
|
||||
if selectedPoints then
|
||||
for i = 1, #selectedPoints do
|
||||
drawSelectedPoint(selectedPoints[i].x, selectedPoints[i].y, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function drawAll()
|
||||
buffer.clear(backgroundColor)
|
||||
drawAxis()
|
||||
drawGraph()
|
||||
drawSelectedPoints()
|
||||
drawButtons()
|
||||
buffer.draw()
|
||||
end
|
||||
|
||||
local function clicked(x, y, object)
|
||||
if x >= object[1] and y >= object[2] and x <= object[3] and y <= object[4] then return true end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
drawAll()
|
||||
|
||||
local xMove, yMove
|
||||
while true do
|
||||
local e = {event.pull()}
|
||||
if e[1] == "touch" then
|
||||
if e[5] == 1 then
|
||||
selectedPoints = selectedPoints or {}
|
||||
table.insert(selectedPoints, { x = math.floor((e[3] - xGraph) / graphScale), y = math.floor((yGraph - e[4] * 2) / graphScale) })
|
||||
drawAll()
|
||||
else
|
||||
xMove, yMove = e[3], e[4]
|
||||
|
||||
for key in pairs(buttons) do
|
||||
if clicked(e[3], e[4], buttons[key]) then
|
||||
buffer.button(buttons[key][1], buttons[key][2], buttonWidth, 3, graphColor, backgroundColor, key)
|
||||
buffer.draw()
|
||||
os.sleep(0.2)
|
||||
drawAll()
|
||||
|
||||
if key == "Функция" then
|
||||
local data = ecs.universalWindow("auto", "auto", 36, 0x262626, true,
|
||||
{"EmptyLine"},
|
||||
{"CenterText", ecs.colors.orange, "Функция"},
|
||||
{"EmptyLine"},
|
||||
{"Input", 0xFFFFFF, ecs.colors.orange, yDependencyString},
|
||||
{"EmptyLine"},
|
||||
{"CenterText", ecs.colors.orange, "Параметры рендера"},
|
||||
{"Slider", 0xFFFFFF, ecs.colors.orange, 1, 100, renderRange, "Диапазон: ", ""},
|
||||
{"Slider", 0xFFFFFF, ecs.colors.orange, 1, 100, renderAccuracy * 100, "Точность: ", "/100"},
|
||||
{"EmptyLine"},
|
||||
{"Button", {ecs.colors.orange, 0xffffff, "OK"}, {0x999999, 0xffffff, "Отмена"}}
|
||||
)
|
||||
if data[4] == "OK" then
|
||||
yDependencyString = data[1]
|
||||
renderRange = tonumber(data[2])
|
||||
renderAccuracy = tonumber(data[3]) / 100
|
||||
drawAll()
|
||||
end
|
||||
elseif key == "Масштаб" then
|
||||
local data = ecs.universalWindow("auto", "auto", 36, 0x262626, true,
|
||||
{"EmptyLine"},
|
||||
{"CenterText", ecs.colors.orange, "Масштаб"},
|
||||
{"EmptyLine"},
|
||||
{"Slider", 0xFFFFFF, ecs.colors.orange, 1, 5000, math.floor(graphScale * 100), "", "%"},
|
||||
{"EmptyLine"},
|
||||
{"Button", {ecs.colors.orange, 0xffffff, "OK"}, {0x999999, 0xffffff, "Отмена"}}
|
||||
)
|
||||
|
||||
if data[2] == "OK" then
|
||||
graphScale = data[1] / 100
|
||||
drawAll()
|
||||
end
|
||||
elseif key == "Очистить точки" then
|
||||
selectedPoints = nil
|
||||
drawAll()
|
||||
elseif key == "Выход" then
|
||||
buffer.clear(0x262626)
|
||||
buffer.draw()
|
||||
return
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif e[1] == "drag" then
|
||||
if e[5] ~= 1 then
|
||||
local xDifference, yDifference = e[3] - xMove, e[4] - yMove
|
||||
xGraph, yGraph = xGraph + xDifference, yGraph + yDifference * 2
|
||||
xMove, yMove = e[3], e[4]
|
||||
drawAll()
|
||||
end
|
||||
elseif e[1] == "scroll" then
|
||||
if e[5] == 1 then
|
||||
graphScale = graphScale + graphResizeSpeed
|
||||
else
|
||||
graphScale = graphScale - graphResizeSpeed
|
||||
if graphScale < graphResizeSpeed then graphScale = graphResizeSpeed end
|
||||
end
|
||||
drawAll()
|
||||
elseif e[1] == "key_down" then
|
||||
if e[4] == 28 then
|
||||
selectedPoints = nil
|
||||
drawAll()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Applications/Graph/Icon.pic
Normal file
BIN
Applications/Graph/Icon.pic
Normal file
Binary file not shown.
80
lib/doubleHeight.lua
Normal file
80
lib/doubleHeight.lua
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
if not _G.buffer then _G.buffer = require("doubleBuffering") end
|
||||
local doubleHeight = {}
|
||||
|
||||
local upperPixel = "▀"
|
||||
local lowerPixel = "▄"
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
function doubleHeight.set(x, y, color)
|
||||
if x >= 1 and x <= buffer.screen.width and y >= 1 and y <= buffer.screen.height * 2 then
|
||||
local yFixed = math.ceil(y / 2)
|
||||
local background, foreground, symbol = buffer.get(x, yFixed)
|
||||
|
||||
if y % 2 == 0 then
|
||||
if symbol == upperPixel then
|
||||
buffer.set(x, yFixed, color, foreground, upperPixel)
|
||||
else
|
||||
buffer.set(x, yFixed, background, color, lowerPixel)
|
||||
end
|
||||
else
|
||||
if symbol == lowerPixel then
|
||||
buffer.set(x, yFixed, color, foreground, lowerPixel)
|
||||
else
|
||||
buffer.set(x, yFixed, background, color, upperPixel)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function swap(a, b)
|
||||
return b, a
|
||||
end
|
||||
|
||||
function doubleHeight.line(x0, y0, x1, y1, color)
|
||||
local steep = false;
|
||||
|
||||
if math.abs(x0 - x1) < math.abs(y0 - y1 ) then
|
||||
x0, y0 = swap(x0, y0)
|
||||
x1, y1 = swap(x1, y1)
|
||||
steep = true;
|
||||
end
|
||||
|
||||
if (x0 > x1) then
|
||||
x0, x1 = swap(x0, x1)
|
||||
y0, y1 = swap(y0, y1)
|
||||
end
|
||||
|
||||
local dx = x1 - x0;
|
||||
local dy = y1 - y0;
|
||||
local derror2 = math.abs(dy) * 2
|
||||
local error2 = 0;
|
||||
local y = y0;
|
||||
|
||||
for x = x0, x1, 1 do
|
||||
if steep then
|
||||
doubleHeight.set(y, x, color);
|
||||
else
|
||||
doubleHeight.set(x, y, color)
|
||||
end
|
||||
|
||||
error2 = error2 + derror2;
|
||||
|
||||
if error2 > dx then
|
||||
y = y + (y1 > y0 and 1 or -1);
|
||||
error2 = error2 - dx * 2;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return doubleHeight
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user