2017-05-22 22:16:30 +03:00

245 lines
7.7 KiB
Lua
Executable File

_G.buffer = require("doubleBuffering")
buffer.start()
_G.unicode = require("unicode")
_G.event = require("event")
_G.ecs = require("ECSAPI")
local xGraph, yGraph = math.floor(buffer.width / 2), buffer.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 showCornerPoints = false
------------------------------------------------------------------------------------------------------------------------------------------
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.width / 2 - (#buttonNames * (buttonWidth + 2) - 2) / 2), buffer.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 buffer.semiPixelSet(i, y, color) end
end
local function drawVerticalLine(x, y, y2, color)
for i = y, y2 do buffer.semiPixelSet(x, i, color) end
end
local function drawAxis()
drawHorizontalLine(1, yGraph, buffer.width, axisColor)
drawVerticalLine(xGraph, 1, buffer.height * 2, axisColor)
end
local function limit(n)
if n > -500 and n < 500 then return true end
end
local keyPoints = {}
local function calculateKeyPoints()
keyPoints = {}
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(x * graphScale), math.floor(result * graphScale)
if limit(xOld) and limit(yOld) and limit(xNew) and limit(yNew) then
table.insert(keyPoints, {x = xOld, y = yOld, x2 = xNew, y2 = yNew})
-- buffer.semiPixelLine(xOld, yOld, xNew, yNew, graphColor)
end
xOld, yOld = xNew, yNew
end
-- else
-- error(result)
end
end
end
local function drawGraph()
for i = 1, #keyPoints do
buffer.semiPixelLine(xGraph + keyPoints[i].x, yGraph - keyPoints[i].y, xGraph + keyPoints[i].x2, yGraph - keyPoints[i].y2, graphColor)
if showCornerPoints then buffer.semiPixelSet(xGraph + keyPoints[i].x, yGraph - keyPoints[i].y, 0x00A8FF) 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
buffer.semiPixelSet(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
------------------------------------------------------------------------------------------------------------------------------------------
calculateKeyPoints()
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, 101 - renderAccuracy * 100, "Точность: ", ""},
{"EmptyLine"},
{"Switch", ecs.colors.orange, 0xffffff, 0xFFFFFF, "Показывать квант-точки", showCornerPoints},
{"EmptyLine"},
{"Button", {ecs.colors.orange, 0xffffff, "OK"}, {0x999999, 0xffffff, "Отмена"}}
)
if data[5] == "OK" then
yDependencyString = data[1]
renderRange = tonumber(data[2])
renderAccuracy = (101 - tonumber(data[3])) / 100
showCornerPoints = data[4]
calculateKeyPoints()
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, 3000, math.floor(graphScale * 100), "", "%"},
{"EmptyLine"},
{"Button", {ecs.colors.orange, 0xffffff, "OK"}, {0x999999, 0xffffff, "Отмена"}}
)
if data[2] == "OK" then
graphScale = data[1] / 100
calculateKeyPoints()
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
calculateKeyPoints()
else
graphScale = graphScale - graphResizeSpeed
if graphScale < graphResizeSpeed then graphScale = graphResizeSpeed end
calculateKeyPoints()
end
drawAll()
elseif e[1] == "key_down" then
if e[4] == 28 then
selectedPoints = nil
drawAll()
end
end
end