From a40300da713a6809c52fdb8d14bd90a03d1a3236 Mon Sep 17 00:00:00 2001 From: Igor Timofeev Date: Tue, 14 Mar 2017 11:51:50 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=20?= =?UTF-8?q?=D0=B0=D0=BB=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC=20=D1=81=D0=BC?= =?UTF-8?q?=D0=B5=D1=88=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=86=D0=B2?= =?UTF-8?q?=D0=B5=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Applications/3DTest/3DTest.lua | 13 +- Applications/Photoshop/Photoshop.lua | 4 +- Applications/PrintImage/PrintImage.lua | 4 +- Applications/RayWalk/RayEngine.cfg | 28 +- Applications/RayWalk/RayWalk.lua | 4 +- Beta/Cyka.java | 319 --- Beta/MineCode2/ECSAPI.lua | 2424 ----------------- Beta/MineCode2/colorlib.lua | 151 - Beta/MineCode2/context.lua | 137 - Beta/MineCode2/doubleBuffering.lua | 467 ---- Beta/MineCode2/filemanager.lua | 95 - Beta/MineCode2/image.lua | 1091 -------- Beta/MineCode2/m.lua | 242 -- Beta/MineCode2/syntax.lua | 318 --- Beta/PS3.lua | 833 ------ Beta/Printer.lua | 344 --- Beta/Reactor.lua | 18 - Beta/Shop2.lua | 1073 -------- Beta/Tetris.lua | 264 -- Beta/bufferNotOptimized.lua | 553 ---- Beta/calendar.lua | 205 -- Beta/colorPaletteCompressed.lua | 256 -- Beta/debugImageApi.lua | 646 ----- .../Фирменный компьютер ECS.json | 9 +- lib/ECSAPI.lua | 2 +- lib/GUI.lua | 44 +- lib/OpenComputersGL/Main.lua | 2 +- lib/colorlib.lua | 2 - lib/doubleBuffering.lua | 4 +- lib/image.lua | 6 +- lib/rayEngine.lua | 4 +- lib/rayEngineBackup.lua | 472 ---- 32 files changed, 71 insertions(+), 9963 deletions(-) delete mode 100644 Beta/Cyka.java delete mode 100644 Beta/MineCode2/ECSAPI.lua delete mode 100644 Beta/MineCode2/colorlib.lua delete mode 100644 Beta/MineCode2/context.lua delete mode 100644 Beta/MineCode2/doubleBuffering.lua delete mode 100644 Beta/MineCode2/filemanager.lua delete mode 100644 Beta/MineCode2/image.lua delete mode 100644 Beta/MineCode2/m.lua delete mode 100644 Beta/MineCode2/syntax.lua delete mode 100644 Beta/PS3.lua delete mode 100644 Beta/Printer.lua delete mode 100644 Beta/Reactor.lua delete mode 100644 Beta/Shop2.lua delete mode 100644 Beta/Tetris.lua delete mode 100644 Beta/bufferNotOptimized.lua delete mode 100644 Beta/calendar.lua delete mode 100644 Beta/colorPaletteCompressed.lua delete mode 100644 Beta/debugImageApi.lua delete mode 100644 lib/rayEngineBackup.lua diff --git a/Applications/3DTest/3DTest.lua b/Applications/3DTest/3DTest.lua index 35a9d654..22c52541 100644 --- a/Applications/3DTest/3DTest.lua +++ b/Applications/3DTest/3DTest.lua @@ -26,8 +26,10 @@ local polyCatEngine = require("PolyCatEngine/Main") ---------------------------------------------- Anus preparing ---------------------------------------------- +-- /MineOS/Desktop/3DTest.app/3DTest.lua + buffer.start() -polyCatEngine.intro(vector.newVector3(0, 0, 0), 20) +-- polyCatEngine.intro(vector.newVector3(0, 0, 0), 20) local mainWindow = windows.fullScreen() local scene = polyCatEngine.newScene(0x1D1D1D) scene:addLight(polyCatEngine.newLight(vector.newVector3(0, 20, 0), 1000)) @@ -482,13 +484,15 @@ mainWindow.toolbar.backgroundColorSelector.onTouch = function() end mainWindow.toolbar:addLabel(2, elementY, elementWidth, 1, 0xEEEEEE, "RAM monitoring"):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top); elementY = elementY + 2 -mainWindow.toolbar.RAMChart = mainWindow.toolbar:addChart(2, elementY, elementWidth, mainWindow.toolbar.height - elementY - 3, 0xEEEEEE, 0xAAAAAA, 0x555555, 0x66DB80, 0.35, 0.25, "s", "%", true, {}); elementY = elementY + mainWindow.toolbar.RAMChart.height + 1 +mainWindow.toolbar.RAMChart = mainWindow.toolbar:addChart(2, elementY, elementWidth, mainWindow.toolbar.height - elementY - 6, 0xEEEEEE, 0xAAAAAA, 0x555555, 0x66DB80, 0.35, 0.25, "s", "%", true, {}); elementY = elementY + mainWindow.toolbar.RAMChart.height + 1 mainWindow.toolbar.RAMChart.roundValues = true +-- mainWindow.toolbar.RAMChart.showXAxisValues = false mainWindow.toolbar.RAMChart.counter = 1 +mainWindow.toolbar.RAMProgressBar = mainWindow.toolbar:addProgressBar(2, elementY, elementWidth, 0x66DB80, 0x2D2D2D, 0xAAAAAA, 1, true, true, "", "%") + mainWindow.toolbar:addButton(1, mainWindow.toolbar.height - 2, mainWindow.toolbar.width, 3, 0xEEEEEE, 0x2D2D2D, 0xAAAAAA, 0x2D2D2D, "Exit").onTouch = function() mainWindow:close() end - mainWindow.onDrawFinished = function() -- clock sec - 1 frame -- 1 sec - x frames @@ -498,7 +502,8 @@ end mainWindow.onAnyEvent = function(e) if not mainWindow.toolbar.isHidden then local totalMemory = computer.totalMemory() - table.insert(mainWindow.toolbar.RAMChart.values, {mainWindow.toolbar.RAMChart.counter, math.ceil((totalMemory - computer.freeMemory()) / totalMemory * 100)}) + mainWindow.toolbar.RAMProgressBar.value = math.ceil((totalMemory - computer.freeMemory()) / totalMemory * 100) + table.insert(mainWindow.toolbar.RAMChart.values, {mainWindow.toolbar.RAMChart.counter, mainWindow.toolbar.RAMProgressBar.value}) mainWindow.toolbar.RAMChart.counter = mainWindow.toolbar.RAMChart.counter + 1 if #mainWindow.toolbar.RAMChart.values > 20 then table.remove(mainWindow.toolbar.RAMChart.values, 1) end diff --git a/Applications/Photoshop/Photoshop.lua b/Applications/Photoshop/Photoshop.lua index a8067640..62048dfc 100755 --- a/Applications/Photoshop/Photoshop.lua +++ b/Applications/Photoshop/Photoshop.lua @@ -327,7 +327,7 @@ local function drawPixel(x, y, xPixel, yPixel, iterator) end end - buffer.set(x, y, colorlib.alphaBlend(blendColor, background, alpha), foreground, symbol) + buffer.set(x, y, colorlib.alphaBlend(blendColor, background, alpha / 0xFF), foreground, symbol) end background, foreground, alpha, symbol = nil, nil, nil, nil end @@ -862,7 +862,7 @@ local function brush(x, y, background, foreground, alpha, symbol) elseif alpha < 0xFF and alpha > 0x00 then --Если пиксель в массиве ни хуя не прозрачный, то оставляем его таким же, разве что цвет меняем на сблендированный if masterPixels[newIterator + 2] == 0x00 then - local gettedBackground = colorlib.alphaBlend(masterPixels[newIterator], background, alpha) + local gettedBackground = colorlib.alphaBlend(masterPixels[newIterator], background, alpha / 0xFF) setPixel(newIterator, gettedBackground, foreground, 0x00, symbol) --А если прозрачный, то смешиваем прозрачности --Пиздануться вообще, сук diff --git a/Applications/PrintImage/PrintImage.lua b/Applications/PrintImage/PrintImage.lua index 0bdb990c..cba7f4fa 100755 --- a/Applications/PrintImage/PrintImage.lua +++ b/Applications/PrintImage/PrintImage.lua @@ -178,8 +178,8 @@ local function drawMainImageObject(object) buffer.image(xImage, yImage, mainImage) GUI.windowShadow(xImage, yImage, mainImage.width, mainImage.height, 50, true) if config.showGrid then - for x = xImage, xImage + mainImage.width - 1, shapeResolutionLimit do verticalLine(x, yImage, mainImage.height, 0xA0) end - for y = yImage, yImage + mainImage.height - 1, shapeResolutionLimit / 2 do horizontalLine(xImage, y, mainImage.width, 0xA0) end + for x = xImage, xImage + mainImage.width - 1, shapeResolutionLimit do verticalLine(x, yImage, mainImage.height, 0.627) end + for y = yImage, yImage + mainImage.height - 1, shapeResolutionLimit / 2 do horizontalLine(xImage, y, mainImage.width, 0.627) end buffer.text(1, 1, 0xBBBBBB, "хуй") end end diff --git a/Applications/RayWalk/RayEngine.cfg b/Applications/RayWalk/RayEngine.cfg index f9bd0b1a..ed061679 100755 --- a/Applications/RayWalk/RayEngine.cfg +++ b/Applications/RayWalk/RayEngine.cfg @@ -3,20 +3,20 @@ ["shadingCascades"] = 8, ["shadingDistance"] = 500, ["shadingTransparencyMap"] = { - [12] = 128, - [6] = 255, - [13] = 102, - [1] = 51, - [3] = 153, - [7] = 255, - [8] = 204, - [4] = 204, - [9] = 204, - [14] = 77, - [2] = 102, - [5] = 255, - [11] = 153, - [10] = 179 + [1] = 0.2, + [2] = 0.4, + [3] = 0.6, + [4] = 0.8, + [5] = 1.0, + [6] = 1.0, + [7] = 1.0, + [8] = 0.8, + [9] = 0.8, + [10] = 0.70196078431373, + [11] = 0.6, + [12] = 0.50196078431373, + [13] = 0.4, + [14] = 0.30196078431373, }, ["raycastQuality"] = 6.4, ["screenResolution"] = { diff --git a/Applications/RayWalk/RayWalk.lua b/Applications/RayWalk/RayWalk.lua index d8629ac8..5a23b627 100755 --- a/Applications/RayWalk/RayWalk.lua +++ b/Applications/RayWalk/RayWalk.lua @@ -1,5 +1,5 @@ --- package.loaded.rayEngine, package.loaded.GUI, package.loaded.windows, _G.rayEngine, _G.GUI, _G.windows = nil, nil, nil, nil, nil, nil, nil, nil +package.loaded.rayEngine, package.loaded.GUI, package.loaded.windows, _G.rayEngine, _G.GUI, _G.windows = nil, nil, nil, nil, nil, nil, nil, nil local fs = require("filesystem") local component = require("component") @@ -164,7 +164,7 @@ rayEngine.loadEngineProperties(applicationResourcesDirectory .. "RayEngine.cfg") rayEngine.loadWeapons(applicationResourcesDirectory .. "Weapons/") rayEngine.loadWorld(worldsPath .. "ExampleWorld") rayEngine.changeResolution(rayEngine.properties.screenResolution.width, rayEngine.properties.screenResolution.height) --- rayEngine.intro() +rayEngine.intro() menu() rayEngine.update() diff --git a/Beta/Cyka.java b/Beta/Cyka.java deleted file mode 100644 index f2095987..00000000 --- a/Beta/Cyka.java +++ /dev/null @@ -1,319 +0,0 @@ -package com.dreamfinity.main.api; - -import net.minecraft.client.Minecraft; -import net.minecraft.util.ResourceLocation; -import org.lwjgl.input.Mouse; - -import java.awt.*; - -/** - * Created by Pirnogion on 19.01.2016. - * SOSI, CYKA - * REKOSTILED BY IGOR - */ - -public class MineButton extends DreamAPI -{ - - private Minecraft mc = DreamAPI.mc; - - public boolean isHover = false; - public boolean isPressed = false; - public boolean visible = true; - public Runnable callback; - public int x = 1; - public int y = 1; - public int width = 10; - public int height = 20; - public String text = ""; - public ButtonStyle style; - public float textSize = 3; - public int padding = (int)(0.1f * this.height); - - //Класс стиля кнопки - public class ButtonStyle { - //Подкласс стиля кнопки в обычном состоянии - public class Standard { - public Color buttonColor; - public Color textColor; - public ResourceLocation texture; - } - - //Подкласс стиля кнопки в состоянии наведения мышью - public class Hovered { - public Color buttonColor; - public Color textColor; - public ResourceLocation texture; - } - - //Подкласс стиля кнопки в состоянии клика мышью - public class Pressed { - public Color buttonColor; - public Color textColor; - public ResourceLocation texture; - } - - //Создаем экземпляры подклассов стилей - public Standard standard = new Standard(); - public Hovered hovered = new Hovered(); - public Pressed pressed = new Pressed(); - public String type; - - //Конструктор класса стиля со всеми флет-параметрами - public ButtonStyle(int buttonColor, int buttonHoverColor, int buttonPressColor, int textColor, int textHoverColor, int textPressColor) { - this.standard.buttonColor = new Color(buttonColor); - this.hovered.buttonColor = new Color(buttonHoverColor); - this.pressed.buttonColor = new Color(buttonPressColor); - - this.standard.textColor = new Color(textColor); - this.hovered.textColor = new Color(textHoverColor); - this.pressed.textColor = new Color(textPressColor); - - this.type = "flat"; - } - - //Конструктор класса стиля со всеми текстурными параметрами - public ButtonStyle(ResourceLocation buttonTexture, ResourceLocation buttonHoverTexture, ResourceLocation buttonPressTexture, int textColor, int textHoverColor, int textPressColor) { - this.standard.texture = buttonTexture; - this.hovered.texture = buttonHoverTexture; - this.pressed.texture = buttonPressTexture; - - this.standard.textColor = new Color(textColor); - this.hovered.textColor = new Color(textHoverColor); - this.pressed.textColor = new Color(textPressColor); - - this.type = "textured"; - } - - //Конструктор класса стиля без параметров, создаются дефолтные цвета - public ButtonStyle() { - this.standard.buttonColor = new Color(0x00A8FF); - this.hovered.buttonColor = new Color(0x42A8ff); - this.pressed.buttonColor = new Color(0xFFFFFF); - - this.standard.textColor = new Color(0xFFFFFF); - this.hovered.textColor = new Color(0xFFFFFF); - this.pressed.textColor = new Color(0x555555); - - this.type = "flat"; - } - } - - //Конструктор кнопки во флет-дизайне со всеми параметрами - public MineButton(int x, int y, int width, int height, int buttonColor, int buttonHoverColor, int buttonPressColor, int textColor, int textHoverColor, int textPressColor, int textSize, String text) - { - this.style = new ButtonStyle(buttonColor, buttonHoverColor, buttonPressColor, textColor, textHoverColor, textPressColor); - this.callback = null; - this.isPressed = false; - this.isHover = false; - this.x = y; - this.y = x; - this.width = width; - this.height = height; - this.text = text; - this.textSize = textSize; - } - - //Конструктор кнопки без аргументов (по умолчанию во флет-дизайне) - public MineButton() - { - this.style = new ButtonStyle(); - this.callback = null; - this.isPressed = false; - this.isHover = false; - this.x = 1; - this.y = 1; - this.width = 200; - this.height = 50; - this.text = "Button"; - this.textSize = 3; - } - - //Отрисовка текста с определенным цветом - private void drawText(Color textColor) { - drawScaledString(this.text, this.x + this.width / 2,this.y + this.height / 2 - (this.textSize * 4), textSize, TextPosition.CENTER, textColor); - //this.drawCenteredString(this.mc.fontRenderer, this.text, this.x + this.width / 2, this.y + (this.height - 8) / 2, RGBtoHEX(textColor)); - } - - //Отрисовка кнопки с определенным цветом - private void drawButton(Color color) - { - square(this.x, this.y, this.width, this.height - this.padding, color); - square(this.x, this.y + this.height - this.padding - 1, this.width, this.padding, alphaBlend(color, Color.black, 180)); - } - - //Функция отрисовки - public void draw(int x, int y) - { - //Eсли кнопка невидимая, то отменить отрисовку - if (!visible) { - return; - } - - //Отрисовка - //Если кликнуто - if ( this.isPressed ) - { - //Рисуем в зависимости от стиля кнопки - if ( this.style.type == "flat" ) - { - drawButton(this.style.pressed.buttonColor); - } - else - { - - } - - //Рисуем текст - drawText(this.style.pressed.textColor); - } - //Если просто наведено мышкой - else if ( isHover ) - { - //Рисуем в зависимости от стиля кнопки - if ( this.style.type == "flat" ) - { - drawButton(this.style.hovered.buttonColor); - } - else - { - - } - - //Рисуем текст - drawText(this.style.hovered.textColor); - } - //Если ни то, ни другое - т.е. обычное состояние кнопки - else - { - //Рисуем в зависимости от стиля кнопки - if ( this.style.type == "flat" ) - { - drawButton(this.style.standard.buttonColor); - } - else - { - - } - - //Рисуем текст - drawText(this.style.standard.textColor); - } - } - - //Обработка - public MineButton update(int x, int y) - { - if (!visible) return this; - - x = x * getScaleFactor(); - y = y * getScaleFactor(); - - isHover = x >= this.x && y >= this.y && x < this.x + this.width && y < this.y + this.height; - - if (isHover && Mouse.isButtonDown(0)) - { - if (!isPressed && callback != null) - { - callback.run(); - } - isPressed = true; - } - else - { - isPressed = false; - } - - //Отрисовываем - this.draw(x, y); - - return this; - } - - //Стиль кнопки во флет-дизайне - public void setStyle(int buttonColor, int buttonHoverColor, int buttonPressColor, int textColor, int textHoverColor, int textPressColor) - { - this.style.type = "flat"; - this.style = new ButtonStyle(buttonColor, buttonHoverColor, buttonPressColor, textColor, textHoverColor, textPressColor); - } - - //Стиль кнопки в текстурном дизайне - public void setStyle(String buttonTexture, String buttonTextureHover, String buttonTexturePress, int textColor, int textHoverColor, int textPressColor) - { - this.style.type = "textured"; - this.style = new ButtonStyle( - new ResourceLocation(buttonTexture), - new ResourceLocation(buttonTextureHover), - new ResourceLocation(buttonTexturePress), - textColor, - textHoverColor, - textPressColor - ); - } - - //Установить размер текста - public void setTextSize(float textSize) - { - this.textSize = textSize; - } - - //Изменить размер кнопки - public void setSize(int width, int height) - { - this.width = width; - this.height = height; - } - - //Изменить расположение кнопки - public void setPosition(int x, int y) - { - this.x = x; - this.y = y; - } - - //Изменить текст кнопки - public void setText(String text) - { - this.text = text; - } - - //Установить функцию, выполняемую при нажатии на кнопку - public void setCallback(Runnable callback) - { - this.callback = callback; - } - - //Установить цвет текста - public void setTextColor(int textColor, int textHoverColor, int textPressColor) - { - this.style.standard.textColor = new Color(textColor); - this.style.hovered.textColor = new Color(textHoverColor); - this.style.pressed.textColor = new Color(textPressColor); - } - - //Установить цвет кнопки для всех стилей одинаково без ебли мозга - public void setTextColor(int color) - { - Color cyka = new Color(color); - this.style.standard.textColor = cyka; - this.style.hovered.textColor = cyka; - this.style.pressed.textColor = cyka; - } - - //Установить цвет кнопки по всем трем стилям - public void setButtonColor(int buttonColor, int buttonHoverColor, int buttonPressColor) - { - this.style.standard.buttonColor = new Color(buttonColor); - this.style.hovered.buttonColor = new Color(buttonHoverColor); - this.style.pressed.buttonColor = new Color(buttonPressColor); - } - - //Установить цвет кнопки для всех стилей одинаково без ебли мозга - public void setButtonColor(int color) - { - Color cyka = new Color(color); - this.style.standard.buttonColor = cyka; - this.style.hovered.buttonColor = cyka; - this.style.pressed.buttonColor = cyka; - } -} diff --git a/Beta/MineCode2/ECSAPI.lua b/Beta/MineCode2/ECSAPI.lua deleted file mode 100644 index 557e7a26..00000000 --- a/Beta/MineCode2/ECSAPI.lua +++ /dev/null @@ -1,2424 +0,0 @@ - --- Адаптивная загрузка необходимых библиотек и компонентов -local libraries = { - ["component"] = "component", - ["term"] = "term", - ["unicode"] = "unicode", - ["event"] = "event", - ["fs"] = "filesystem", - ["shell"] = "shell", - ["keyboard"] = "keyboard", - ["computer"] = "computer", - ["serialization"] = "serialization", - ["colorlib"] = "colorlib", - --["internet"] = "internet", - --["image"] = "image", -} - -local components = { - ["gpu"] = "gpu", -} - -for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end -for comp in pairs(components) do if not _G[comp] then _G[comp] = _G.component[components[comp]] end end -libraries, components = nil, nil - -local ECSAPI = {} - ----------------------------------------------------------------------------------------------------- - -ECSAPI.windowColors = { - background = 0xeeeeee, - usualText = 0x444444, - subText = 0x888888, - tab = 0xaaaaaa, - title = 0xffffff, - shadow = 0x444444, -} - -ECSAPI.colors = { - white = 0xffffff, - orange = 0xF2B233, - magenta = 0xE57FD8, - lightBlue = 0x99B2F2, - yellow = 0xDEDE6C, - lime = 0x7FCC19, - pink = 0xF2B2CC, - gray = 0x4C4C4C, - lightGray = 0x999999, - cyan = 0x4C99B2, - purple = 0xB266E5, - blue = 0x3366CC, - brown = 0x7F664C, - green = 0x57A64E, - red = 0xCC4C4C, - black = 0x000000, - ["0"] = 0xffffff, - ["1"] = 0xF2B233, - ["2"] = 0xE57FD8, - ["3"] = 0x99B2F2, - ["4"] = 0xDEDE6C, - ["5"] = 0x7FCC19, - ["6"] = 0xF2B2CC, - ["7"] = 0x4C4C4C, - ["8"] = 0x999999, - ["9"] = 0x4C99B2, - ["a"] = 0xB266E5, - ["b"] = 0x3366CC, - ["c"] = 0x7F664C, - ["d"] = 0x57A64E, - ["e"] = 0xCC4C4C, - ["f"] = 0x000000 -} - ----------------------------------------------------------------------------------------------------- - ---Установка масштаба монитора -function ECSAPI.setScale(scale, debug) - --Базовая коррекция масштаба, чтобы всякие умники не писали своими погаными ручонками, чего не следует - if scale > 1 then - scale = 1 - elseif scale < 0.1 then - scale = 0.1 - end - - --Просчет монитора в псевдопикселях - забей, даже объяснять не буду, работает как часы - local function calculateAspect(screens) - local abc = 12 - - if screens == 2 then - abc = 28 - elseif screens > 2 then - abc = 28 + (screens - 2) * 16 - end - - return abc - end - - --Рассчитываем пропорцию монитора в псевдопикселях - local xScreens, yScreens = component.screen.getAspectRatio() - local xPixels, yPixels = calculateAspect(xScreens), calculateAspect(yScreens) - local proportion = xPixels / yPixels - - --Получаем максимально возможное разрешение данной видеокарты - local xMax, yMax = gpu.maxResolution() - - --Получаем теоретическое максимальное разрешение монитора с учетом его пропорции, но без учета лимита видеокарты - local newWidth, newHeight - if proportion >= 1 then - newWidth = math.floor(xMax) - newHeight = math.floor(newWidth / proportion / 2) - else - newHeight = math.floor(yMax) - newWidth = math.floor(newHeight * proportion * 2) - end - - --Получаем оптимальное разрешение для данного монитора с поддержкой видеокарты - local optimalNewWidth, optimalNewHeight = newWidth, newHeight - - if optimalNewWidth > xMax then - local difference = optimalNewWidth - xMax - optimalNewWidth = xMax - optimalNewHeight = optimalNewHeight - math.ceil(difference / 2 ) - end - - if optimalNewHeight > yMax then - local difference = optimalNewHeight - yMax - optimalNewHeight = yMax - --optimalNewWidth = optimalNewWidth - difference * 2 - math.ceil(difference / 2) - optimalNewWidth = optimalNewWidth - difference * 2 - end - - --Корректируем идеальное разрешение по заданному масштабу - local finalNewWidth, finalNewHeight = math.floor(optimalNewWidth * scale), math.floor(optimalNewHeight * scale) - - --Выводим инфу, если нужно - if debug then - print(" ") - print("Максимальное разрешение: "..xMax.."x"..yMax) - print("Пропорция монитора: "..xPixels.."x"..yPixels) - print("Коэффициент пропорции: "..proportion) - print(" ") - print("Теоретическое разрешение: "..newWidth.."x"..newHeight) - print("Оптимизированное разрешение: "..optimalNewWidth.."x"..optimalNewHeight) - print(" ") - print("Новое разрешение: "..finalNewWidth.."x"..finalNewHeight) - print(" ") - end - - --Устанавливаем выбранное разрешение - gpu.setResolution(finalNewWidth, finalNewHeight) -end - -function ECSAPI.rebindGPU(address) - gpu.bind(address) -end - ---Получаем всю инфу об оперативку в килобайтах -function ECSAPI.getInfoAboutRAM() - local free = math.floor(computer.freeMemory() / 1024) - local total = math.floor(computer.totalMemory() / 1024) - local used = total - free - - return free, total, used -end - ---Получить информацию о жестких дисках -function ECSAPI.getHDDs() - local candidates = {} - for address in component.list("filesystem") do - local proxy = component.proxy(address) - if proxy.address ~= computer.tmpAddress() and proxy.getLabel() ~= "internet" then - local isFloppy, spaceTotal = false, math.floor(proxy.spaceTotal() / 1024) - if spaceTotal < 600 then isFloppy = true end - table.insert(candidates, { - ["spaceTotal"] = spaceTotal, - ["spaceUsed"] = math.floor(proxy.spaceUsed() / 1024), - ["label"] = proxy.getLabel(), - ["address"] = proxy.address, - ["isReadOnly"] = proxy.isReadOnly(), - ["isFloppy"] = isFloppy, - }) - end - end - return candidates -end - ---Форматировать диск -function ECSAPI.formatHDD(address) - local proxy = component.proxy(address) - local list = proxy.list("") - ECSAPI.info("auto", "auto", "", "Formatting disk...") - for _, file in pairs(list) do - if type(file) == "string" then - if not proxy.isReadOnly(file) then proxy.remove(file) end - end - end - list = nil -end - ---Установить имя жесткого диска -function ECSAPI.setHDDLabel(address, label) - local proxy = component.proxy(address) - proxy.setLabel(label or "Untitled") -end - ---Найти монтированный путь конкретного адреса диска -function ECSAPI.findMount(address) - for fs1, path in fs.mounts() do - if fs1.address == component.get(address) then - return path - end - end -end - ---Скопировать файлы с одного диска на другой с заменой -function ECSAPI.duplicateFileSystem(fromAddress, toAddress) - local source, destination = ECSAPI.findMount(fromAddress), ECSAPI.findMount(toAddress) - ECSAPI.info("auto", "auto", "", "Copying file system...") - shell.execute("bin/cp -rx "..source.."* "..destination) -end - ---Загрузка файла с инета -function ECSAPI.getFileFromUrl(url, path) - if not _G.internet then _G.internet = require("internet") end - local sContent = "" - local result, response = pcall(internet.request, url) - if not result then - ECSAPI.error("Could not connect to to URL address \"" .. url .. "\"") - return - end - - fs.remove(path) - fs.makeDirectory(fs.path(path)) - local file = io.open(path, "w") - - for chunk in response do - file:write(chunk) - sContent = sContent .. chunk - end - - file:close() - - return sContent -end - ---Загрузка файла с пастебина -function ECSAPI.getFromPastebin(paste, path) - local url = "http://pastebin.com/raw.php?i=" .. paste - ECSAPI.getFileFromUrl(url, path) -end - ---Загрузка файла с гитхаба -function ECSAPI.getFromGitHub(url, path) - url = "https://raw.githubusercontent.com/" .. url - ECSAPI.getFileFromUrl(url, path) -end - ---Загрузить ОС-приложение -function ECSAPI.getOSApplication(elementFromMassiv) - --Удаляем старый файл и получаем путь - local path = elementFromMassiv.name - fs.remove(path) - --Если тип = приложение - if elementFromMassiv.type == "Application" then - fs.makeDirectory(path .. ".app/Resources") - ECSAPI.getFromGitHub(elementFromMassiv.url, path .. ".app/" .. fs.name(elementFromMassiv.name .. ".lua")) - ECSAPI.getFromGitHub(elementFromMassiv.icon, path .. ".app/Resources/Icon.pic") - if elementFromMassiv.resources then - for i = 1, #elementFromMassiv.resources do - ECSAPI.getFromGitHub(elementFromMassiv.resources[i].url, path .. ".app/Resources/" .. elementFromMassiv.resources[i].name) - end - end - --А если че-то другое - else - ECSAPI.getFromGitHub(elementFromMassiv.url, path) - end -end - ---Получить список приложений, которые требуется обновить -function ECSAPI.getAppsToUpdate(debug) - --Задаем стартовые пути - local pathToApplicationsFile = "MineOS/System/OS/Applications.txt" - local pathToSecondApplicationsFile = "MineOS/System/OS/Applications2.txt" - --Путь к файл-листу на пастебине - local paste = "3j2x4dDn" - --Выводим инфу - local oldPixels - if debug then oldPixels = ECSAPI.info("auto", "auto", " ", "Checking for updates...") end - --Получаем свеженький файл - ECSAPI.getFromPastebin(paste, pathToSecondApplicationsFile) - --Читаем оба файла - local file = io.open(pathToApplicationsFile, "r") - local applications = serialization.unserialize(file:read("*a")) - file:close() - --И второй - file = io.open(pathToSecondApplicationsFile, "r") - local applications2 = serialization.unserialize(file:read("*a")) - file:close() - - local countOfUpdates = 0 - - --Просматриваем свеженький файлик и анализируем, че в нем нового, все старое удаляем - local i = 1 - while true do - --Разрыв цикла - if i > #applications2 then break end - --Новая версия файла - local newVersion, oldVersion = applications2[i].version, 0 - --Получаем старую версию этого файла - for j = 1, #applications do - if applications2[i].name == applications[j].name then - oldVersion = applications[j].version or 0 - break - end - end - --Если новая версия новее, чем старая, то добавить в массив то, что нужно обновить - if newVersion > oldVersion then - applications2[i].needToUpdate = true - countOfUpdates = countOfUpdates + 1 - end - - i = i + 1 - end - --Если чет рисовалось, то стереть на хер - if oldPixels then ECSAPI.drawOldPixels(oldPixels) end - --Возвращаем массив с тем, че нужно обновить и просто старый аппликашнс на всякий случай - return applications2, countOfUpdates -end - ---Сделать строку пригодной для отображения в ОпенКомпах -function ECSAPI.stringOptimize(sto4ka, indentatonWidth) - indentatonWidth = indentatonWidth or 2 - sto4ka = string.gsub(sto4ka, "\r\n", "\n") - sto4ka = string.gsub(sto4ka, " ", string.rep(" ", indentatonWidth)) - return stro4ka -end - ---ИЗ ДЕСЯТИЧНОЙ В ШЕСТНАДЦАТИРИЧНУЮ -function ECSAPI.decToBase(IN,BASE) - local hexCode = "0123456789ABCDEFGHIJKLMNOPQRSTUVW" - OUT = "" - local ostatok = 0 - while IN>0 do - ostatok = math.fmod(IN,BASE) + 1 - IN = math.floor(IN/BASE) - OUT = string.sub(hexCode,ostatok,ostatok)..OUT - end - if #OUT == 1 then OUT = "0"..OUT end - if OUT == "" then OUT = "00" end - return OUT -end - ---Правильное конвертирование HEX-переменной в строковую -function ECSAPI.HEXtoString(color, bitCount, withNull) - local stro4ka = string.format("%X",color) - local sStro4ka = unicode.len(stro4ka) - if sStro4ka < bitCount then - stro4ka = string.rep("0", bitCount - sStro4ka) .. stro4ka - end - sStro4ka = nil - if withNull then return "0x"..stro4ka else return stro4ka end -end - ---КЛИКНУЛИ ЛИ В ЗОНУ -function ECSAPI.clickedAtArea(x,y,sx,sy,ex,ey) - if (x >= sx) and (x <= ex) and (y >= sy) and (y <= ey) then return true end - return false -end - ---Заливка всего экрана указанным цветом -function ECSAPI.clearScreen(color) - if color then gpu.setBackground(color) end - term.clear() -end - ---Установка пикселя нужного цвета -function ECSAPI.setPixel(x,y,color) - gpu.setBackground(color) - gpu.set(x,y," ") -end - ---Простая установка цветов в одну строку, ибо я ленивый -function ECSAPI.setColor(background, foreground) - gpu.setBackground(background) - gpu.setForeground(foreground) -end - ---Цветной текст -function ECSAPI.colorText(x,y,textColor,text) - gpu.setForeground(textColor) - gpu.set(x,y,text) -end - ---Цветной текст с жопкой! -function ECSAPI.colorTextWithBack(x,y,textColor,backColor,text) - gpu.setForeground(textColor) - gpu.setBackground(backColor) - gpu.set(x,y,text) -end - ---Инверсия цвета -function ECSAPI.invertColor(color) - return 0xffffff - color -end - ---Адаптивный текст, подстраивающийся под фон -function ECSAPI.adaptiveText(x,y,text,textColor) - gpu.setForeground(textColor) - x = x - 1 - for i=1,unicode.len(text) do - local info = {gpu.get(x+i,y)} - gpu.setBackground(info[3]) - gpu.set(x+i,y,unicode.sub(text,i,i)) - end -end - ---Костыльная замена обычному string.find() ---Работает медленнее, но хотя бы поддерживает юникод -function unicode.find(str, pattern, init, plain) - if init then - if init < 0 then - init = -#unicode.sub(str,init) - elseif init > 0 then - init = #unicode.sub(str,1,init-1)+1 - end - end - - a, b = string.find(str, pattern, init, plain) - - if a then - local ap,bp = str:sub(1,a-1), str:sub(a,b) - a = unicode.len(ap)+1 - b = a + unicode.len(bp)-1 - return a,b - else - return a - end -end - ---Умный текст по аналогии с майнчатовским. Ставишь символ параграфа, указываешь хуйню - и хуякс! Работает! -function ECSAPI.smartText(x, y, text) - local sText = unicode.len(text) - local specialSymbol = "§" - --Разбираем по кусочкам строку и получаем цвета - local massiv = {} - local iterator = 1 - local currentColor = gpu.getForeground() - while iterator <= sText do - local symbol = unicode.sub(text, iterator, iterator) - if symbol == specialSymbol then - currentColor = ECSAPI.colors[unicode.sub(text, iterator + 1, iterator + 1) or "f"] - iterator = iterator + 1 - else - table.insert(massiv, {symbol, currentColor}) - end - symbol = nil - iterator = iterator + 1 - end - x = x - 1 - for i = 1, #massiv do - if currentColor ~= massiv[i][2] then currentColor = massiv[i][2]; gpu.setForeground(massiv[i][2]) end - gpu.set(x + i, y, massiv[i][1]) - end -end - ---Аналог умного текста, но использующий HEX-цвета для кодировки -function ECSAPI.formattedText(x, y, text, limit) - --Ограничение длины строки - limit = limit or math.huge - --Стартовая позиция курсора для отрисовки - local xPos = x - --Создаем массив символов данной строки - local symbols = {} - for i = 1, unicode.len(text) do table.insert(symbols, unicode.sub(text, i, i)) end - --Перебираем все символы строки, пока не переберем все или не достигнем указанного лимита - local i = 1 - while i <= #symbols and i <= limit do - --Если находим символ параграфа, то - if symbols[i] == "§" then - --Меняем цвет текста на указанный - gpu.setForeground(tonumber("0x" .. symbols[i+1] .. symbols[i+2] .. symbols[i+3] .. symbols[i+4] .. symbols[i+5] .. symbols[i+6])) - --Увеличиваем лимит на 7, т.к. - limit = limit + 7 - --Сдвигаем итератор цикла на 7 - i = i + 7 - end - --Рисуем символ на нужной позиции - gpu.set(xPos, y, symbols[i]) - --Увеличиваем позицию курсора и итератор на 1 - xPos = xPos + 1 - i = i + 1 - end -end - ---Инвертированный текст на основе цвета фона -function ECSAPI.invertedText(x,y,symbol) - local info = {gpu.get(x,y)} - ECSAPI.adaptiveText(x,y,symbol,ECSAPI.invertColor(info[3])) -end - ---Адаптивное округление числа -function ECSAPI.adaptiveRound(chislo) - local celaya,drobnaya = math.modf(chislo) - if drobnaya >= 0.5 then - return (celaya + 1) - else - return celaya - end -end - ---Округление до опред. кол-ва знаков после запятой -function ECSAPI.round(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult -end - ---Обычный квадрат указанного цвета -function ECSAPI.square(x,y,width,height,color) - gpu.setBackground(color) - gpu.fill(x,y,width,height," ") -end - ---Юникодовская рамка -function ECSAPI.border(x, y, width, height, back, fore) - local stringUp = "┌"..string.rep("─", width - 2).."┐" - local stringDown = "└"..string.rep("─", width - 2).."┘" - gpu.setForeground(fore) - gpu.setBackground(back) - gpu.set(x, y, stringUp) - gpu.set(x, y + height - 1, stringDown) - - local yPos = 1 - for i = 1, (height - 2) do - gpu.set(x, y + yPos, "│") - gpu.set(x + width - 1, y + yPos, "│") - yPos = yPos + 1 - end -end - ---Кнопка в виде текста в рамке -function ECSAPI.drawFramedButton(x, y, width, height, text, color) - ECSAPI.border(x, y, width, height, gpu.getBackground(), color) - gpu.fill(x + 1, y + 1, width - 2, height - 2, " ") - x = x + math.floor(width / 2 - unicode.len(text) / 2) - y = y + math.floor(width / 2 - 1) - gpu.set(x, y, text) -end - ---Юникодовский разделитель -function ECSAPI.separator(x, y, width, back, fore) - ECSAPI.colorTextWithBack(x, y, fore, back, string.rep("─", width)) -end - ---Автоматическое центрирование текста по указанной координате (x, y, xy) -function ECSAPI.centerText(mode,coord,text) - local dlina = unicode.len(text) - local xSize,ySize = gpu.getResolution() - - if mode == "x" then - gpu.set(math.floor(xSize/2-dlina/2),coord,text) - elseif mode == "y" then - gpu.set(coord,math.floor(ySize/2),text) - else - gpu.set(math.floor(xSize/2-dlina/2),math.floor(ySize/2),text) - end -end - ---Отрисовка "изображения" по указанному массиву -function ECSAPI.drawCustomImage(x,y,pixels) - x = x - 1 - y = y - 1 - local pixelsWidth = #pixels[1] - local pixelsHeight = #pixels - local xEnd = x + pixelsWidth - local yEnd = y + pixelsHeight - - for i=1,pixelsHeight do - for j=1,pixelsWidth do - if pixels[i][j][3] ~= "#" then - gpu.setBackground(pixels[i][j][1]) - gpu.setForeground(pixels[i][j][2]) - gpu.set(x+j,y+i,pixels[i][j][3]) - end - end - end - - return (x+1),(y+1),xEnd,yEnd -end - ---Корректировка стартовых координат. Core-функция для всех моих программ -function ECSAPI.correctStartCoords(xStart,yStart,xWindowSize,yWindowSize) - local xSize,ySize = gpu.getResolution() - if xStart == "auto" then - xStart = math.floor(xSize/2 - xWindowSize/2) - end - if yStart == "auto" then - yStart = math.ceil(ySize/2 - yWindowSize/2) - end - return xStart,yStart -end - ---Запомнить область пикселей и возвратить ее в виде массива -function ECSAPI.rememberOldPixels(x, y, x2, y2) - local newPNGMassiv = { ["backgrounds"] = {} } - local xSize, ySize = gpu.getResolution() - newPNGMassiv.x, newPNGMassiv.y = x, y - - --Перебираем весь массив стандартного PNG-вида по высоте - local xCounter, yCounter = 1, 1 - for j = y, y2 do - xCounter = 1 - for i = x, x2 do - - if (i > xSize or i < 0) or (j > ySize or j < 0) then - error("Can't remember pixel, because it's located behind the screen: x("..i.."), y("..j..") out of xSize("..xSize.."), ySize("..ySize..")\n") - end - - local symbol, fore, back = gpu.get(i, j) - - newPNGMassiv["backgrounds"][back] = newPNGMassiv["backgrounds"][back] or {} - newPNGMassiv["backgrounds"][back][fore] = newPNGMassiv["backgrounds"][back][fore] or {} - - table.insert(newPNGMassiv["backgrounds"][back][fore], {xCounter, yCounter, symbol} ) - - xCounter = xCounter + 1 - back, fore, symbol = nil, nil, nil - end - - yCounter = yCounter + 1 - end - - xSize, ySize = nil, nil - return newPNGMassiv -end - ---Нарисовать запомненные ранее пиксели из массива -function ECSAPI.drawOldPixels(massivSudaPihay) - --Перебираем массив с фонами - for back, backValue in pairs(massivSudaPihay["backgrounds"]) do - gpu.setBackground(back) - for fore, foreValue in pairs(massivSudaPihay["backgrounds"][back]) do - gpu.setForeground(fore) - for pixel = 1, #massivSudaPihay["backgrounds"][back][fore] do - if massivSudaPihay["backgrounds"][back][fore][pixel][3] ~= transparentSymbol then - gpu.set(massivSudaPihay.x + massivSudaPihay["backgrounds"][back][fore][pixel][1] - 1, massivSudaPihay.y + massivSudaPihay["backgrounds"][back][fore][pixel][2] - 1, massivSudaPihay["backgrounds"][back][fore][pixel][3]) - end - end - end - end -end - ---Ограничение длины строки. Маст-хев функция. -function ECSAPI.stringLimit(mode, text, size, noDots) - if unicode.len(text) <= size then return text end - local length = unicode.len(text) - if mode == "start" then - if noDots then - return unicode.sub(text, length - size + 1, -1) - else - return "…" .. unicode.sub(text, length - size + 2, -1) - end - else - if noDots then - return unicode.sub(text, 1, size) - else - return unicode.sub(text, 1, size - 1) .. "…" - end - end -end - ---Получить текущее реальное время компьютера, хостящего сервер майна -function ECSAPI.getHostTime(timezone) - timezone = timezone or 2 - --Создаем файл с записанной в него парашей - local file = io.open("HostTime.tmp", "w") - file:write("") - file:close() - --Коррекция времени на основе часового пояса - local timeCorrection = timezone * 3600 - --Получаем дату изменения файла в юникс-виде - local lastModified = tonumber(string.sub(fs.lastModified("HostTime.tmp"), 1, -4)) + timeCorrection - --Удаляем файл, ибо на хуй он нам не нужен - fs.remove("HostTime.tmp") - --Конвертируем юникс-время в норм время - local year, month, day, hour, minute, second = os.date("%Y", lastModified), os.date("%m", lastModified), os.date("%d", lastModified), os.date("%H", lastModified), os.date("%M", lastModified), os.date("%S", lastModified) - --Возвращаем все - return tonumber(day), tonumber(month), tonumber(year), tonumber(hour), tonumber(minute), tonumber(second) -end - ---Получить спискок файлов из конкретной директории, костыль -function ECSAPI.getFileList(path) - local list = fs.list(path) - local massiv = {} - for file in list do - --if string.find(file, "%/$") then file = unicode.sub(file, 1, -2) end - table.insert(massiv, file) - end - list = nil - return massiv -end - ---Получить файловое древо. Сильно нагружает систему, только для дебага! -function ECSAPI.getFileTree(path) - local massiv = {} - local list = ECSAPI.getFileList(path) - for key, file in pairs(list) do - if fs.isDirectory(path.."/"..file) then - table.insert(massiv, getFileTree(path.."/"..file)) - else - table.insert(massiv, file) - end - end - list = nil - - return massiv -end - ---Поиск по файловой системе -function ECSAPI.find(path, cheBudemIskat) - --Массив, в котором будут находиться все найденные соответствия - local massivNaydennogoGovna = {} - --Костыль, но удобный - local function dofind(path, cheBudemIskat) - --Получаем список файлов в директории - local list = ECSAPI.getFileList(path) - --Перебираем все элементы файл листа - for key, file in pairs(list) do - --Путь к файлу - local pathToFile = path..file - --Если нашло совпадение в имени файла, то выдает путь к этому файлу - if string.find(unicode.lower(file), unicode.lower(cheBudemIskat)) then - table.insert(massivNaydennogoGovna, pathToFile) - end - --Анализ, что делать дальше - if fs.isDirectory(pathToFile) then - dofind(pathToFile, cheBudemIskat) - end - --Очищаем оперативку - pathToFile = nil - end - --Очищаем оперативку - list = nil - end - --Выполняем функцию - dofind(path, cheBudemIskat) - --Возвращаем, че нашло - return massivNaydennogoGovna -end - ---Получение формата файла -function ECSAPI.getFileFormat(path) - local name = fs.name(path) - local starting, ending = string.find(name, "(.)%.[%d%w]*$") - if starting == nil then - return nil - else - return unicode.sub(name,starting + 1, -1) - end - name, starting, ending = nil, nil, nil -end - ---Проверить, скрытый ли файл (.пидор, .хуй = true; пидор, хуй = false) -function ECSAPI.isFileHidden(path) - local name = fs.name(path) - local starting, ending = string.find(name, "^%.(.*)$") - if starting == nil then - return false - else - return true - end - name, starting, ending = nil, nil, nil -end - ---Скрыть формат файла -function ECSAPI.hideFileFormat(path) - local name = fs.name(path) - local fileFormat = ECSAPI.getFileFormat(name) - if fileFormat == nil then - return name - else - return unicode.sub(name, 1, unicode.len(name) - unicode.len(fileFormat)) - end -end - ---Ожидание клика либо нажатия какой-либо клавиши -function ECSAPI.waitForTouchOrClick() - while true do - local e = { event.pull() } - if e[1] == "key_down" or e[1] == "touch" then break end - end -end - ---То же самое, но в сокращенном варианте -function ECSAPI.wait() - ECSAPI.waitForTouchOrClick() -end - ---Нарисовать кнопочки закрытия окна -function ECSAPI.drawCloses(x, y, active) - local symbol = "⮾" - ECSAPI.colorText(x, y , (active == 1 and ECSAPI.colors.blue) or 0xCC4C4C, symbol) - ECSAPI.colorText(x + 2, y , (active == 2 and ECSAPI.colors.blue) or 0xDEDE6C, symbol) - ECSAPI.colorText(x + 4, y , (active == 3 and ECSAPI.colors.blue) or 0x57A64E, symbol) -end - ---Нарисовать верхнюю оконную панель с выбором объектов -function ECSAPI.drawTopBar(x, y, width, selectedObject, background, foreground, ...) - local objects = { ... } - ECSAPI.square(x, y, width, 3, background) - local widthOfObjects = 0 - local spaceBetween = 2 - for i = 1, #objects do - widthOfObjects = widthOfObjects + unicode.len(objects[i][1]) + spaceBetween - end - local xPos = x + math.floor(width / 2 - widthOfObjects / 2) - for i = 1, #objects do - if i == selectedObject then - ECSAPI.square(xPos, y, unicode.len(objects[i][1]) + spaceBetween, 3, ECSAPI.colors.blue) - gpu.setForeground(0xffffff) - else - gpu.setBackground(background) - gpu.setForeground(foreground) - end - gpu.set(xPos + spaceBetween / 2, y + 2, objects[i][1]) - gpu.set(xPos + math.ceil(unicode.len(objects[i][1]) / 2), y + 1, objects[i][2]) - - xPos = xPos + unicode.len(objects[i][1]) + spaceBetween - end -end - ---Нарисовать топ-меню, горизонтальная полоска такая с текстами -function ECSAPI.drawTopMenu(x, y, width, color, selectedObject, ...) - local objects = { ... } - local objectsToReturn = {} - local xPos = x + 2 - local spaceBetween = 2 - ECSAPI.square(x, y, width, 1, color) - for i = 1, #objects do - if i == selectedObject then - ECSAPI.square(xPos - 1, y, unicode.len(objects[i][1]) + spaceBetween, 1, ECSAPI.colors.blue) - gpu.setForeground(0xffffff) - gpu.set(xPos, y, objects[i][1]) - gpu.setForeground(objects[i][2]) - gpu.setBackground(color) - else - if gpu.getForeground() ~= objects[i][2] then gpu.setForeground(objects[i][2]) end - gpu.set(xPos, y, objects[i][1]) - end - objectsToReturn[objects[i][1]] = { xPos, y, xPos + unicode.len(objects[i][1]) - 1, y, i } - xPos = xPos + unicode.len(objects[i][1]) + spaceBetween - end - return objectsToReturn -end - ---Функция отрисовки кнопки указанной ширины -function ECSAPI.drawButton(x,y,width,height,text,backColor,textColor) - x,y = ECSAPI.correctStartCoords(x,y,width,height) - - local textPosX = math.floor(x + width / 2 - unicode.len(text) / 2) - local textPosY = math.floor(y + height / 2) - ECSAPI.square(x,y,width,height,backColor) - ECSAPI.colorText(textPosX,textPosY,textColor,text) - - return x, y, (x + width - 1), (y + height - 1) -end - ---Отрисовка кнопки с указанными отступами от текста -function ECSAPI.drawAdaptiveButton(x,y,offsetX,offsetY,text,backColor,textColor) - local length = unicode.len(text) - local width = offsetX*2 + length - local height = offsetY*2 + 1 - - x,y = ECSAPI.correctStartCoords(x,y,width,height) - - ECSAPI.square(x,y,width,height,backColor) - ECSAPI.colorText(x+offsetX,y+offsetY,textColor,text) - - return x,y,(x+width-1),(y+height-1) -end - ---Отрисовка оконной "тени" -function ECSAPI.windowShadow(x,y,width,height) - gpu.setBackground(ECSAPI.windowColors.shadow) - gpu.fill(x+width,y+1,2,height," ") - gpu.fill(x+1,y+height,width,1," ") -end - ---Просто белое окошко с тенью -function ECSAPI.blankWindow(x,y,width,height) - local oldPixels = ECSAPI.rememberOldPixels(x,y,x+width+1,y+height) - - ECSAPI.square(x,y,width,height,ECSAPI.windowColors.background) - - ECSAPI.windowShadow(x,y,width,height) - - return oldPixels -end - ---Белое окошко, но уже с титлом вверху! -function ECSAPI.emptyWindow(x,y,width,height,title) - - local oldPixels = ECSAPI.rememberOldPixels(x,y,x+width+1,y+height) - - --ОКНО - gpu.setBackground(ECSAPI.windowColors.background) - gpu.fill(x,y+1,width,height-1," ") - - --ТАБ СВЕРХУ - gpu.setBackground(ECSAPI.windowColors.tab) - gpu.fill(x,y,width,1," ") - - --ТИТЛ - gpu.setForeground(ECSAPI.windowColors.title) - local textPosX = x + math.floor(width/2-unicode.len(title)/2) -1 - gpu.set(textPosX,y,title) - - --ТЕНЬ - ECSAPI.windowShadow(x,y,width,height) - - return oldPixels - -end - ---Функция по переносу слов на новую строку в зависимости от ограничения по ширине -function ECSAPI.stringWrap(strings, limit) - local massiv = {} - - --Перебираем все указанные строки - for i = 1, #strings do - - --Создаем массив слов данной строки - local words = {} - for match in string.gmatch(strings[i], "[^%s]+") do table.insert(words, match) end - - --Если длина слов не превышает лимита - if unicode.len(strings[i]) <= limit then - table.insert(massiv, table.concat(words, " ")) - else - --Перебираем все слова данной строки с 1 до конца - local from = 1 - local to = 1 - while to <= #words do - --Если длина соединенных слов превышает лимит, то - if unicode.len(table.concat(words, " ", from, to)) > limit then - --Вставить в новый массив строк - table.insert(massiv, table.concat(words, " ", from, to - 1)) - from = to - else - if to == #words then - table.insert(massiv, table.concat(words, " ", from, to)) - end - end - - to = to + 1 - end - end - end - - return massiv -end - ---Моя любимая функция ошибки C: -function ECSAPI.error(...) - local args = {...} - local text = "" - if #args > 1 then - for i = 1, #args do - --text = text .. "[" .. i .. "] = " .. tostring(args[i]) - if type(args[i]) == "string" then args[i] = "\"" .. args[i] .. "\"" end - text = text .. tostring(args[i]) - if i ~= #args then text = text .. ", " end - end - else - text = tostring(args[1]) - end - ECSAPI.universalWindow("auto", "auto", math.ceil(gpu.getResolution() * 0.45), ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x880000, "Ошибка!"}, {"EmptyLine"}, {"WrappedText", 0x262626, text}, {"EmptyLine"}, {"Button", {0x880000, 0xffffff, "OK!"}}) -end - ---Очистить экран, установить комфортные цвета и поставить курсок на 1, 1 -function ECSAPI.prepareToExit(color1, color2) - ECSAPI.clearScreen(color1 or 0x333333) - gpu.setForeground(color2 or 0xffffff) - gpu.set(1, 1, "") -end - ---Конвертация из юникода в символ. Вроде норм, а вроде и не норм. Но полезно. -function ECSAPI.convertCodeToSymbol(code) - local symbol - if code ~= 0 and code ~= 13 and code ~= 8 and code ~= 9 and code ~= 200 and code ~= 208 and code ~= 203 and code ~= 205 and not keyboard.isControlDown() then - symbol = unicode.char(code) - if keyboard.isShiftPressed then symbol = unicode.upper(symbol) end - end - return symbol -end - ---Шкала прогресса - маст-хев! -function ECSAPI.progressBar(x, y, width, height, background, foreground, percent) - local activeWidth = math.ceil(width * percent / 100) - ECSAPI.square(x, y, width, height, background) - ECSAPI.square(x, y, activeWidth, height, foreground) -end - ---Окошко с прогрессбаром! Давно хотел -function ECSAPI.progressWindow(x, y, width, percent, text) - local height = 6 - local barWidth = width - 6 - - x, y = ECSAPI.correctStartCoords(x, y, width, height) - - ECSAPI.emptyWindow(x, y, width, height, " ") - ECSAPI.colorTextWithBack(x + math.floor(width / 2 - unicode.len(text) / 2), y + 4, 0x000000, ECSAPI.windowColors.background, text) - ECSAPI.progressBar(x + 3, y + 2, barWidth, 1, 0xCCCCCC, ECSAPI.colors.blue, percent) -end - ---Функция для ввода текста в мини-поле. -function ECSAPI.inputText(x, y, limit, cheBiloVvedeno, background, foreground, justDrawNotEvent, maskTextWith) - limit = limit or 10 - cheBiloVvedeno = cheBiloVvedeno or "" - background = background or 0xffffff - foreground = foreground or 0x000000 - - gpu.setBackground(background) - gpu.setForeground(foreground) - gpu.fill(x, y, limit, 1, " ") - - local text = cheBiloVvedeno - - local function draw() - term.setCursorBlink(false) - - local dlina = unicode.len(text) - local xCursor = x + dlina - if xCursor > (x + limit - 1) then xCursor = (x + limit - 1) end - - if maskTextWith then - gpu.set(x, y, ECSAPI.stringLimit("start", string.rep("●", dlina), limit)) - else - gpu.set(x, y, ECSAPI.stringLimit("start", text, limit)) - end - - term.setCursor(xCursor, y) - - term.setCursorBlink(true) - end - - draw() - - if justDrawNotEvent then term.setCursorBlink(false); return cheBiloVvedeno end - - while true do - local e = {event.pull()} - if e[1] == "key_down" then - if e[4] == 14 then - term.setCursorBlink(false) - text = unicode.sub(text, 1, -2) - if unicode.len(text) < limit then gpu.set(x + unicode.len(text), y, " ") end - draw() - elseif e[4] == 28 then - term.setCursorBlink(false) - return text - else - local symbol = ECSAPI.convertCodeToSymbol(e[3]) - if symbol then - text = text..symbol - draw() - end - end - elseif e[1] == "touch" then - term.setCursorBlink(false) - return text - elseif e[1] == "clipboard" then - if e[3] then - text = text..e[3] - draw() - end - end - end -end - ---Функция парсинга сообщения об ошибке. Конвертирует из строки в массив и переводит на русский. -function ECSAPI.parseErrorMessage(error, translate) - - local parsedError = {} - - --ПОИСК ЭНТЕРОВ - local starting, ending, searchFrom = nil, nil, 1 - for i = 1, unicode.len(error) do - starting, ending = string.find(error, "\n", searchFrom) - if starting then - table.insert(parsedError, unicode.sub(error, searchFrom, starting - 1)) - searchFrom = ending + 1 - else - break - end - end - - --На всякий случай, если сообщение об ошибке без энтеров вообще, т.е. однострочное - if #parsedError == 0 and error ~= "" and error ~= nil and error ~= " " then - table.insert(parsedError, error) - end - - --Замена /r/n и табсов - for i = 1, #parsedError do - parsedError[i] = string.gsub(parsedError[i], "\r\n", "\n") - parsedError[i] = string.gsub(parsedError[i], " ", " ") - end - - if translate then - for i = 1, #parsedError do - parsedError[i] = string.gsub(parsedError[i], "interrupted", "Выполнение программы прервано пользователем") - parsedError[i] = string.gsub(parsedError[i], " got ", " получена ") - parsedError[i] = string.gsub(parsedError[i], " expected,", " ожидается,") - parsedError[i] = string.gsub(parsedError[i], "bad argument #", "Неверный аргумент №") - parsedError[i] = string.gsub(parsedError[i], "stack traceback", "Отслеживание ошибки") - parsedError[i] = string.gsub(parsedError[i], "tail calls", "Дочерние функции") - parsedError[i] = string.gsub(parsedError[i], "in function", "в функции") - parsedError[i] = string.gsub(parsedError[i], "in main chunk", "в основной программе") - parsedError[i] = string.gsub(parsedError[i], "unexpected symbol near", "неожиданный символ рядом с") - parsedError[i] = string.gsub(parsedError[i], "attempt to index", "несуществующий индекс") - parsedError[i] = string.gsub(parsedError[i], "attempt to get length of", "не удается получить длину") - parsedError[i] = string.gsub(parsedError[i], ": ", ", ") - parsedError[i] = string.gsub(parsedError[i], " module ", " модуль ") - parsedError[i] = string.gsub(parsedError[i], "not found", "не найден") - parsedError[i] = string.gsub(parsedError[i], "no field package.preload", "не найдена библиотека") - parsedError[i] = string.gsub(parsedError[i], "no file", "нет файла") - parsedError[i] = string.gsub(parsedError[i], "local", "локальной") - parsedError[i] = string.gsub(parsedError[i], "global", "глобальной") - parsedError[i] = string.gsub(parsedError[i], "no primary", "не найден компонент") - parsedError[i] = string.gsub(parsedError[i], "available", "в доступе") - parsedError[i] = string.gsub(parsedError[i], "attempt to concatenate", "не могу присоединить") - end - end - - starting, ending = nil, nil - - return parsedError -end - ---Отображение сообщения об ошибке компиляции скрипта в красивом окошке. -function ECSAPI.displayCompileMessage(y, reason, translate, withAnimation) - - local xSize, ySize = gpu.getResolution() - - --Переводим причину в массив - reason = ECSAPI.parseErrorMessage(reason, translate) - - --Получаем ширину и высоту окошка - local width = math.floor(xSize * 7 / 10) - local height = #reason + 6 - local textWidth = width - 11 - - --Просчет вот этой хуйни, аааахаахах - local difference = ySize - (height + y) - if difference < 0 then - for i = 1, (math.abs(difference) + 1) do - table.remove(reason, 1) - end - table.insert(reason, 1, "…") - height = #reason + 6 - end - - local x = math.floor(xSize / 2 - width / 2) - - --Иконочка воскл знака на красном фоне - local errorImage = { - {{0xff0000,0xffffff,"#"},{0xff0000,0xffffff,"#"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"#"},{0xff0000,0xffffff,"#"}}, - {{0xff0000,0xffffff,"#"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"!"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"#"}}, - {{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "}} - } - - --Запоминаем, че было отображено - local oldPixels = ECSAPI.rememberOldPixels(x, y, x + width + 1, y + height) - - --Типа анимация, ога - if withAnimation then - for i = 1, height, 1 do - ECSAPI.square(x, y, width, i, ECSAPI.windowColors.background) - ECSAPI.windowShadow(x, y, width, i) - os.sleep(0.01) - end - else - ECSAPI.square(x, y, width, height, ECSAPI.windowColors.background) - ECSAPI.windowShadow(x, y, width, height) - end - - --Рисуем воскл знак - ECSAPI.drawCustomImage(x + 2, y + 1, errorImage) - - --Рисуем текст - local yPos = y + 1 - local xPos = x + 9 - gpu.setBackground(ECSAPI.windowColors.background) - - ECSAPI.colorText(xPos, yPos, ECSAPI.windowColors.usualText, "Код ошибки:") - yPos = yPos + 2 - - gpu.setForeground( 0xcc0000 ) - for i = 1, #reason do - gpu.set(xPos, yPos, ECSAPI.stringLimit("end", reason[i], textWidth)) - yPos = yPos + 1 - end - - yPos = yPos + 1 - ECSAPI.colorText(xPos, yPos, ECSAPI.windowColors.usualText, ECSAPI.stringLimit("end", "Нажмите любую клавишу, чтобы продолжить", textWidth)) - - --Пикаем звуком кароч - for i = 1, 3 do - computer.beep(1000) - end - - --Ждем сам знаешь чего - ECSAPI.waitForTouchOrClick() - - --Рисуем, че было нарисовано - ECSAPI.drawOldPixels(oldPixels) -end - ---Спросить, заменять ли файл (если таковой уже имеется) -function ECSAPI.askForReplaceFile(path) - if fs.exists(path) then - local action = ECSAPI.universalWindow("auto", "auto", 46, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Файл \"".. fs.name(path) .. "\" уже имеется в этом месте."}, {"CenterText", 0x262626, "Заменить его перемещаемым объектом?"}, {"EmptyLine"}, {"Button", {0xdddddd, 0x262626, "Оставить оба"}, {0xffffff, 0x262626, "Отмена"}, {ECSAPI.colors.lightBlue, 0xffffff, "Заменить"}}) - if action[1] == "Оставить оба" then - return "keepBoth" - elseif action[2] == "Отмена" then - return "cancel" - else - return "replace" - end - end -end - ---Проверить имя файла на соответствие критериям -function ECSAPI.checkName(name, path) - --Если ввели хуйню какую-то, то - if name == "" or name == " " or name == nil then - ECSAPI.error("Неверное имя файла.") - return false - else - --Если файл с новым путем уже существует, то - if fs.exists(path .. name) then - ECSAPI.error("Файл \"".. name .. "\" уже имеется в этом месте.") - return false - --А если все заебок, то - else - return true - end - end -end - ---Переименование файлов (для операционки) -function ECSAPI.rename(mainPath) - --Задаем стартовую щнягу - local name = fs.name(mainPath) - path = fs.path(mainPath) - --Рисуем окошко ввода нового имени файла - local inputs = ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Переименовать"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, name}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK"}}) - --Переименовываем - if ECSAPI.checkName(inputs[1], path) then - fs.rename(mainPath, path .. inputs[1]) - end -end - ---Создать новую папку (для операционки) -function ECSAPI.newFolder(path) - --Рисуем окошко ввода нового имени файла - local inputs = ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Новая папка"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, ""}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK"}}) - - if ECSAPI.checkName(inputs[1], path) then - fs.makeDirectory(path .. inputs[1]) - end -end - ---Создать новый файл (для операционки) -function ECSAPI.newFile(path) - --Рисуем окошко ввода нового имени файла - local inputs = ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Новый файл"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, ""}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK"}}) - - if ECSAPI.checkName(inputs[1], path) then - ECSAPI.prepareToExit() - ECSAPI.editFile(path .. inputs[1]) - end -end - ---Создать новое приложение (для операционки) -function ECSAPI.newApplication(path, startName) - --Рисуем окошко ввода нового имени файла - local inputs - if not startName then - inputs = ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Новое приложение"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, "Введите имя"}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK"}}) - end - - if ECSAPI.checkName(inputs[1] .. ".app", path) then - local name = path .. inputs[1] .. ".app/Resources/" - fs.makeDirectory(name) - fs.copy("MineOS/System/OS/Icons/SampleIcon.pic", name .. "Icon.pic") - local file = io.open(path .. inputs[1] .. ".app/" .. inputs[1] .. ".lua", "w") - file:write("local ecs = require(\"ECSAPI\")", "\n") - file:write("ecs.universalWindow(\"auto\", \"auto\", 30, 0xeeeeee, true, {\"EmptyLine\"}, {\"CenterText\", 0x262626, \"Hello world!\"}, {\"EmptyLine\"}, {\"Button\", {0x880000, 0xffffff, \"Hello!\"}})", "\n") - file:close() - end -end - ---Создать приложение на основе существующего ЛУА-файла -function ECSAPI.newApplicationFromLuaFile(pathToLuaFile, pathWhereToCreateApplication) - local data = ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x000000, "Новое приложение"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, "Имя приложения"}, {"Input", 0x262626, 0x880000, "Путь к иконке приложения"}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK"}}) - data[1] = data[1] or "MyApplication" - data[2] = data[2] or "MineOS/System/OS/Icons/SampleIcon.pic" - if fs.exists(data[2]) then - fs.makeDirectory(pathWhereToCreateApplication .. "/" .. data[1] .. ".app/Resources") - fs.copy(pathToLuaFile, pathWhereToCreateApplication .. "/" .. data[1] .. ".app/" .. data[1] .. ".lua") - fs.copy(data[2], pathWhereToCreateApplication .. "/" .. data[1] .. ".app/Resources/Icon.pic") - - --ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x000000, "Приложение создано!"}, {"EmptyLine"}, {"Button", {ecs.colors.green, 0xffffff, "OK"}}) - else - ECSAPI.error("Указанный файл иконки не существует.") - return - end -end - ---Простое информационное окошечко. Возвращает старые пиксели - мало ли понадобится. -function ECSAPI.info(x, y, title, text) - x = x or "auto" - y = y or "auto" - title = title or " " - text = text or "Sample text" - - local width = unicode.len(text) + 4 - local height = 4 - x, y = ECSAPI.correctStartCoords(x, y, width, height) - - local oldPixels = ECSAPI.rememberOldPixels(x, y, x + width + 1, y + height) - - ECSAPI.emptyWindow(x, y, width, height, title) - ECSAPI.colorTextWithBack(x + 2, y + 2, ECSAPI.windowColors.usualText, ECSAPI.windowColors.background, text) - - return oldPixels -end - ---Вертикальный скроллбар. Маст-хев! -function ECSAPI.srollBar(x, y, width, height, countOfAllElements, currentElement, backColor, frontColor) - local sizeOfScrollBar = math.ceil(1 / countOfAllElements * height) - local displayBarFrom = math.floor(y + height * ((currentElement - 1) / countOfAllElements)) - - ECSAPI.square(x, y, width, height, backColor) - ECSAPI.square(x, displayBarFrom, width, sizeOfScrollBar, frontColor) - - sizeOfScrollBar, displayBarFrom = nil, nil -end - ---Отрисовка поля с текстом. Сюда пихать массив вида {"строка1", "строка2", "строка3", ...} -function ECSAPI.textField(x, y, width, height, lines, displayFrom, background, foreground, scrollbarBackground, scrollbarForeground) - x, y = ECSAPI.correctStartCoords(x, y, width, height) - - background = background or 0xffffff - foreground = foreground or ECSAPI.windowColors.usualText - - local sLines = #lines - local lineLimit = width - 3 - - --Парсим строки - local line = 1 - while lines[line] do - local sLine = unicode.len(lines[line]) - if sLine > lineLimit then - local part1, part2 = unicode.sub(lines[line], 1, lineLimit), unicode.sub(lines[line], lineLimit + 1, -1) - lines[line] = part1 - table.insert(lines, line + 1, part2) - part1, part2 = nil, nil - end - line = line + 1 - sLine = nil - end - line = nil - - ECSAPI.square(x, y, width - 1, height, background) - ECSAPI.srollBar(x + width - 1, y, 1, height, sLines, displayFrom, scrollbarBackground, scrollbarForeground) - - gpu.setBackground(background) - gpu.setForeground(foreground) - local yPos = y - for i = displayFrom, (displayFrom + height - 1) do - if lines[i] then - gpu.set(x + 1, yPos, lines[i]) - yPos = yPos + 1 - else - break - end - end - - return sLines -end - ---Получение верного имени языка. Просто для безопасности. (для операционки) -function ECSAPI.getCorrectLangName(pathToLangs) - local language = _G.OSSettings.language .. ".lang" - if not fs.exists(pathToLangs .. "/" .. language) then - language = "English.lang" - end - return language -end - ---Чтение языкового файла (для операционки) -function ECSAPI.readCorrectLangFile(pathToLangs) - local lang - - local language = ECSAPI.getCorrectLangName(pathToLangs) - - lang = config.readAll(pathToLangs .. "/" .. language) - - return lang -end - --------------------------ВСЕ ДЛЯ ОСКИ------------------------------------------------------------------------------- - -function ECSAPI.sortFiles(path, fileList, sortingMethod, showHiddenFiles) - local sortedFileList = {} - if sortingMethod == "type" then - local typeList = {} - for i = 1, #fileList do - local fileFormat = ECSAPI.getFileFormat(fileList[i]) or "Script" - if fs.isDirectory(path .. fileList[i]) and fileFormat ~= ".app" then fileFormat = "Folder" end - typeList[fileFormat] = typeList[fileFormat] or {} - table.insert(typeList[fileFormat], fileList[i]) - end - - if typeList["Folder"] then - for i = 1, #typeList["Folder"] do - table.insert(sortedFileList, typeList["Folder"][i]) - end - typeList["Folder"] = nil - end - - for fileFormat in pairs(typeList) do - for i = 1, #typeList[fileFormat] do - table.insert(sortedFileList, typeList[fileFormat][i]) - end - end - elseif sortingMethod == "name" then - sortedFileList = fileList - elseif sortingMethod == "date" then - for i = 1, #fileList do - fileList[i] = {fileList[i], fs.lastModified(path .. fileList[i])} - end - table.sort(fileList, function(a,b) return a[2] > b[2] end) - for i = 1, #fileList do - table.insert(sortedFileList, fileList[i][1]) - end - else - error("Unknown sorting method") - end - - local i = 1 - while i <= #sortedFileList do - if not showHiddenFiles and ECSAPI.isFileHidden(sortedFileList[i]) then - table.remove(sortedFileList, i) - else - i = i + 1 - end - end - - return sortedFileList -end - ---Сохранить файл конфигурации ОС -function ECSAPI.saveOSSettings() - local pathToOSSettings = "MineOS/System/OS/OSSettings.cfg" - if not _G.OSSettings then error("Массив настроек ОС отсутствует в памяти!") end - fs.makeDirectory(fs.path(pathToOSSettings)) - local file = io.open(pathToOSSettings, "w") - file:write(serialization.serialize(_G.OSSettings)) - file:close() -end - ---Загрузить файл конфигурации ОС, а если его не существует, то создать -function ECSAPI.loadOSSettings() - local pathToOSSettings = "MineOS/System/OS/OSSettings.cfg" - if fs.exists(pathToOSSettings) then - local file = io.open(pathToOSSettings, "r") - _G.OSSettings = serialization.unserialize(file:read("*a")) - file:close() - else - _G.OSSettings = { showHelpOnApplicationStart = true, language = "Russian" } - ECSAPI.saveOSSettings() - end -end - ---Отобразить окно с содержимым файла информации о приложении -function ECSAPI.applicationHelp(pathToApplication) - local pathToAboutFile = pathToApplication .. "/resources/About.txt" - if fs.exists(pathToAboutFile) and _G.OSSettings and _G.OSSettings.showHelpOnApplicationStart then - local applicationName = fs.name(pathToApplication) - local file = io.open(pathToAboutFile, "r") - local text = "" - for line in file:lines() do text = text .. line .. " " end - file:close() - - local data = ECSAPI.universalWindow("auto", "auto", 52, 0xeeeeee, true, {"EmptyLine"}, {"CenterText", 0x262626, "О приложении " .. applicationName}, {"EmptyLine"}, {"TextField", 14, 0xffffff, 0x262626, 0xcccccc, 0x3366CC, text}, {"EmptyLine"}, {"Switch", 0x3366CC, 0xffffff, 0x262626, "Показывать информацию о приложениях", true}, {"EmptyLine"}, {"Button", {ECSAPI.colors.green, 0xffffff, "OK"}}) - if data[1] == false then - _G.OSSettings.showHelpOnApplicationStart = false - ECSAPI.saveOSSettings() - end - end -end - ---Создать ярлык для конкретной проги (для операционки) -function ECSAPI.createShortCut(path, pathToProgram) - fs.remove(path) - fs.makeDirectory(fs.path(path)) - local file = io.open(path, "w") - file:write("return ", "\"", pathToProgram, "\"") - file:close() -end - ---Получить данные о файле из ярлыка (для операционки) -function ECSAPI.readShortcut(path) - local success, filename = pcall(loadfile(path)) - if success then - return filename - else - error("Ошибка чтения файла ярлыка. Вероятно, он создан криво, либо не существует в папке " .. path) - end -end - ---Редактирование файла (для операционки) -function ECSAPI.editFile(path) - ECSAPI.prepareToExit() - shell.execute("edit "..path) -end - --- Копирование папки через рекурсию, т.к. fs.copy() не поддерживает папки --- Ну долбоеб автор мода - хули я тут сделаю? Придется так вот --- Хотя можно юзать обычный bin/cp, как это сделано в дисковом дубляже. Надо перекодить, короч -function ECSAPI.copyFolder(path, toPath) - local function doCopy(path) - local fileList = ECSAPI.getFileList(path) - for i = 1, #fileList do - if fs.isDirectory(path..fileList[i]) then - doCopy(path..fileList[i]) - else - fs.makeDirectory(toPath..path) - fs.copy(path..fileList[i], toPath ..path.. fileList[i]) - end - end - end - - toPath = fs.path(toPath) - doCopy(path.."/") -end - ---Копирование файлов для операционки -function ECSAPI.copy(from, to) - local name = fs.name(from) - local toName = to .. "/" .. name - local action = ECSAPI.askForReplaceFile(toName) - if action == nil or action == "replace" then - fs.remove(toName) - if fs.isDirectory(from) then - ECSAPI.copyFolder(from, toName) - else - fs.copy(from, toName) - end - elseif action == "keepBoth" then - if fs.isDirectory(from) then - ECSAPI.copyFolder(from, to .. "/(copy)" .. name) - else - fs.copy(from, to .. "/(copy)" .. name) - end - end -end - -ECSAPI.OSIconsWidth = 12 -ECSAPI.OSIconsHeight = 6 - ---Вся необходимая информация для иконок -local function OSIconsInit() - if not _G.image then _G.image = require("image") end - if not _G.buffer then _G.buffer = require("doubleBuffering") end - if not ECSAPI.OSIcons then - --Константы для иконок - ECSAPI.OSIcons = {} - ECSAPI.pathToIcons = "MineOS/System/OS/Icons/" - - --Иконки - ECSAPI.OSIcons.folder = image.load(ECSAPI.pathToIcons .. "Folder.pic") - ECSAPI.OSIcons.script = image.load(ECSAPI.pathToIcons .. "Script.pic") - ECSAPI.OSIcons.text = image.load(ECSAPI.pathToIcons .. "Text.pic") - ECSAPI.OSIcons.config = image.load(ECSAPI.pathToIcons .. "Config.pic") - ECSAPI.OSIcons.lua = image.load(ECSAPI.pathToIcons .. "Lua.pic") - ECSAPI.OSIcons.image = image.load(ECSAPI.pathToIcons .. "Image.pic") - ECSAPI.OSIcons.imageJPG = image.load(ECSAPI.pathToIcons .. "RawImage.pic") - ECSAPI.OSIcons.pastebin = image.load(ECSAPI.pathToIcons .. "Pastebin.pic") - ECSAPI.OSIcons.fileNotExists = image.load(ECSAPI.pathToIcons .. "FileNotExists.pic") - ECSAPI.OSIcons.archive = image.load(ECSAPI.pathToIcons .. "Archive.pic") - end -end - ---Отрисовка одной иконки -function ECSAPI.drawOSIcon(x, y, path, showFileFormat, nameColor) - --Инициализируем переменные иконок. Чисто для уменьшения расхода оперативки. - OSIconsInit() - --Получаем формат файла - local fileFormat = ECSAPI.getFileFormat(path) - --Создаем пустую переменную для конкретной иконки, для ее типа - local icon - --Если данный файл является папкой, то - if fs.isDirectory(path) then - if fileFormat == ".app" then - icon = path .. "/Resources/Icon.pic" - --Если данной иконки еще нет в оперативке, то загрузить ее - if not ECSAPI.OSIcons[icon] then - ECSAPI.OSIcons[icon] = image.load(icon) - end - else - icon = "folder" - end - else - if fileFormat == ".lnk" then - local shortcutLink = ECSAPI.readShortcut(path) - ECSAPI.drawOSIcon(x, y, shortcutLink, showFileFormat, nameColor) - --Стрелочка - buffer.set(x + ECSAPI.OSIconsWidth - 3, y + ECSAPI.OSIconsHeight - 3, 0xFFFFFF, 0x000000, "<") - return 0 - elseif fileFormat == ".cfg" or fileFormat == ".config" then - icon = "config" - elseif fileFormat == ".txt" or fileFormat == ".rtf" then - icon = "text" - elseif fileFormat == ".lua" then - icon = "lua" - elseif fileFormat == ".pic" or fileFormat == ".png" then - icon = "image" - elseif fileFormat == ".rawpic" then - icon = "imageJPG" - elseif fileFormat == ".paste" then - icon = "pastebin" - elseif fileFormat == ".pkg" then - icon = "archive" - elseif not fs.exists(path) then - icon = "fileNotExists" - else - icon = "script" - end - end - - --Рисуем иконку - buffer.image(x + 2, y, ECSAPI.OSIcons[icon]) - - --Делаем текст для иконки - local text = fs.name(path) - if not showFileFormat and fileFormat then - text = unicode.sub(text, 1, -(unicode.len(fileFormat) + 1)) - end - text = ECSAPI.stringLimit("end", text, ECSAPI.OSIconsWidth) - --Рассчитываем позицию текста - local textPos = x + math.floor(ECSAPI.OSIconsWidth / 2 - unicode.len(text) / 2) - --Рисуем текст под иконкой - buffer.text(textPos, y + ECSAPI.OSIconsHeight - 1, nameColor or 0xffffff, text) - -end - ---ЗАПУСТИТЬ ПРОГУ -function ECSAPI.launchIcon(path, arguments) - --Запоминаем, какое разрешение было - local oldWidth, oldHeight = gpu.getResolution() - --Создаем нормальные аргументы для Шелла - if arguments then arguments = " " .. arguments else arguments = "" end - --Получаем файл формат заранее - local fileFormat = ECSAPI.getFileFormat(path) - local isDirectory = fs.isDirectory(path) - --Если это приложение - if fileFormat == ".app" then - ECSAPI.applicationHelp(path) - local cyka = path .. "/" .. ECSAPI.hideFileFormat(fs.name(path)) .. ".lua" - local success, reason = shell.execute(cyka) - if not success then ECSAPI.displayCompileMessage(1, reason, true) end - --Если это папка - elseif (fileFormat == "" or fileFormat == nil) and isDirectory then - shell.execute("MineOS/Applications/Finder.app/Finder.lua " .. path) - --Если это обычный луа файл - т.е. скрипт - elseif fileFormat == ".lua" or fileFormat == nil then - ECSAPI.prepareToExit() - local success, reason = shell.execute(path .. arguments) - if success then - print(" ") - print("Program sucessfully executed. Press any key to continue.") - print(" ") - else - ECSAPI.displayCompileMessage(1, reason, true) - end - --Если это фоточка - elseif fileFormat == ".pic" then - shell.execute("MineOS/Applications/Photoshop.app/Photoshop.lua open " .. path) - --Если это фоточка - elseif fileFormat == ".raw" then - shell.execute("MineOS/Applications/Photoshop.app/Photoshop.lua open " .. path) - --Если это текст или конфиг или языковой - elseif fileFormat == ".txt" or fileFormat == ".cfg" or fileFormat == ".lang" then - ECSAPI.prepareToExit() - shell.execute("edit "..path) - --Если это ярлык - elseif fileFormat == ".lnk" then - local shortcutLink = ECSAPI.readShortcut(path) - if fs.exists(shortcutLink) then - ECSAPI.launchIcon(shortcutLink) - else - ECSAPI.error("File from shortcut link doesn't exists.") - end - --Если это ссылка на пастебин - elseif fileFormat == ".paste" then - local shortcutLink = ECSAPI.readShortcut(path) - ECSAPI.prepareToExit() - local success, reason = shell.execute("pastebin run " .. shortcutLink) - if success then - print(" ") - print("Program sucessfully executed. Press any key to continue.") - ECSAPI.waitForTouchOrClick() - else - ECSAPI.displayCompileMessage(1, reason, false) - end - --Если это архив - elseif fileFormat == ".zip" then - zip.unarchive(path, (fs.path(path) or "")) - end - --Ставим старое разрешение - gpu.setResolution(oldWidth, oldHeight) -end - - - - ----------------------------------------------ОКОШЕЧКИ------------------------------------------------------------ - - ---Описание ниже, ебана. Ниже - это значит в самой жопе кода! -function ECSAPI.universalWindow(x, y, width, background, closeWindowAfter, ...) - local objects = {...} - local countOfObjects = #objects - - local pressedButton - local pressedMultiButton - - --Задаем высотные константы для объектов - local objectsHeights = { - ["button"] = 3, - ["centertext"] = 1, - ["emptyline"] = 1, - ["input"] = 3, - ["slider"] = 3, - ["select"] = 3, - ["selector"] = 3, - ["separator"] = 1, - ["switch"] = 1, - ["color"] = 3, - } - - --Скорректировать ширину, если нужно - local function correctWidth(newWidthForAnalyse) - width = math.max(width, newWidthForAnalyse) - end - - --Корректируем ширину - for i = 1, countOfObjects do - local objectType = string.lower(objects[i][1]) - - if objectType == "centertext" then - correctWidth(unicode.len(objects[i][3]) + 2) - elseif objectType == "slider" then --!!!!!!!!!!!!!!!!!! ВОТ ТУТ НЕ ЗАБУДЬ ФИКСАНУТЬ - correctWidth(unicode.len(objects[i][7]..tostring(objects[i][5].." ")) + 2) - elseif objectType == "select" then - for j = 4, #objects[i] do - correctWidth(unicode.len(objects[i][j]) + 2) - end - --elseif objectType == "selector" then - - --elseif objectType == "separator" then - - elseif objectType == "textfield" then - correctWidth(7) - elseif objectType == "wrappedtext" then - correctWidth(6) - elseif objectType == "button" then - --Корректируем ширину - local widthOfButtons = 0 - local maxButton = 0 - for j = 2, #objects[i] do - maxButton = math.max(maxButton, unicode.len(objects[i][j][3]) + 2) - end - widthOfButtons = maxButton * #objects[i] - correctWidth(widthOfButtons) - elseif objectType == "switch" then - local dlina = unicode.len(objects[i][5]) + 2 + 10 + 4 - correctWidth(dlina) - elseif objectType == "color" then - correctWidth(unicode.len(objects[i][2]) + 6) - end - end - - --Считаем высоту этой хуйни - local height = 0 - for i = 1, countOfObjects do - local objectType = string.lower(objects[i][1]) - if objectType == "select" then - height = height + (objectsHeights[objectType] * (#objects[i] - 3)) - elseif objectType == "textfield" then - height = height + objects[i][2] - elseif objectType == "wrappedtext" then - --Заранее парсим текст перенесенный - objects[i].wrapped = ECSAPI.stringWrap({objects[i][3]}, width - 4) - objects[i].height = #objects[i].wrapped - height = height + objects[i].height - else - height = height + objectsHeights[objectType] - end - end - - --Коорректируем стартовые координаты - x, y = ECSAPI.correctStartCoords(x, y, width, height) - --Запоминаем инфу о том, что было нарисовано, если это необходимо - local oldPixels, oldBackground, oldForeground - if closeWindowAfter then - oldBackground = gpu.getBackground() - oldForeground = gpu.getForeground() - oldPixels = ECSAPI.rememberOldPixels(x, y, x + width - 1, y + height - 1) - end - --Считаем все координаты объектов - objects[1].y = y - if countOfObjects > 1 then - for i = 2, countOfObjects do - local objectType = string.lower(objects[i - 1][1]) - if objectType == "select" then - objects[i].y = objects[i - 1].y + (objectsHeights[objectType] * (#objects[i - 1] - 3)) - elseif objectType == "textfield" then - objects[i].y = objects[i - 1].y + objects[i - 1][2] - elseif objectType == "wrappedtext" then - objects[i].y = objects[i - 1].y + objects[i - 1].height - else - objects[i].y = objects[i - 1].y + objectsHeights[objectType] - end - end - end - - --Объекты для тача - local obj = {} - local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} - end - - --Отображение объекта по номеру - local function displayObject(number, active) - local objectType = string.lower(objects[number][1]) - - if objectType == "centertext" then - local xPos = x + math.floor(width / 2 - unicode.len(objects[number][3]) / 2) - gpu.setForeground(objects[number][2]) - gpu.setBackground(background) - gpu.set(xPos, objects[number].y, objects[number][3]) - - elseif objectType == "input" then - - if active then - --Рамочка - ECSAPI.border(x + 1, objects[number].y, width - 2, objectsHeights.input, background, objects[number][3]) - --Тестик - objects[number][4] = ECSAPI.inputText(x + 3, objects[number].y + 1, width - 6, "", background, objects[number][3], false, objects[number][5]) - else - --Рамочка - ECSAPI.border(x + 1, objects[number].y, width - 2, objectsHeights.input, background, objects[number][2]) - --Текстик - gpu.set(x + 3, objects[number].y + 1, ECSAPI.stringLimit("start", objects[number][4], width - 6)) - ECSAPI.inputText(x + 3, objects[number].y + 1, width - 6, objects[number][4], background, objects[number][2], true, objects[number][5]) - end - - newObj("Inputs", number, x + 1, objects[number].y, x + width - 2, objects[number].y + 2) - - elseif objectType == "slider" then - local widthOfSlider = width - 2 - local xOfSlider = x + 1 - local yOfSlider = objects[number].y + 1 - local countOfSliderThings = objects[number][5] - objects[number][4] - local showSliderValue= objects[number][7] - - local dolya = widthOfSlider / countOfSliderThings - local position = math.floor(dolya * objects[number][6]) - --Костыль - if (xOfSlider + position) > (xOfSlider + widthOfSlider - 1) then position = widthOfSlider - 2 end - - --Две линии - ECSAPI.separator(xOfSlider, yOfSlider, position, background, objects[number][3]) - ECSAPI.separator(xOfSlider + position, yOfSlider, widthOfSlider - position, background, objects[number][2]) - --Слудир - ECSAPI.square(xOfSlider + position, yOfSlider, 2, 1, objects[number][3]) - - --Текстик под слудиром - if showSliderValue then - local text = showSliderValue .. tostring(objects[number][6]) .. (objects[number][8] or "") - local textPos = (xOfSlider + widthOfSlider / 2 - unicode.len(text) / 2) - ECSAPI.square(x, yOfSlider + 1, width, 1, background) - ECSAPI.colorText(textPos, yOfSlider + 1, objects[number][2], text) - end - - newObj("Sliders", number, xOfSlider, yOfSlider, x + widthOfSlider, yOfSlider, dolya) - - elseif objectType == "select" then - local usualColor = objects[number][2] - local selectionColor = objects[number][3] - - objects[number].selectedData = objects[number].selectedData or 1 - - local symbol = "✔" - local yPos = objects[number].y - for i = 4, #objects[number] do - --Коробка для галочки - ECSAPI.border(x + 1, yPos, 5, 3, background, usualColor) - --Текст - gpu.set(x + 7, yPos + 1, objects[number][i]) - --Галочка - if objects[number].selectedData == (i - 3) then - ECSAPI.colorText(x + 3, yPos + 1, selectionColor, symbol) - else - gpu.set(x + 3, yPos + 1, " ") - end - - obj["Selects"] = obj["Selects"] or {} - obj["Selects"][number] = obj["Selects"][number] or {} - obj["Selects"][number][i - 3] = { x + 1, yPos, x + width - 2, yPos + 2 } - - yPos = yPos + objectsHeights.select - end - - elseif objectType == "selector" then - local borderColor = objects[number][2] - local arrowColor = objects[number][3] - local selectorWidth = width - 2 - objects[number].selectedElement = objects[number].selectedElement or objects[number][4] - - local topLine = "┌" .. string.rep("─", selectorWidth - 6) .. "┬───┐" - local midLine = "│" .. string.rep(" ", selectorWidth - 6) .. "│ │" - local botLine = "└" .. string.rep("─", selectorWidth - 6) .. "┴───┘" - - local yPos = objects[number].y - - local function bordak(borderColor) - gpu.setBackground(background) - gpu.setForeground(borderColor) - gpu.set(x + 1, objects[number].y, topLine) - gpu.set(x + 1, objects[number].y + 1, midLine) - gpu.set(x + 1, objects[number].y + 2, botLine) - gpu.set(x + 3, objects[number].y + 1, ECSAPI.stringLimit("start", objects[number].selectedElement, width - 6)) - ECSAPI.colorText(x + width - 4, objects[number].y + 1, arrowColor, "▼") - end - - bordak(borderColor) - - --Выпадающий список, самый гемор, блядь - if active then - local xPos, yPos = x + 1, objects[number].y + 3 - local spisokWidth = width - 2 - local countOfElements = #objects[number] - 3 - local spisokHeight = countOfElements + 1 - local oldPixels = ECSAPI.rememberOldPixels( xPos, yPos, xPos + spisokWidth - 1, yPos + spisokHeight - 1) - - local coords = {} - - bordak(arrowColor) - - --Рамку рисуем поверх фоника - local topLine = "├"..string.rep("─", spisokWidth - 6).."┴───┤" - local midLine = "│"..string.rep(" ", spisokWidth - 2).."│" - local botLine = "└"..string.rep("─", selectorWidth - 2) .. "┘" - ECSAPI.colorTextWithBack(xPos, yPos - 1, arrowColor, background, topLine) - for i = 1, spisokHeight - 1 do - gpu.set(xPos, yPos + i - 1, midLine) - end - gpu.set(xPos, yPos + spisokHeight - 1, botLine) - - --Элементы рисуем - xPos = xPos + 2 - for i = 1, countOfElements do - ECSAPI.colorText(xPos, yPos, borderColor, ECSAPI.stringLimit("start", objects[number][i + 3], spisokWidth - 4)) - coords[i] = {xPos - 1, yPos, xPos + spisokWidth - 4, yPos} - yPos = yPos + 1 - end - - --Обработка - local exit - while true do - if exit then break end - local e = {event.pull()} - if e[1] == "touch" then - for i = 1, #coords do - if ECSAPI.clickedAtArea(e[3], e[4], coords[i][1], coords[i][2], coords[i][3], coords[i][4]) then - ECSAPI.square(coords[i][1], coords[i][2], spisokWidth - 2, 1, ECSAPI.colors.blue) - ECSAPI.colorText(coords[i][1] + 1, coords[i][2], 0xffffff, objects[number][i + 3]) - os.sleep(0.3) - objects[number].selectedElement = objects[number][i + 3] - exit = true - break - end - end - end - end - - ECSAPI.drawOldPixels(oldPixels) - end - - newObj("Selectors", number, x + 1, objects[number].y, x + width - 2, objects[number].y + 2) - - elseif objectType == "separator" then - ECSAPI.separator(x, objects[number].y, width, background, objects[number][2]) - - elseif objectType == "textfield" then - newObj("TextFields", number, x + 1, objects[number].y, x + width - 2, objects[number].y + objects[number][2] - 1) - if not objects[number].strings then objects[number].strings = ECSAPI.stringWrap({objects[number][7]}, width - 7) end - objects[number].displayFrom = objects[number].displayFrom or 1 - ECSAPI.textField(x + 1, objects[number].y, width - 2, objects[number][2], objects[number].strings, objects[number].displayFrom, objects[number][3], objects[number][4], objects[number][5], objects[number][6]) - - elseif objectType == "wrappedtext" then - gpu.setBackground(background) - gpu.setForeground(objects[number][2]) - for i = 1, #objects[number].wrapped do - gpu.set(x + 2, objects[number].y + i - 1, objects[number].wrapped[i]) - end - - elseif objectType == "button" then - - obj["MultiButtons"] = obj["MultiButtons"] or {} - obj["MultiButtons"][number] = {} - - local widthOfButton = math.floor(width / (#objects[number] - 1)) - - local xPos, yPos = x, objects[number].y - for i = 1, #objects[number] do - if type(objects[number][i]) == "table" then - local x1, y1, x2, y2 = ECSAPI.drawButton(xPos, yPos, widthOfButton, 3, objects[number][i][3], objects[number][i][1], objects[number][i][2]) - table.insert(obj["MultiButtons"][number], {x1, y1, x2, y2, widthOfButton}) - xPos = x2 + 1 - - if i == #objects[number] then - ECSAPI.square(xPos, yPos, x + width - xPos, 3, objects[number][i][1]) - obj["MultiButtons"][number][i - 1][5] = obj["MultiButtons"][number][i - 1][5] + x + width - xPos - end - - x1, y1, x2, y2 = nil, nil, nil, nil - end - end - - elseif objectType == "switch" then - - local xPos, yPos = x + 2, objects[number].y - local activeColor, passiveColor, textColor, text, state = objects[number][2], objects[number][3], objects[number][4], objects[number][5], objects[number][6] - local switchWidth = 8 - ECSAPI.colorTextWithBack(xPos, yPos, textColor, background, text) - - xPos = x + width - switchWidth - 2 - if state then - ECSAPI.square(xPos, yPos, switchWidth, 1, activeColor) - ECSAPI.square(xPos + switchWidth - 2, yPos, 2, 1, passiveColor) - --ECSAPI.colorTextWithBack(xPos + 4, yPos, passiveColor, activeColor, "ON") - else - ECSAPI.square(xPos, yPos, switchWidth, 1, passiveColor - 0x444444) - ECSAPI.square(xPos, yPos, 2, 1, passiveColor) - --ECSAPI.colorTextWithBack(xPos + 4, yPos, passiveColor, passiveColor - 0x444444, "OFF") - end - newObj("Switches", number, xPos, yPos, xPos + switchWidth - 1, yPos) - - elseif objectType == "color" then - local xPos, yPos = x + 1, objects[number].y - local blendedColor = colorlib.alphaBlend(objects[number][3], 0xFFFFFF, 180) - local w = width - 2 - - ECSAPI.colorTextWithBack(xPos, yPos + 2, blendedColor, background, string.rep("▀", w)) - ECSAPI.colorText(xPos, yPos, objects[number][3], string.rep("▄", w)) - ECSAPI.square(xPos, yPos + 1, w, 1, objects[number][3]) - - ECSAPI.colorText(xPos + 1, yPos + 1, 0xffffff - objects[number][3], objects[number][2]) - newObj("Colors", number, xPos, yPos, x + width - 2, yPos + 2) - end - end - - --Отображение всех объектов - local function displayAllObjects() - for i = 1, countOfObjects do - displayObject(i) - end - end - - --Подготовить массив возвращаемый - local function getReturn() - local massiv = {} - - for i = 1, countOfObjects do - local type = string.lower(objects[i][1]) - - if type == "button" then - table.insert(massiv, pressedButton) - elseif type == "input" then - table.insert(massiv, objects[i][4]) - elseif type == "select" then - table.insert(massiv, objects[i][objects[i].selectedData + 3]) - elseif type == "selector" then - table.insert(massiv, objects[i].selectedElement) - elseif type == "slider" then - table.insert(massiv, objects[i][6]) - elseif type == "switch" then - table.insert(massiv, objects[i][6]) - elseif type == "color" then - table.insert(massiv, objects[i][3]) - else - table.insert(massiv, nil) - end - end - - return massiv - end - - local function redrawBeforeClose() - if closeWindowAfter then - ECSAPI.drawOldPixels(oldPixels) - gpu.setBackground(oldBackground) - gpu.setForeground(oldForeground) - end - end - - --Рисуем окно - ECSAPI.square(x, y, width, height, background) - displayAllObjects() - - while true do - local e = {event.pull()} - if e[1] == "touch" or e[1] == "drag" then - - --Анализируем клик на кнопки - if obj["MultiButtons"] then - for key in pairs(obj["MultiButtons"]) do - for i = 1, #obj["MultiButtons"][key] do - if ECSAPI.clickedAtArea(e[3], e[4], obj["MultiButtons"][key][i][1], obj["MultiButtons"][key][i][2], obj["MultiButtons"][key][i][3], obj["MultiButtons"][key][i][4]) then - ECSAPI.drawButton(obj["MultiButtons"][key][i][1], obj["MultiButtons"][key][i][2], obj["MultiButtons"][key][i][5], 3, objects[key][i + 1][3], objects[key][i + 1][2], objects[key][i + 1][1]) - os.sleep(0.3) - pressedButton = objects[key][i + 1][3] - redrawBeforeClose() - return getReturn() - end - end - end - end - - --А теперь клик на инпуты! - if obj["Inputs"] then - for key in pairs(obj["Inputs"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Inputs"][key][1], obj["Inputs"][key][2], obj["Inputs"][key][3], obj["Inputs"][key][4]) then - displayObject(key, true) - displayObject(key) - break - end - end - end - - --А теперь галочковыбор! - if obj["Selects"] then - for key in pairs(obj["Selects"]) do - for i in pairs(obj["Selects"][key]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Selects"][key][i][1], obj["Selects"][key][i][2], obj["Selects"][key][i][3], obj["Selects"][key][i][4]) then - objects[key].selectedData = i - displayObject(key) - break - end - end - end - end - - --Хм, а вот и селектор подъехал! - if obj["Selectors"] then - for key in pairs(obj["Selectors"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Selectors"][key][1], obj["Selectors"][key][2], obj["Selectors"][key][3], obj["Selectors"][key][4]) then - displayObject(key, true) - displayObject(key) - break - end - end - end - - --Слайдеры, епта! "Потный матан", все делы - if obj["Sliders"] then - for key in pairs(obj["Sliders"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Sliders"][key][1], obj["Sliders"][key][2], obj["Sliders"][key][3], obj["Sliders"][key][4]) then - local xOfSlider, dolya = obj["Sliders"][key][1], obj["Sliders"][key][5] - local currentPixels = e[3] - xOfSlider - local currentValue = math.floor(currentPixels / dolya) - --Костыль - if e[3] == obj["Sliders"][key][3] then currentValue = objects[key][5] end - objects[key][6] = currentValue or objects[key][6] - displayObject(key) - break - end - end - end - - if obj["Switches"] then - for key in pairs(obj["Switches"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Switches"][key][1], obj["Switches"][key][2], obj["Switches"][key][3], obj["Switches"][key][4]) then - objects[key][6] = not objects[key][6] - displayObject(key) - break - end - end - end - - if obj["Colors"] then - for key in pairs(obj["Colors"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Colors"][key][1], obj["Colors"][key][2], obj["Colors"][key][3], obj["Colors"][key][4]) then - local oldColor = objects[key][3] - objects[key][3] = 0xffffff - objects[key][3] - displayObject(key) - os.sleep(0.3) - objects[key][3] = oldColor - displayObject(key) - local color = loadfile("lib/palette.lua")().draw("auto", "auto", objects[key][3]) - objects[key][3] = color or oldColor - displayObject(key) - break - end - end - end - - elseif e[1] == "scroll" then - if obj["TextFields"] then - for key in pairs(obj["TextFields"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["TextFields"][key][1], obj["TextFields"][key][2], obj["TextFields"][key][3], obj["TextFields"][key][4]) then - if e[5] == 1 then - if objects[key].displayFrom > 1 then objects[key].displayFrom = objects[key].displayFrom - 1; displayObject(key) end - else - if objects[key].displayFrom < #objects[key].strings then objects[key].displayFrom = objects[key].displayFrom + 1; displayObject(key) end - end - end - end - end - elseif e[1] == "key_down" then - if e[4] == 28 then - redrawBeforeClose() - return getReturn() - end - end - end -end - ---Демонстрационное окно, показывающее всю мощь universalWindow -function ECSAPI.demoWindow() - --Очищаем экран перед юзанием окна и ставим курсор на 1, 1 - ECSAPI.prepareToExit() - --Рисуем окно и получаем данные после взаимодействия с ним - local data = ECSAPI.universalWindow("auto", "auto", 36, 0xeeeeee, true, - {"EmptyLine"}, - {"CenterText", 0x880000, "Здорово, ебана!"}, - {"EmptyLine"}, - {"Input", 0x262626, 0x880000, "Сюда вводить можно"}, - {"Selector", 0x262626, 0x880000, "Выбор формата", "PNG", "JPG", "GIF", "PSD"}, - {"EmptyLine"}, - {"WrappedText", 0x262626, "Тест автоматического переноса букв в зависимости от ширины данного окна. Пока что тупо режет на куски, не особо красиво."}, - {"EmptyLine"}, - {"Select", 0x262626, 0x880000, "Я пидор", "Я не пидор"}, - {"Slider", 0x262626, 0x880000, 1, 100, 50, "Убито ", " младенцев"}, - {"EmptyLine"}, - {"Separator", 0xaaaaaa}, - {"Switch", 0xF2B233, 0xffffff, 0x262626, "✈ Авиарежим", false}, - {"EmptyLine"}, - {"Switch", 0x3366CC, 0xffffff, 0x262626, "☾ Не беспокоить", true}, - {"Separator", 0xaaaaaa}, - {"EmptyLine"}, - {"TextField", 5, 0xffffff, 0x262626, 0xcccccc, 0x3366CC, "Тест текстового информационного поля. По сути это тот же самый WrappedText, разве что эта хрень ограничена по высоте, и ее можно скроллить. Ну же, поскролль меня! Скролль меня полностью! Моя жадная пизда жаждет твой хуй!"}, - {"Color", "Цвет фона", 0xFF0000}, - {"EmptyLine"}, - {"Button", {0x57A64E, 0xffffff, "Да"}, {0xF2B233, 0xffffff, "Нет"}, {0xCC4C4C, 0xffffff, "Отмена"}} - ) - --Еще разок - ECSAPI.prepareToExit() - --Выводим данные - print(" ") - print("Вывод данных из окна:") - for i = 1, #data do print("["..i.."] = "..tostring(data[i])) end - print(" ") -end - --- ECSAPI.demoWindow() - ---[[ -Функция universalWindow(x, y, width, background, closeWindowAfter, ...) - - Это универсальная модульная функция для максимально удобного и быстрого отображения - необходимой вам информации. С ее помощью вводить данные с клавиатуры, осуществлять выбор - из предложенных вариантов, рисовать красивые кнопки, отрисовывать обычный текст, - отрисовывать текстовые поля с возможностью прокрутки, рисовать разделители и прочее. - Любой объект выделяется с помощью клика мыши, после чего функция приступает к работе - с этим объектом. - -Аргументы функции: - - x и y: это числа, обозначающие стартовые координаты левого верхнего угла данного окна. - Вместо цифр вы также можете написать "auto" - и программа автоматически разместит окно - по центру экрана по выбранной координате. Или по обеим координатам, если вам угодно. - - width: это ширина окна, которую вы можете задать по собственному желанию. Если некторые - объекты требуют расширения окна, то окно будет автоматически расширено до нужной ширины. - Да, вот такая вот тавтология ;) - - background: базовый цвет окна (цвет фона, кому как понятнее). - - closeWindowAfter: eсли true, то окно по завершению функции будет выгружено, а на его месте - отрисуются пиксели, которые имелись на экране до выполнения функции. Удобно, если не хочешь - париться с перерисовкой интерфейса. - - ... : многоточием тут является перечень объектов, указанных через запятую. Каждый объект - является массивом и имеет собственный формат. Ниже перечислены все возможные типы объектов. - - {"Button", {Цвет кнопки1, Цвет текста на кнопке1, Сам текст1}, {Цвет кнопки2, Цвет текста на кнопке2, Сам текст2}, ...} - - Это объект для рисования кнопок. Каждая кнопка - это массив, состоящий из трех элементов: - цвета кнопки, цвета текста на кнопке и самого текста. Кнопок может быть неограниченное количество, - однако чем их больше, тем большее требуется разрешение экрана по ширине. - - Интерактивный объект. - - {"Input", Цвет рамки и текста, Цвет при выделении, Стартовый текст [, Маскировать символом]} - - Объект для рисования полей ввода текстовой информации. Удобно для открытия или сохранения файлов, - Опциональный аргумент "Маскировать символом" полезен, если вы делаете поле для ввода пароля. - Никто не увидит ваш текст. В качестве данного аргумента передается символ, например "*". - - Интерактивный объект. - - {"Selector", Цвет рамки, Цвет при выделении, Выбор 1, Выбор 2, Выбор 3 ...} - - Внешне схож с объектом "Input", однако в этом случае вы будете выбирать один из предложенных - вариантов из выпадающего списка. По умолчанию выбран первый вариант. - - Интерактивный объект. - - {"Select", Цвет рамки, Цвет галочки, Выбор 1, Выбор 2, Выбор 3 ...} - - Объект выбора. Отличается от "Selector" тем, что здесь вы выбираете один из вариантов, отмечая - его галочкой. По умолчанию выбран первый вариант. - - Интерактивный объект. - - {"Slider", Цвет линии слайдера, Цвет пимпочки слайдера, Значения слайдера ОТ, Значения слайдера ДО, Текущее значение [, Текст-подсказка ДО] [, Текст-подсказка ПОСЛЕ]} - - Ползунок, позволяющий задавать определенное количество чего-либо в указанном интервале. Имеются два - опциональных аргумента, позволяющих четко понимать, с чем именно мы имеем дело. - - К примеру, если аргумент "Текст-подсказка ДО" будет равен "Съедено ", а аргумент "Текст-подсказка ПОСЛЕ" - будет равен " яблок", а значение слайдера будет равно 50, то на экране будет написано "Съедено 50 яблок". - - Интерактивный объект. - - {"Switch", Активный цвет, Пассивный цвет, Цвет текста, Текст, Состояние} - - Переключатель, принимающий два состояния: true или false. Текст - это всего лишь информация, некое - название данного переключателя. - - Интерактивный объект. - - {"CenterText", Цвет текста, Сам текст} - - Отображение текста указанного цвета по центру окна. Чисто для информативных целей. - - {"WrappedText", Цвет текста, Текст} - - Отображение большого количества текста с автоматическим переносом. Прото режет слова на кусочки, - перенос символический. Чисто для информативных целей. - - {"TextField", Высота, Цвет фона, Цвет текста, Цвет скроллбара, Цвет пимпочки скроллбара, Сам текст} - - Текстовое поле с возможностью прокрутки. Отличается от "WrappedText" - фиксированной высотой. Чисто для информативных целей. - - {"Separator", Цвет разделителя} - - Линия-разделитель, помогающая лучше отделять объекты друг от друга. Декоративный объект. - - {"EmptyLine"} - - Пустое пространство, помогающая лучше отделять объекты друг от друга. Декоративный объект. - - Каждый из объектов рисуется по порядку сверху вниз. Каждый объект автоматически - увеличивает высоту окна до необходимого значения. Если объектов будет указано слишком много - - т.е. если окно вылезет за пределы экрана, то программа завершится с ошибкой. - - Что возвращает функция: - - Возвратом является массив, пронумерованный от 1 до <количества объектов>. - К примеру, 1 индекс данного массива соответствует 1 указанному объекту. - Каждый индекс данного массива несет в себе какие-то данные, которые вы - внесли в объект во время работы функции. - Например, если в 1-ый объект типа "Input" вы ввели фразу "Hello world", - то первый индекс в возвращенном массиве будет равен "Hello world". - Конкретнее это будет вот так: massiv[1] = "Hello world". - - Если взаимодействие с объектом невозможно - например, как в случае - с EmptyLine, CenterText, TextField или Separator, то в возвращенном - массиве этот объект указываться не будет. - - Готовые примеры использования функции указаны ниже и закомментированы. - Выбирайте нужный и раскомментируйте. -]] - ---Функция-демонстратор, показывающая все возможные объекты в одном окне. Код окна находится выше. ---ECSAPI.demoWindow() - ---Функция-отладчик, выдающая окно с указанным сообщением об ошибке. Полезна при дебаге. ---ECSAPI.error("Это сообщение об ошибке! Hello world!") - ---Функция, спрашивающая, стоит ли заменять указанный файл, если он уже имеется ---ECSAPI.askForReplaceFile("OS.lua") - ---Функция, предлагающая сохранить файл в нужном месте в нужном формате. ---ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Сохранить как"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, "Путь"}, {"Selector", 0x262626, 0x880000, "PNG", "JPG", "PSD"}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK!"}}) - - ----------------------------------------------------------------------------------------------------- - -ECSAPI.applicationHelp("MineOS/Applications/InfoPanel.app") - -return ECSAPI - - diff --git a/Beta/MineCode2/colorlib.lua b/Beta/MineCode2/colorlib.lua deleted file mode 100644 index 28d3f4d2..00000000 --- a/Beta/MineCode2/colorlib.lua +++ /dev/null @@ -1,151 +0,0 @@ -local colorlib = {} - ---utils -local function check(tVal, tMaxVal, tMinVal, tType) - -end - -local function isNan(x) - return x~=x -end - ---RGB model -function colorlib.HEXtoRGB(color) - color = math.ceil(color) - - local rr = bit32.rshift( color, 16 ) - local gg = bit32.rshift( bit32.band(color, 0x00ff00), 8 ) - local bb = bit32.band(color, 0x0000ff) - - return rr, gg, bb -end - -function colorlib.RGBtoHEX(rr, gg, bb) - return bit32.lshift(rr, 16) + bit32.lshift(gg, 8) + bb -end - ---HSB model -function colorlib.RGBtoHSB(rr, gg, bb) - local max = math.max(rr, math.max(gg, bb)) - local min = math.min(rr, math.min(gg, bb)) - local delta = max - min - - local h = 0 - if ( max == rr and gg >= bb) then h = 60*(gg-bb)/delta end - if ( max == rr and gg <= bb ) then h = 60*(gg-bb)/delta + 360 end - if ( max == gg ) then h = 60*(bb-rr)/delta + 120 end - if ( max == bb ) then h = 60*(rr-gg)/delta + 240 end - - local s = 0 - if ( max ~= 0 ) then s = 1-(min/max) end - - local b = max*100/255 - - if isNan(h) then h = 0 end - - return h, s*100, b -end - -function colorlib.HSBtoRGB(h, s, v) - if h >359 then h = 0 end - local rr, gg, bb = 0, 0, 0 - local const = 255 - - s = s/100 - v = v/100 - - local i = math.floor(h/60) - local f = h/60 - i - - local p = v*(1-s) - local q = v*(1-s*f) - local t = v*(1-(1-f)*s) - - if ( i == 0 ) then rr, gg, bb = v, t, p end - if ( i == 1 ) then rr, gg, bb = q, v, p end - if ( i == 2 ) then rr, gg, bb = p, v, t end - if ( i == 3 ) then rr, gg, bb = p, q, v end - if ( i == 4 ) then rr, gg, bb = t, p, v end - if ( i == 5 ) then rr, gg, bb = v, p, q end - - return rr*const, gg*const, bb*const -end - -function colorlib.HEXtoHSB(color) - local rr, gg, bb = colorlib.HEXtoRGB(color) - local h, s, b = colorlib.RGBtoHSB( rr, gg, bb ) - - return h, s, b -end - -function colorlib.HSBtoHEX(h, s, b) - local rr, gg, bb = colorlib.HSBtoRGB(h, s, b) - local color = colorlib.RGBtoHEX(rr, gg, bb) - - return color -end - ---Смешивание двух цветов на основе альфа-канала второго -function colorlib.alphaBlend(back_color, front_color, alpha_channel) - local INVERTED_ALPHA_CHANNEL = 255 - alpha_channel - - local back_color_rr, back_color_gg, back_color_bb = colorlib.HEXtoRGB(back_color) - local front_color_rr, front_color_gg, front_color_bb = colorlib.HEXtoRGB(front_color) - - local blended_rr = front_color_rr * INVERTED_ALPHA_CHANNEL / 255 + back_color_rr * alpha_channel / 255 - local blended_gg = front_color_gg * INVERTED_ALPHA_CHANNEL / 255 + back_color_gg * alpha_channel / 255 - local blended_bb = front_color_bb * INVERTED_ALPHA_CHANNEL / 255 + back_color_bb * alpha_channel / 255 - - INVERTED_ALPHA_CHANNEL, back_color_rr, back_color_gg, back_color_bb, front_color_rr, front_color_gg, front_color_bb = nil, nil, nil, nil, nil, nil, nil - - return colorlib.RGBtoHEX( blended_rr, blended_gg, blended_bb ) -end - ------------------------------------------------------------------------------------------------------------------------ - -local palette = { - 0x000000, 0x000040, 0x000080, 0x0000BF, 0x0000FF, 0x002400, 0x002440, 0x002480, 0x0024BF, 0x0024FF, 0x004900, 0x004940, 0x004980, 0x0049BF, 0x0049FF, 0x006D00, - 0x006D40, 0x006D80, 0x006DBF, 0x006DFF, 0x009200, 0x009240, 0x009280, 0x0092BF, 0x0092FF, 0x00B600, 0x00B640, 0x00B680, 0x00B6BF, 0x00B6FF, 0x00DB00, 0x00DB40, - 0x00DB80, 0x00DBBF, 0x00DBFF, 0x00FF00, 0x00FF40, 0x00FF80, 0x00FFBF, 0x00FFFF, 0x0F0F0F, 0x1E1E1E, 0x2D2D2D, 0x330000, 0x330040, 0x330080, 0x3300BF, 0x3300FF, - 0x332400, 0x332440, 0x332480, 0x3324BF, 0x3324FF, 0x334900, 0x334940, 0x334980, 0x3349BF, 0x3349FF, 0x336D00, 0x336D40, 0x336D80, 0x336DBF, 0x336DFF, 0x339200, - 0x339240, 0x339280, 0x3392BF, 0x3392FF, 0x33B600, 0x33B640, 0x33B680, 0x33B6BF, 0x33B6FF, 0x33DB00, 0x33DB40, 0x33DB80, 0x33DBBF, 0x33DBFF, 0x33FF00, 0x33FF40, - 0x33FF80, 0x33FFBF, 0x33FFFF, 0x3C3C3C, 0x4B4B4B, 0x5A5A5A, 0x660000, 0x660040, 0x660080, 0x6600BF, 0x6600FF, 0x662400, 0x662440, 0x662480, 0x6624BF, 0x6624FF, - 0x664900, 0x664940, 0x664980, 0x6649BF, 0x6649FF, 0x666D00, 0x666D40, 0x666D80, 0x666DBF, 0x666DFF, 0x669200, 0x669240, 0x669280, 0x6692BF, 0x6692FF, 0x66B600, - 0x66B640, 0x66B680, 0x66B6BF, 0x66B6FF, 0x66DB00, 0x66DB40, 0x66DB80, 0x66DBBF, 0x66DBFF, 0x66FF00, 0x66FF40, 0x66FF80, 0x66FFBF, 0x66FFFF, 0x696969, 0x787878, - 0x878787, 0x969696, 0x990000, 0x990040, 0x990080, 0x9900BF, 0x9900FF, 0x992400, 0x992440, 0x992480, 0x9924BF, 0x9924FF, 0x994900, 0x994940, 0x994980, 0x9949BF, - 0x9949FF, 0x996D00, 0x996D40, 0x996D80, 0x996DBF, 0x996DFF, 0x999200, 0x999240, 0x999280, 0x9992BF, 0x9992FF, 0x99B600, 0x99B640, 0x99B680, 0x99B6BF, 0x99B6FF, - 0x99DB00, 0x99DB40, 0x99DB80, 0x99DBBF, 0x99DBFF, 0x99FF00, 0x99FF40, 0x99FF80, 0x99FFBF, 0x99FFFF, 0xA5A5A5, 0xB4B4B4, 0xC3C3C3, 0xCC0000, 0xCC0040, 0xCC0080, - 0xCC00BF, 0xCC00FF, 0xCC2400, 0xCC2440, 0xCC2480, 0xCC24BF, 0xCC24FF, 0xCC4900, 0xCC4940, 0xCC4980, 0xCC49BF, 0xCC49FF, 0xCC6D00, 0xCC6D40, 0xCC6D80, 0xCC6DBF, - 0xCC6DFF, 0xCC9200, 0xCC9240, 0xCC9280, 0xCC92BF, 0xCC92FF, 0xCCB600, 0xCCB640, 0xCCB680, 0xCCB6BF, 0xCCB6FF, 0xCCDB00, 0xCCDB40, 0xCCDB80, 0xCCDBBF, 0xCCDBFF, - 0xCCFF00, 0xCCFF40, 0xCCFF80, 0xCCFFBF, 0xCCFFFF, 0xD2D2D2, 0xE1E1E1, 0xF0F0F0, 0xFF0000, 0xFF0040, 0xFF0080, 0xFF00BF, 0xFF00FF, 0xFF2400, 0xFF2440, 0xFF2480, - 0xFF24BF, 0xFF24FF, 0xFF4900, 0xFF4940, 0xFF4980, 0xFF49BF, 0xFF49FF, 0xFF6D00, 0xFF6D40, 0xFF6D80, 0xFF6DBF, 0xFF6DFF, 0xFF9200, 0xFF9240, 0xFF9280, 0xFF92BF, - 0xFF92FF, 0xFFB600, 0xFFB640, 0xFFB680, 0xFFB6BF, 0xFFB6FF, 0xFFDB00, 0xFFDB40, 0xFFDB80, 0xFFDBBF, 0xFFDBFF, 0xFFFF00, 0xFFFF40, 0xFFFF80, 0xFFFFBF, 0xFFFFFF, -} - --- Конвертер -function colorlib.convert24BitTo8Bit(hex24) - local encodedIndex = nil - local colorMatchFactor = nil - local colorMatchFactor_min = math.huge - - local red24, green24, blue24 = colorlib.HEXtoRGB(hex24) - - for colorIndex, colorPalette in ipairs(palette) do - local redPalette, greenPalette, bluePalette = colorlib.HEXtoRGB(colorPalette) - - colorMatchFactor = (redPalette-red24)^2 + (greenPalette-green24)^2 + (bluePalette-blue24)^2 - - if (colorMatchFactor < colorMatchFactor_min) then - encodedIndex = colorIndex - colorMatchFactor_min = colorMatchFactor - end - end - - return encodedIndex - 1 -end - -function colorlib.convert8BitTo24Bit(hex8) - return palette[hex8 + 1] -end - -return colorlib diff --git a/Beta/MineCode2/context.lua b/Beta/MineCode2/context.lua deleted file mode 100644 index 6c1abef9..00000000 --- a/Beta/MineCode2/context.lua +++ /dev/null @@ -1,137 +0,0 @@ -local component = require("component") -local event = require("event") -local unicode = require("unicode") -local ecs = require("ECSAPI") -local gpu = component.gpu - -local context = {} - -local separatorColor = 0xcccccc -local shortcutAutism = 3 - ----------------------------------------------------------------------------------------------------------------- - ---ОБЪЕКТЫ -local obj = {} -local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} -end - -function context.menu(x, y, ...) - - local data = {...} - local sData = #data - - obj = {} - - --Получаем размер экрана - local xSize, ySize = gpu.getResolution() - - --Получаем самую жирную полоску текста - local biggestElement = 0 - for i = 1, sData do - if data[i] ~= "-" then - local length = unicode.len(data[i][1]) - if data[i][3] then length = length + shortcutAutism + unicode.len(data[i][3]) end - biggestElement = math.max(biggestElement, length) - length = nil - end - end - - --Задание ширины и высоты - local width = 4 + biggestElement - local height = sData - - --А это чтоб за края экрана не лезло - if y + height >= ySize then y = ySize - height end - if x + width + 1 >= xSize then x = xSize - width - 1 end - - --Рисуем окошечко и запоминаем, че было до него (сначала был Бог...!) - local oldPixels = ecs.rememberOldPixels(x, y, x + width + 1, y + height) - ecs.square(x, y, width, height, 0xffffff) - ecs.windowShadow(x, y, width, height) - gpu.setBackground(0xffffff) - - --Нарисовать конкретный элемент - local function drawElement(i, background, foreground, yPos) - - if background then ecs.square(x, yPos, width, 1, background) end - - --Получаем текстик - local text - if data[i] == "-" then - ecs.colorText(x, yPos, separatorColor, string.rep("─", width)) - else - --Нужный цвет - local color = foreground or 0x000000 - if data[i][2] then color = separatorColor end - - --Рисуем текстик - ecs.colorText(x + 2, yPos, color, data[i][1]) - - --Рисуем сокращение - if data[i][3] then gpu.set(x + width - 2 - unicode.len(data[i][3]), yPos, data[i][3]) end - - if not data[i][2] then newObj("Elements", i, x, yPos, x + width - 1, yPos) end - end - end - - --Рисуем все элементы - local counter = 0 - local yPos - for i = 1, sData do - yPos = y + counter - - drawElement(i, nil, nil, yPos) - - counter = counter + 1 - end - - --Проверка нажатия - local action - local e = {event.pull("touch")} - if obj["Elements"] then - for key, val in pairs(obj["Elements"]) do - if ecs.clickedAtArea(e[3], e[4], obj["Elements"][key][1], obj["Elements"][key][2], obj["Elements"][key][3], obj["Elements"][key][4]) then - - --ecs.error("Кол-во объектов: "..#obj["Elements"]..", кликнули на объект номер = "..tostring(key)..", #Data = "..#data..", sData ="..sData) - - drawElement(key, ecs.colors.blue, 0xffffff, e[4]) - os.sleep(0.3) - action = data[key][1] - break - end - end - end - - --Красим то, че было - ecs.drawOldPixels(oldPixels) - - --Возвращаем выбранное - return action - -end - ----------------------------------------------------------------------------------------------------------------- - --- while true do --- local e = {event.pull("touch")} --- ecs.prepareToExit() --- local action = context.menu(e[3], e[4], {"Показать содержимое"}, "-", {"Вырезать", false, "^X"}, {"Копировать", false, "^C"}, {"Вставить", true, "^V"}, "-", {"Переименовать"}, {"Создать ярлык"}, {"Добавить в архив"}, "-", {"Удалить", false, "⌫"}) --- ecs.prepareToExit() --- print("Ты выбрал = "..tostring(action)) --- end - ---local action = context.menu(6, 2, {(function() if showHiddenFiles then return "Скрывать скрытые файлы" else return "Показывать скрытые файлы" end end)()}, {(function() if showSystemFiles then return "Скрывать системные файлы" else return "Показывать системные файлы" end end)()}, "-", {(function() if showFileFormat then return "Скрывать формат файлов" else return "Показывать формат файлов" end end)()}) - - -return context - - - - - - - - diff --git a/Beta/MineCode2/doubleBuffering.lua b/Beta/MineCode2/doubleBuffering.lua deleted file mode 100644 index 7c024b56..00000000 --- a/Beta/MineCode2/doubleBuffering.lua +++ /dev/null @@ -1,467 +0,0 @@ - --- Адаптивная загрузка необходимых библиотек и компонентов -local libraries = { - ["component"] = "component", - ["unicode"] = "unicode", - ["image"] = "image", - ["colorlib"] = "colorlib", -} - -local components = { - ["gpu"] = "gpu", -} - -for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end -for comp in pairs(components) do if not _G[comp] then _G[comp] = _G.component[components[comp]] end end -libraries, components = nil, nil - -local buffer = {} -local debug = false -local sizeOfPixelData = 3 - ------------------------------------------------------------------------------------------------------- - ---Формула конвертации индекса массива изображения в абсолютные координаты пикселя изображения -local function convertIndexToCoords(index) - --Приводим индекс к корректному виду (1 = 1, 4 = 2, 7 = 3, 10 = 4, 13 = 5, ...) - index = (index + sizeOfPixelData - 1) / sizeOfPixelData - --Получаем остаток от деления индекса на ширину изображения - local ostatok = index % buffer.screen.width - --Если остаток равен 0, то х равен ширине изображения, а если нет, то х равен остатку - local x = (ostatok == 0) and buffer.screen.width or ostatok - --А теперь как два пальца получаем координату по Y - local y = math.ceil(index / buffer.screen.width) - --Очищаем остаток из оперативки - ostatok = nil - --Возвращаем координаты - return x, y -end - ---Формула конвертации абсолютных координат пикселя изображения в индекс для массива изображения -local function convertCoordsToIndex(x, y) - return (buffer.screen.width * (y - 1) + x) * sizeOfPixelData - sizeOfPixelData + 1 -end - -local function printDebug(line, text) - if debug then - ecs.square(1, line, buffer.screen.width, 1, 0x262626) - ecs.colorText(2, line, 0xFFFFFF, text) - end -end - --- Установить ограниченную зону рисования. Все пиксели, не попадающие в эту зону, будут игнорироваться. -function buffer.setDrawLimit(x, y, width, height) - buffer.drawLimit = { x1 = x, y1 = y, x2 = x + width - 1, y2 = y + height - 1 } -end - --- Удалить ограничение зоны рисования, по умолчанию она будет от 1х1 до координат размера экрана. -function buffer.resetDrawLimit() - buffer.drawLimit = {x1 = 1, y1 = 1, x2 = buffer.screen.width, y2 = buffer.screen.height} -end - --- Создать массив буфера с базовыми переменными и базовыми цветами. Т.е. черный фон, белый текст. -function buffer.start() - buffer.screen = {} - buffer.screen.current = {} - buffer.screen.new = {} - buffer.screen.width, buffer.screen.height = gpu.getResolution() - - buffer.totalCountOfGPUOperations = 0 - buffer.localCountOfGPUOperations = 0 - buffer.resetDrawLimit() - - for y = 1, buffer.screen.height do - for x = 1, buffer.screen.width do - table.insert(buffer.screen.current, 0x010101) - table.insert(buffer.screen.current, 0xFEFEFE) - table.insert(buffer.screen.current, " ") - - table.insert(buffer.screen.new, 0x010101) - table.insert(buffer.screen.new, 0xFEFEFE) - table.insert(buffer.screen.new, " ") - end - end -end - --- Получить информацию о пикселе из буфера -function buffer.get(x, y) - local index = convertCoordsToIndex(x, y) - if x >= buffer.drawLimit.x1 and y >= buffer.drawLimit.y1 and x <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then - return buffer.screen.current[index], buffer.screen.current[index + 1], buffer.screen.current[index + 2] - else - error("Невозможно получить указанные значения, так как указанные координаты лежат за пределами экрана.\n") - end -end - --- Установить пиксель в буфере -function buffer.set(x, y, background, foreground, symbol) - local index = convertCoordsToIndex(x, y) - if x >= buffer.drawLimit.x1 and y >= buffer.drawLimit.y1 and x <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then - buffer.screen.new[index] = background - buffer.screen.new[index + 1] = foreground - buffer.screen.new[index + 2] = symbol - end -end - ---Нарисовать квадрат -function buffer.square(x, y, width, height, background, foreground, symbol, transparency) - local index - if transparency then transparency = transparency * 2.55 end - for j = y, (y + height - 1) do - for i = x, (x + width - 1) do - if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then - index = convertCoordsToIndex(i, j) - if transparency then - buffer.screen.new[index] = colorlib.alphaBlend(buffer.screen.new[index], background, transparency) - buffer.screen.new[index + 1] = colorlib.alphaBlend(buffer.screen.new[index + 1], background, transparency) - else - buffer.screen.new[index] = background - buffer.screen.new[index + 1] = foreground - buffer.screen.new[index + 2] = symbol - end - end - end - end -end - ---Заливка области изображения (рекурсивная, говно-метод) -function buffer.fill(x, y, background, foreground, symbol) - - local startBackground, startForeground, startSymbol - - local function doFill(xStart, yStart) - local index = convertCoordsToIndex(xStart, yStart) - - if - buffer.screen.new[index] ~= startBackground or - -- buffer.screen.new[index + 1] ~= startForeground or - -- buffer.screen.new[index + 2] ~= startSymbol or - buffer.screen.new[index] == background - -- buffer.screen.new[index + 1] == foreground or - -- buffer.screen.new[index + 2] == symbol - then - return - end - - --Заливаем в память - if xStart >= buffer.drawLimit.x1 and yStart >= buffer.drawLimit.y1 and xStart <= buffer.drawLimit.x2 and yStart <= buffer.drawLimit.y2 then - buffer.screen.new[index] = background - buffer.screen.new[index + 1] = foreground - buffer.screen.new[index + 2] = symbol - end - - doFill(xStart + 1, yStart) - doFill(xStart - 1, yStart) - doFill(xStart, yStart + 1) - doFill(xStart, yStart - 1) - - iterator = nil - end - - local startIndex = convertCoordsToIndex(x, y) - startBackground = buffer.screen.new[startIndex] - startForeground = buffer.screen.new[startIndex + 1] - startSymbol = buffer.screen.new[startIndex + 2] - - doFill(x, y) -end - ---Нарисовать окружность, алгоритм спизжен с вики -function buffer.circle(xCenter, yCenter, radius, background, foreground, symbol) - --Подфункция вставки точек - local function insertPoints(x, y) - buffer.set(xCenter + x * 2, yCenter + y, background, foreground, symbol) - buffer.set(xCenter + x * 2, yCenter - y, background, foreground, symbol) - buffer.set(xCenter - x * 2, yCenter + y, background, foreground, symbol) - buffer.set(xCenter - x * 2, yCenter - y, background, foreground, symbol) - - buffer.set(xCenter + x * 2 + 1, yCenter + y, background, foreground, symbol) - buffer.set(xCenter + x * 2 + 1, yCenter - y, background, foreground, symbol) - buffer.set(xCenter - x * 2 + 1, yCenter + y, background, foreground, symbol) - buffer.set(xCenter - x * 2 + 1, yCenter - y, background, foreground, symbol) - end - - local x = 0 - local y = radius - local delta = 3 - 2 * radius; - while (x < y) do - insertPoints(x, y); - insertPoints(y, x); - if (delta < 0) then - delta = delta + (4 * x + 6) - else - delta = delta + (4 * (x - y) + 10) - y = y - 1 - end - x = x + 1 - end - - if x == y then insertPoints(x, y) end -end - ---Скопировать область изображения и вернуть ее в виде массива -function buffer.copy(x, y, width, height) - local copyArray = { - ["width"] = width, - ["height"] = height, - } - - if x < 1 or y < 1 or x + width - 1 > buffer.screen.width or y + height - 1 > buffer.screen.height then - errror("Область копирования выходит за пределы экрана.") - end - - local index - for j = y, (y + height - 1) do - for i = x, (x + width - 1) do - index = convertCoordsToIndex(i, j) - table.insert(copyArray, buffer.screen.new[index]) - table.insert(copyArray, buffer.screen.new[index + 1]) - table.insert(copyArray, buffer.screen.new[index + 2]) - end - end - - return copyArray -end - ---Вставить скопированную ранее область изображения -function buffer.paste(x, y, copyArray) - local index, arrayIndex - if not copyArray or #copyArray == 0 then error("Массив области экрана пуст.") end - - for j = y, (y + copyArray.height - 1) do - for i = x, (x + copyArray.width - 1) do - if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then - --Рассчитываем индекс массива основного изображения - index = convertCoordsToIndex(i, j) - --Копипаст формулы, аккуратнее! - --Рассчитываем индекс массива вставочного изображения - arrayIndex = (copyArray.width * ((j - y + 1) - 1) + (i - x + 1)) * sizeOfPixelData - sizeOfPixelData + 1 - --Вставляем данные - buffer.screen.new[index] = copyArray[arrayIndex] - buffer.screen.new[index + 1] = copyArray[arrayIndex + 1] - buffer.screen.new[index + 2] = copyArray[arrayIndex + 2] - end - end - end -end - ---Нарисовать линию, алгоритм спизжен с вики -function buffer.line(x1, y1, x2, y2, background, foreground, symbol) - local deltaX = math.abs(x2 - x1) - local deltaY = math.abs(y2 - y1) - local signX = (x1 < x2) and 1 or -1 - local signY = (y1 < y2) and 1 or -1 - - local errorCyka = deltaX - deltaY - local errorCyka2 - - buffer.set(x2, y2, background, foreground, symbol) - - while(x1 ~= x2 or y1 ~= y2) do - buffer.set(x1, y1, background, foreground, symbol) - - errorCyka2 = errorCyka * 2 - - if (errorCyka2 > -deltaY) then - errorCyka = errorCyka - deltaY - x1 = x1 + signX - end - - if (errorCyka2 < deltaX) then - errorCyka = errorCyka + deltaX - y1 = y1 + signY - end - end -end - -function buffer.text(x, y, color, text) - local index - local sText = unicode.len(text) - for i = 1, sText do - if (x + i - 1) >= buffer.drawLimit.x1 and y >= buffer.drawLimit.y1 and (x + i - 1) <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then - index = convertCoordsToIndex(x + i - 1, y) - buffer.screen.new[index + 1] = color - buffer.screen.new[index + 2] = unicode.sub(text, i, i) - end - end -end - -function buffer.image(x, y, picture) - if not image then image = require("image") end - local index, imageIndex - for j = y, (y + picture.height - 1) do - for i = x, (x + picture.width - 1) do - if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then - index = convertCoordsToIndex(i, j) - --Копипаст формулы! - imageIndex = (picture.width * ((j - y + 1) - 1) + (i - x + 1)) * 4 - 4 + 1 - - if picture[imageIndex + 2] ~= 0x00 then - buffer.screen.new[index] = colorlib.alphaBlend(buffer.screen.new[index], picture[imageIndex], picture[imageIndex + 2]) - else - buffer.screen.new[index] = picture[imageIndex] - end - buffer.screen.new[index + 1] = picture[imageIndex + 1] - buffer.screen.new[index + 2] = picture[imageIndex + 3] - end - end - end -end - -function buffer.button(x, y, width, height, background, foreground, text) - local textPosX = math.floor(x + width / 2 - unicode.len(text) / 2) - local textPosY = math.floor(y + height / 2) - buffer.square(x, y, width, height, background, 0xFFFFFF, " ") - buffer.text(textPosX, textPosY, foreground, text) - - return x, y, (x + width - 1), (y + height - 1) -end - -function buffer.adaptiveButton(x, y, xOffset, yOffset, background, foreground, text) - local width = xOffset * 2 + unicode.len(text) - local height = yOffset * 2 + 1 - - buffer.square(x, y, width, height, background, 0xFFFFFF, " ") - buffer.text(x + xOffset, y + yOffset, foreground, text) - - return x, y, (x + width - 1), (y + height - 1) -end - -function buffer.scrollBar(x, y, width, height, countOfAllElements, currentElement, backColor, frontColor) - local sizeOfScrollBar = math.ceil(1 / countOfAllElements * height) - local displayBarFrom = math.floor(y + height * ((currentElement - 1) / countOfAllElements)) - - buffer.square(x, y, width, height, backColor, 0xFFFFFF, " ") - buffer.square(x, displayBarFrom, width, sizeOfScrollBar, frontColor, 0xFFFFFF, " ") - - sizeOfScrollBar, displayBarFrom = nil, nil -end - -function buffer.calculateDifference(x, y) - local index = convertCoordsToIndex(x, y) - local backgroundIsChanged, foregroundIsChanged, symbolIsChanged = false, false, false - - --Если цвет фона на новом экране отличается от цвета фона на текущем, то - if buffer.screen.new[index] ~= buffer.screen.current[index] then - --Присваиваем цвету фона на текущем экране значение цвета фона на новом экране - buffer.screen.current[index] = buffer.screen.new[index] - - --Говорим системе, что что фон изменился - backgroundIsChanged = true - end - - index = index + 1 - - --Аналогично для цвета текста - if buffer.screen.new[index] ~= buffer.screen.current[index] then - buffer.screen.current[index] = buffer.screen.new[index] - foregroundIsChanged = true - --if _G.cyka then ecs.error("new = \"" .. ecs.HEXtoString(buffer.screen.new[index], 6) .."\", current = \"" .. ecs.HEXtoString(buffer.screen.current[index], 6) .."\"") end - end - - index = index + 1 - - --И для символа - if buffer.screen.new[index] ~= buffer.screen.current[index] then - buffer.screen.current[index] = buffer.screen.new[index] - symbolIsChanged = true - end - - return backgroundIsChanged, foregroundIsChanged, symbolIsChanged -end - -function buffer.draw(force) - local currentBackground, currentForeground = -math.huge, -math.huge - local backgroundIsChanged, foregroundIsChanged, symbolIsChanged - local index - local massiv - buffer.localCountOfGPUOperations = 0 - - for y = 1, buffer.screen.height do - local x = 1 - while x <= buffer.screen.width do - - index = convertCoordsToIndex(x, y) - - backgroundIsChanged, foregroundIsChanged, symbolIsChanged = buffer.calculateDifference(x, y) - - --Оптимизация by me - --Ну, скорее, жесткий багфикс - --Но "оптимизация" звучит красивее - --Если были найдены какие-то отличия нового экрана от старого, то корректируем эти отличия через gpu.set() - if backgroundIsChanged or foregroundIsChanged or symbolIsChanged or force then - - if currentBackground ~= buffer.screen.current[index] then - gpu.setBackground(buffer.screen.current[index]) - currentBackground = buffer.screen.current[index] - buffer.localCountOfGPUOperations = buffer.localCountOfGPUOperations + 1 - end - - index = index + 1 - - if currentForeground ~= buffer.screen.current[index] then - gpu.setForeground(buffer.screen.current[index]) - currentForeground = buffer.screen.current[index] - buffer.localCountOfGPUOperations = buffer.localCountOfGPUOperations + 1 - end - - index = index - 1 - - --Оптимизация by Krutoy - massiv = { buffer.screen.current[index + 2] } - - --Отрисовка линиями. Не трожь, сука! - local iIndex - for i = (x + 1), buffer.screen.width do - iIndex = convertCoordsToIndex(i, y) - if - buffer.screen.current[index] == buffer.screen.new[iIndex] and - ( - buffer.screen.new[iIndex + 2] == " " - or - buffer.screen.current[index + 1] == buffer.screen.new[iIndex + 1] - ) - then - buffer.calculateDifference(i, y) - table.insert(massiv, buffer.screen.current[iIndex + 2]) - else - break - end - end - - --os.sleep(0.2) - gpu.set(x, y, table.concat(massiv)) - - x = x + #massiv - 1 - - buffer.localCountOfGPUOperations = buffer.localCountOfGPUOperations + 1 - end - - x = x + 1 - end - end - - buffer.totalCountOfGPUOperations = buffer.totalCountOfGPUOperations + buffer.localCountOfGPUOperations - printDebug(50, "Общее число GPU-операций: " .. buffer.totalCountOfGPUOperations .. ", число операций при последнем рендере: " .. buffer.localCountOfGPUOperations) -end - ------------------------------------------------------------------------------------------------------- - -buffer.start() - ------------------------------------------------------------------------------------------------------- - -return buffer - - - - - - - - - - - - - diff --git a/Beta/MineCode2/filemanager.lua b/Beta/MineCode2/filemanager.lua deleted file mode 100644 index 0ae94d79..00000000 --- a/Beta/MineCode2/filemanager.lua +++ /dev/null @@ -1,95 +0,0 @@ - -local fs = require("filesystem") -local buffer = require("doubleBuffering") -local filemanager = {} - -local massiv = { - { - name = "Root", - showContent = true, - content = { - { - name = "File1", - }, - { - name = "File2", - }, - { - name = "Folder1", - showContent = true, - content = { - { - name = "FileInFolder1", - }, - { - name = "FileInFolder2", - }, - { - name = "FolderInFolder1", - showContent = true, - content = { - { - name = "FileInFolderInFolder1", - }, - }, - }, - }, - }, - { - name = "File3", - }, - { - name = "File4", - }, - }, - }, -} - -filemanager.colors = { - background = 0xcccccc, - text = 0x262626, - scrollBar = 0x444444, - scrollBarPipe = 0x24c0ff, -} - -local function recursiveDraw(x, y, array) - for i = 1, #array do - - if array[i].content then - if array[i].showContent then - buffer.text(x, y, filemanager.colors.text, "∨ ▄ " .. array[i].name) - y = y + 1 - _, y = recursiveDraw(x + 2, y, array[i].content) - else - buffer.text(x, y, filemanager.colors.text, "> ▄ " .. array[i].name) - y = y + 1 - end - else - buffer.text(x, y, filemanager.colors.text, " • " .. array[i].name) - y = y + 1 - end - end - - return x, y -end - -function filemanager.draw(x, y, width, height, path, fromElement) - buffer.square(x, y, width, height, filemanager.colors.background, 0xFFFFFF, " ") - - buffer.setDrawLimit(x, y, width - 2, height) - recursiveDraw(x + 1, y, massiv) - buffer.resetDrawLimit() - - buffer.scrollBar(x + width - 1, y, 1, height, #massiv, 1, filemanager.colors.scrollBar, filemanager.colors.scrollBarPipe) -end - -return filemanager - - - - - - - - - diff --git a/Beta/MineCode2/image.lua b/Beta/MineCode2/image.lua deleted file mode 100644 index 5a2fd7b2..00000000 --- a/Beta/MineCode2/image.lua +++ /dev/null @@ -1,1091 +0,0 @@ - ----------------------------------------- OpenComputers Image Format (OCIF) ----------------------------------------------------------- - ---[[ - - Автор: Pornogion - VK: https://vk.com/id88323331 - Соавтор: IT - VK: https://vk.com/id7799889 - - Основные функции: - - image.load(string путь): table изображение - Загружает существующую картинку в формате .pic и возвращает ее - в качестве массива (таблицы). - - image.draw(int x, int y, table изображение) - Рисует на экране загруженную ранее картинку по указанным координатам. - - image.save(string путь, table изображение [, int метод кодирования]) - Сохраняет указанную картинку по указанному пути в формате .pic, - по умолчанию используя метод кодирования 3. Рекомендуется - использовать именно его. - - Функции для работы с изображением: - - image.expand(table картинка, string направление, int количество пикселей[, int цвет фона, int цвет текста, int прозрачность, char символ]): table картинка - Расширяет указанную картинку в указанном направлении (fromRight, fromLeft, fromTop, fromBottom), - создавая при этом пустые белые пиксели. Если указаны опциональные аргументы, то вместо пустых - пикселей могут быть вполне конкретные значения. - - image.crop(table картинка, string направление, int количество пикселей): table картинка - Обрезает указанную картинку в указанном направлении (fromRight, fromLeft, fromTop, fromBottom), - удаляя лишние пиксели. - - image.rotate(table картинка, int угол): table картинка - Поворачивает указанную картинку на указанный угол. Угол может иметь - значение 90, 180 и 270 градусов. - - image.flipVertical(table картинка): table картинка - Отражает указанную картинку по вертикали. - - image.flipHorizontal(table картинка): table картинка - Отражает указанную картинку по горизонтали. - - Функции для работы с цветом: - - image.hueSaturationBrightness(table картинка, int тон, int насыщенность, int яркость): table картинка - Корректирует цветовой тон, насыщенность и яркость указанной картинки. - Значения аргументов могут быть отрицательными для уменьшения параметра - и положительными для его увеличения. Если значение, к примеру, насыщенности - менять не требуется, просто указывайте 0. - - Для удобства вы можете использовать следующие сокращения: - image.hue(table картинка, int тон): table картинка - image.saturation(table картинка, int насыщенность): table картинка - image.brightness(table картинка, int яркость): table картинка - image.blackAndWhite(table картинка): table картинка - - image.colorBalance(table картинка, int красный, int зеленый, int синий): table картинка - Корректирует цветовые каналы изображения указанной картинки. Аргументы цветовых - каналов могут принимать как отрицательные значения для уменьшения интенсивности канала, - так и положительные для увеличения. - - image.invert(table картинка): table картинка - Инвертирует цвета в указанной картинке. - - image.photoFilter(table картинка, int цвет, int прозрачность): table картинка - Накладывает на указанное изображение фотофильтр с указанной прозрачностью. - Прозрачность может быть от 0 до 255. - - image.replaceColor(table картинка, int заменяемыйЦвет, int цветДляЗамены): table картинка - Заменяет в указанном изображении один конкретный цвет на другой. -]] - ---------------------------------------- Подгрузка библиотек -------------------------------------------------------------- - --- Адаптивная загрузка необходимых библиотек и компонентов -local libraries = { - ["component"] = "component", - ["unicode"] = "unicode", - ["fs"] = "filesystem", - ["colorlib"] = "colorlib", - ["bit"] = "bit32", -} - -local components = { - ["gpu"] = "gpu", -} - -for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end -for comp in pairs(components) do if not _G[comp] then _G[comp] = _G.component[components[comp]] end end -libraries, components = nil, nil - -local image = {} - --------------------------------------------- Переменные ------------------------------------------------------------------- - ---Константы программы -local constants = { - OCIFSignature = "OCIF", - encodingMethods = { - raw = 0, - OCIF1 = 1, - OCIF2 = 2, - OCIF3 = 3, - }, - OCIF2Elements = { - alphaStart = "A", - symbolStart = "S", - backgroundStart = "B", - foregroundStart = "F", - }, - elementCount = 4, - byteSize = 8, - nullChar = 0, - rawImageLoadStep = 19, - compressedFileFormat = ".pic", - rawFileFormat = ".rawpic", - pngFileFormat = ".png", -} - ----------------------------------------- Локальные функции ------------------------------------------------------------------- - ---Формула конвертации индекса массива изображения в абсолютные координаты пикселя изображения -local function convertIndexToCoords(index, width) - --Приводим индекс к корректному виду (1 = 1, 4 = 2, 7 = 3, 10 = 4, 13 = 5, ...) - index = (index + constants.elementCount - 1) / constants.elementCount - --Получаем остаток от деления индекса на ширину изображения - local ostatok = index % width - --Если остаток равен 0, то х равен ширине изображения, а если нет, то х равен остатку - local x = (ostatok == 0) and width or ostatok - --А теперь как два пальца получаем координату по Y - local y = math.ceil(index / width) - --Очищаем остаток из оперативки - ostatok = nil - --Возвращаем координаты - return x, y -end - ---Формула конвертации абсолютных координат пикселя изображения в индекс для массива изображения -local function convertCoordsToIndex(x, y, width) - return (width * (y - 1) + x) * constants.elementCount - constants.elementCount + 1 -end - ---Костыльное получение размера массива, ибо автор луа не позволяет ---подсчитывать ненумерические индексы через #massiv ---мда, мда ---... ---мда -local function getArraySize(array) - local size = 0 - for key in pairs(array) do - size = size + 1 - end - return size -end - ---Получить количество байт, которое можно извлечь из указанного числа -local function getCountOfBytes(number) - if number == 0 or number == 1 then return 1 end - return math.ceil(math.log(number, 256)) -end - ---Распидорасить число на составляющие байты -local function extractBytesFromNumber(number, countOfBytesToExtract) - local bytes = {} - local byteCutter = 0xff - for i = 1, countOfBytesToExtract do - table.insert(bytes, 1, bit32.rshift(bit32.band(number, byteCutter), (i-1)*8)) - byteCutter = bit32.lshift(byteCutter, 8) - end - return table.unpack(bytes) -end - ---Склеить байты и создать из них число -local function mergeBytesToNumber(...) - local bytes = {...} - local finalNumber = bytes[1] - for i = 2, #bytes do - finalNumber = bit32.bor(bit32.lshift(finalNumber, 8), bytes[i]) - end - return finalNumber -end - --- Сконвертировать все переданные байты в строку -local function convertBytesToString(...) - local bytes = {...} - for i = 1, #bytes do - bytes[i] = string.char(bytes[i]) - end - return table.concat(bytes) -end - ---Выделить бит-терминатор в первом байте UTF-8 символа: 1100 0010 --> 0010 0000 -local function selectTerminateBit_l() - local prevByte = nil - local prevTerminateBit = nil - - return function( byte ) - local x, terminateBit = nil - if ( prevByte == byte ) then - return prevTerminateBit - end - - x = bit32.band( bit32.bnot(byte), 0x000000FF ) - x = bit32.bor( x, bit32.rshift(x, 1) ) - x = bit32.bor( x, bit32.rshift(x, 2) ) - x = bit32.bor( x, bit32.rshift(x, 4) ) - x = bit32.bor( x, bit32.rshift(x, 8) ) - x = bit32.bor( x, bit32.rshift(x, 16) ) - - terminateBit = x - bit32.rshift(x, 1) - - prevByte = byte - prevTerminateBit = terminateBit - - return terminateBit - end -end -local selectTerminateBit = selectTerminateBit_l() - ---Прочитать n байтов из файла, возвращает прочитанные байты как число, если не удалось прочитать, то возвращает 0 -local function readBytes(file, count) - local readedBytes = file:read(count) - return mergeBytesToNumber(string.byte(readedBytes, 1, count)) -end - ---Подготавливает цвета и символ для записи в файл сжатого формата -local function encodePixel(background, foreground, alpha, char) - --Расхерачиваем жирные цвета в компактные цвета - local ascii_background1, ascii_background2, ascii_background3 = colorlib.HEXtoRGB(background) - local ascii_foreground1, ascii_foreground2, ascii_foreground3 = colorlib.HEXtoRGB(foreground) - --Расхерачиваем жирный код юникод-символа в несколько миленьких ascii-кодов - local ascii_char1, ascii_char2, ascii_char3, ascii_char4, ascii_char5, ascii_char6 = string.byte( char, 1, 6 ) - ascii_char1 = ascii_char1 or constants.nullChar - --Возвращаем все расхераченное - return ascii_background1, ascii_background2, ascii_background3, ascii_foreground1, ascii_foreground2, ascii_foreground3, alpha, ascii_char1, ascii_char2, ascii_char3, ascii_char4, ascii_char5, ascii_char6 -end - ---Декодирование UTF-8 символа -local function decodeChar(file) - local first_byte = readBytes(file, 1) - local charcode_array = {first_byte} - local len = 1 - - local middle = selectTerminateBit(first_byte) - if ( middle == 32 ) then - len = 2 - elseif ( middle == 16 ) then - len = 3 - elseif ( middle == 8 ) then - len = 4 - elseif ( middle == 4 ) then - len = 5 - elseif ( middle == 2 ) then - len = 6 - end - - for i = 1, len-1 do - table.insert( charcode_array, readBytes(file, 1) ) - end - - return string.char( table.unpack( charcode_array ) ) -end - ---Правильное конвертирование HEX-переменной в строковую -local function HEXtoSTRING(color, bitCount, withNull) - local stro4ka = string.format("%X",color) - local sStro4ka = unicode.len(stro4ka) - - if sStro4ka < bitCount then - stro4ka = string.rep("0", bitCount - sStro4ka) .. stro4ka - end - - sStro4ka = nil - - if withNull then return "0x"..stro4ka else return stro4ka end -end - ---Получение формата файла -local function getFileFormat(path) - local name = fs.name(path) - local starting, ending = string.find(name, "(.)%.[%d%w]*$") - if starting == nil then - return nil - else - return unicode.sub(name, starting + 1, -1) - end - name, starting, ending = nil, nil, nil -end - ---Прочесть сигнатуру файла и сравнить ее с константой -local function readSignature(file) - local readedSignature = file:read(4) - if readedSignature ~= constants.OCIFSignature then - file:close() - error("Can't load file: wrong OCIF format signature (\""..readedSignature .. "\" ~= \"" ..constants.OCIFSignature .. "\")") - end -end - ---Записать сигнатуру в файл -local function writeSignature(file) - file:write(constants.OCIFSignature) -end - ---Сжать все цвета в изображении в 8-битную палитру -local function compressImageColorsTo8Bit(picture) - for i = 1, #picture, 4 do - picture[i] = colorlib.convert24BitTo8Bit(picture[i]) - picture[i + 1] = colorlib.convert24BitTo8Bit(picture[i + 1]) - if i % 505 == 0 then os.sleep(0) end - end - return picture -end - ------------------------------- Все, что касается формата OCIF1 ------------------------------------------------------------ - --- Запись в файл сжатого OCIF-формата изображения -local function saveOCIF1(file, picture) - local encodedPixel - file:write( string.char( picture.width ) ) - file:write( string.char( picture.height ) ) - - for i = 1, picture.width * picture.height * constants.elementCount, constants.elementCount do - encodedPixel = - { - encodePixel(picture[i], picture[i + 1], picture[i + 2], picture[i + 3]) - } - for j = 1, #encodedPixel do - file:write( string.char( encodedPixel[j] ) ) - end - end - - file:close() -end - ---Чтение из файла сжатого OCIF-формата изображения, возвращает массив типа 2 (подробнее о типах см. конец файла) -local function loadOCIF1(file) - local picture = {} - - --Читаем ширину и высоту файла - picture.width = readBytes(file, 1) - picture.height = readBytes(file, 1) - - for i = 1, picture.width * picture.height do - --Читаем бекграунд - table.insert(picture, readBytes(file, 3)) - --Читаем форграунд - table.insert(picture, readBytes(file, 3)) - --Читаем альфу - table.insert(picture, readBytes(file, 1)) - --Читаем символ - table.insert(picture, decodeChar( file )) - end - - file:close() - - return picture -end - ------------------------------------------- Все, что касается формата OCIF2 ------------------------------------------------ - -local function saveOCIF2(file, picture, compressColors) - --Записываем ширину изображения - file:write(string.char(picture.width)) - file:write(string.char(picture.height)) - - --Группируем картинку - local grouppedPucture = image.convertToGroupedImage(picture) - - --Перебираем все альфы - for alpha in pairs(grouppedPucture) do - --Получаем размер массива, содержащего символы - local arraySize = getArraySize(grouppedPucture[alpha]) - local countOfBytesForArraySize = getCountOfBytes(arraySize) - --Записываем в файл символ АльфаСтарта, размер массива альфы и само значение альфы - file:write( - constants.OCIF2Elements.alphaStart, - string.char(countOfBytesForArraySize), - convertBytesToString(extractBytesFromNumber(arraySize, countOfBytesForArraySize)), - string.char(alpha) - ) - - for symbol in pairs(grouppedPucture[alpha]) do - --Записываем заголовок - file:write(constants.OCIF2Elements.symbolStart) - --Записываем количество всех цветов текста и символ - if compressColors then - file:write( - string.char(getArraySize(grouppedPucture[alpha][symbol])), - convertBytesToString(string.byte(symbol, 1, 6)) - ) - else - file:write( - convertBytesToString(extractBytesFromNumber(getArraySize(grouppedPucture[alpha][symbol]), 3)), - convertBytesToString(string.byte(symbol, 1, 6)) - ) - end - - for foreground in pairs(grouppedPucture[alpha][symbol]) do - --Записываем заголовок - file:write(constants.OCIF2Elements.foregroundStart) - --Записываем количество цветов фона и цвет текста - if compressColors then - file:write( - string.char(getArraySize(grouppedPucture[alpha][symbol][foreground])), - string.char(foreground) - ) - else - file:write( - convertBytesToString(extractBytesFromNumber(getArraySize(grouppedPucture[alpha][symbol][foreground]), 3)), - convertBytesToString(extractBytesFromNumber(foreground, 3)) - ) - end - - for background in pairs(grouppedPucture[alpha][symbol][foreground]) do - --Записываем заголовок и размер массива координат - file:write( - constants.OCIF2Elements.backgroundStart, - convertBytesToString(extractBytesFromNumber(getArraySize(grouppedPucture[alpha][symbol][foreground][background]), 2)) - ) - --Записываем цвет фона - if compressColors then - file:write(string.char(background)) - else - file:write(convertBytesToString(extractBytesFromNumber(background, 3))) - end - - --Записываем координаты - for i = 1, #grouppedPucture[alpha][symbol][foreground][background], 2 do - file:write( - string.char(grouppedPucture[alpha][symbol][foreground][background][i]), - string.char(grouppedPucture[alpha][symbol][foreground][background][i + 1]) - ) - end - end - end - end - end - - file:close() -end - -local function loadOCIF2(file, decompressColors) - local picture = {} - - --Читаем размер изображения - local readedWidth = string.byte(file:read(1)) - local readedHeight = string.byte(file:read(1)) - picture.width = readedWidth - picture.height = readedHeight - - local header, alpha, symbol, foreground, background, alphaSize, symbolSize, foregroundSize, backgroundSize = "" - while true do - header = file:read(1) - if not header then break end - -- print("----------------------") - -- print("Заголовок: " .. header) - - if header == "A" then - local countOfBytesForArraySize = string.byte(file:read(1)) - alphaSize = string.byte(file:read(countOfBytesForArraySize)) - alpha = string.byte(file:read(1)) - -- print("Количество байт под размер массива символов: " .. countOfBytesForArraySize) - -- print("Размер массива символов: " .. alphaSize) - -- print("Альфа: " .. alpha) - - elseif header == "S" then - if decompressColors then - symbolSize = string.byte(file:read(1)) - else - symbolSize = mergeBytesToNumber(string.byte(file:read(3), 1, 3)) - end - symbol = decodeChar(file) - -- print("Размер массива цвета текста: " .. symbolSize) - -- print("Символ: \"" .. symbol .. "\"") - - elseif header == "F" then - if decompressColors then - foregroundSize = string.byte(file:read(1)) - foreground = colorlib.convert8BitTo24Bit(string.byte(file:read(1))) - else - foregroundSize = mergeBytesToNumber(string.byte(file:read(3), 1, 3)) - foreground = mergeBytesToNumber(string.byte(file:read(3), 1, 3)) - end - -- print("Размер массива цвета фона: " .. foregroundSize) - -- print("Цвет текста: " .. foreground) - - elseif header == "B" then - backgroundSize = mergeBytesToNumber(string.byte(file:read(2), 1, 2)) - if decompressColors then - background = colorlib.convert8BitTo24Bit(string.byte(file:read(1))) - else - background = mergeBytesToNumber(string.byte(file:read(3), 1, 3)) - end - -- print("Размер массива координат: " .. backgroundSize) - -- print("Цвет фона: " .. background) - - --Читаем координаты - for i = 1, backgroundSize, 2 do - local x = string.byte(file:read(1)) - local y = string.byte(file:read(1)) - local index = convertCoordsToIndex(x, y, readedWidth) - -- print("Координата: " .. x .. "x" .. y .. ", индекс: "..index) - - picture[index] = background - picture[index + 1] = foreground - picture[index + 2] = alpha - picture[index + 3] = symbol - end - else - error("Ошибка чтения формата OCIF: неизвестный тип заголовка (" .. header .. ")") - end - - end - - file:close() - - return picture -end - ------------------------------- Все, что касается формата RAW ------------------------------------------------------------ - ---Сохранение в файл сырого формата изображения типа 2 (подробнее о типах см. конец файла) -local function saveRaw(file, picture) - - file:write("\n") - - local xPos, yPos = 1, 1 - for i = 1, picture.width * picture.height * constants.elementCount, constants.elementCount do - file:write( HEXtoSTRING(picture[i], 6), " ", HEXtoSTRING(picture[i + 1], 6), " ", HEXtoSTRING(picture[i + 2], 2), " ", picture[i + 3], " ") - - xPos = xPos + 1 - if xPos > picture.width then - xPos = 1 - yPos = yPos + 1 - file:write("\n") - end - end - - file:close() -end - ---Загрузка из файла сырого формата изображения типа 2 (подробнее о типах см. конец файла) -local function loadRaw(file) - --Читаем один байт "прост так" - file:read(1) - - local picture = {} - local background, foreground, alpha, symbol, sLine - local lineCounter = 0 - - for line in file:lines() do - sLine = unicode.len(line) - for i = 1, sLine, constants.rawImageLoadStep do - background = "0x" .. unicode.sub(line, i, i + 5) - foreground = "0x" .. unicode.sub(line, i + 7, i + 12) - alpha = "0x" .. unicode.sub(line, i + 14, i + 15) - symbol = unicode.sub(line, i + 17, i + 17) - - table.insert(picture, tonumber(background)) - table.insert(picture, tonumber(foreground)) - table.insert(picture, tonumber(alpha)) - table.insert(picture, symbol) - end - lineCounter = lineCounter + 1 - end - - picture.width = sLine / constants.rawImageLoadStep - picture.height = lineCounter - - file:close() - return picture -end - ------------------------------------ Все, что касается реального PNG-формата ------------------------------------------------------------ - -function image.loadPng(path) - if not _G.libPNGImage then _G.libPNGImage = require("libPNGImage") end - - local success, pngImageOrErrorMessage = pcall(libPNGImage.newFromFile, path) - - if not success then - io.stderr:write(" * PNGView: PNG Loading Error *\n") - io.stderr:write("While attempting to load '" .. path .. "' as PNG, libPNGImage erred:\n") - io.stderr:write(pngImageOrErrorMessage) - return - end - - local picture = {} - picture.width, picture.height = pngImageOrErrorMessage:getSize() - - local r, g, b, a, hex - for j = 0, picture.height - 1 do - for i = 0, picture.width - 1 do - r, g, b, a = pngImageOrErrorMessage:getPixel(i, j) - - if r and g and b and a and a > 0 then - hex = colorlib.RGBtoHEX(r, g, b) - table.insert(picture, hex) - table.insert(picture, 0x000000) - table.insert(picture, 0x00) - table.insert(picture, " ") - end - - end - end - - return picture -end - ------------------------------------ Вспомогательные функции программы ------------------------------------------------------------ - ---Оптимизировать и сгруппировать по цветам картинку типа 2 (подробнее о типах см. конец файла) -function image.convertToGroupedImage(picture) - --Создаем массив оптимизированной картинки - local optimizedPicture = {} - --Задаем константы - local xPos, yPos, background, foreground, alpha, symbol = 1, 1, nil, nil, nil, nil - --Перебираем все элементы массива - for i = 1, picture.width * picture.height * constants.elementCount, constants.elementCount do - --Получаем символ из неоптимизированного массива - background, foreground, alpha, symbol = picture[i], picture[i + 1], picture[i + 2], picture[i + 3] - --Группируем картинку по цветам - optimizedPicture[alpha] = optimizedPicture[alpha] or {} - optimizedPicture[alpha][symbol] = optimizedPicture[alpha][symbol] or {} - optimizedPicture[alpha][symbol][foreground] = optimizedPicture[alpha][symbol][foreground] or {} - optimizedPicture[alpha][symbol][foreground][background] = optimizedPicture[alpha][symbol][foreground][background] or {} - - table.insert(optimizedPicture[alpha][symbol][foreground][background], xPos) - table.insert(optimizedPicture[alpha][symbol][foreground][background], yPos) - --Если xPos достигает width изображения, то сбросить на 1, иначе xPos++ - xPos = (xPos == picture.width) and 1 or xPos + 1 - --Если xPos равняется 1, то yPos++, а если нет, то похуй - yPos = (xPos == 1) and yPos + 1 or yPos - end - --Возвращаем оптимизированный массив - return optimizedPicture -end - ---Нарисовать по указанным координатам картинку указанной ширины и высоты для теста -function image.createImage(width, height, random) - local picture = {} - local symbolArray = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "Й", "К", "Л", "И", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "Ь", "Э", "Ю", "Я"} - picture.width = width - picture.height = height - local background, foreground, symbol - for j = 1, height do - for i = 1, width do - if random then - background = math.random(0x000000, 0xffffff) - foreground = math.random(0x000000, 0xffffff) - symbol = symbolArray[math.random(1, #symbolArray)] - else - background = 0x880000 - foreground = 0xffffff - symbol = "Q" - end - - table.insert(picture, background) - table.insert(picture, foreground) - table.insert(picture, 0x00) - table.insert(picture, symbol) - end - end - -- image.draw(x, y, picture) - return picture -end - --- Функция оптимизации цвета текста у картинки, уменьшает число GPU-операций при отрисовке --- Вызывается только при сохранении файла, так что на быстродействии не сказывается, --- а в целом штука очень и очень полезная. Фиксит криворукость художников. -function image.optimize(picture, showOptimizationProcess) - local currentForeground = 0x000000 - local optimizationCounter = 0 - for i = 1, #picture, constants.elementCount do - if picture[i + 3] == " " and picture[i + 1] ~= currentForeground then - picture[i + 1] = currentForeground - if showOptimizationProcess then picture[i + 3] = "#" end - optimizationCounter = optimizationCounter + 1 - else - currentForeground = picture[i + 1] - end - end - if showOptimizationProcess then ecs.error("Count of optimized pixels: " .. optimizationCounter) end - return picture -end - ------------------------------------------- Функция снятия скриншота с экрана ------------------------------------------------ - ---Сделать скриншот экрана и сохранить его по указанному пути -function image.screenshot(path) - local picture = {} - local foreground, background, symbol - picture.width, picture.height = gpu.getResolution() - - for j = 1, picture.height do - for i = 1, picture.width do - symbol, foreground, background = gpu.get(i, j) - table.insert(picture, background) - table.insert(picture, foreground) - table.insert(picture, 0x00) - table.insert(picture, symbol) - end - end - - image.save(path, picture) -end - ------------------------------------------- Функции обработки изображения ------------------------------------------------ - -function image.expand(picture, mode, countOfPixels, background, foreground, alpha, symbol) - background = background or 0xffffff - foreground = foreground or 0x000000 - alpha = alpha or 0x00 - symbol = symbol or " " - if mode == "fromRight" then - for j = 1, countOfPixels do - for i = 1, picture.height do - local index = convertCoordsToIndex(picture.width + j, i, picture.width + j) - table.insert(picture, index, symbol); table.insert(picture, index, alpha); table.insert(picture, index, foreground); table.insert(picture, index, background) - end - end - picture.width = picture.width + countOfPixels - elseif mode == "fromLeft" then - for j = 1, countOfPixels do - for i = 1, picture.height do - local index = convertCoordsToIndex(1, i, picture.width + j) - table.insert(picture, index, symbol); table.insert(picture, index, alpha); table.insert(picture, index, foreground); table.insert(picture, index, background) - end - end - picture.width = picture.width + countOfPixels - elseif mode == "fromTop" then - for i = 1, (countOfPixels * picture.width) do - table.insert(picture, 1, symbol); table.insert(picture, 1, alpha); table.insert(picture, 1, foreground); table.insert(picture, 1, background) - end - picture.height = picture.height + countOfPixels - elseif mode == "fromBottom" then - for i = 1, (countOfPixels * picture.width) do - table.insert(picture, background); table.insert(picture, foreground); table.insert(picture, alpha); table.insert(picture, symbol) - end - picture.height = picture.height + countOfPixels - else - error("Wrong image expanding mode: only 'fromRight', 'fromLeft', 'fromTop' and 'fromBottom' are supported.") - end - return picture -end - -function image.crop(picture, mode, countOfPixels) - if mode == "fromRight" then - for j = 1, countOfPixels do - for i = 1, picture.height do - local index = convertCoordsToIndex(picture.width + 1 - j, i, picture.width - j) - for a = 1, constants.elementCount do table.remove(picture, index) end - end - end - picture.width = picture.width - countOfPixels - elseif mode == "fromLeft" then - for j = 1, countOfPixels do - for i = 1, picture.height do - local index = convertCoordsToIndex(1, i, picture.width - j) - for a = 1, constants.elementCount do table.remove(picture, index) end - end - end - picture.width = picture.width - countOfPixels - elseif mode == "fromTop" then - for i = 1, (countOfPixels * constants.elementCount * picture.width) do table.remove(picture, 1) end - picture.height = picture.height - countOfPixels - elseif mode == "fromBottom" then - for i = 1, (countOfPixels * constants.elementCount * picture.width) do table.remove(picture, #picture) end - picture.height = picture.height - countOfPixels - else - error("Wrong image cropping mode: only 'fromRight', 'fromLeft', 'fromTop' and 'fromBottom' are supported.") - end - return picture -end - -function image.flipVertical(picture) - local newPicture = {}; newPicture.width = picture.width; newPicture.height = picture.height - for j = picture.height, 1, -1 do - for i = 1, picture.width do - local index = convertCoordsToIndex(i, j, picture.width) - table.insert(newPicture, picture[index]); table.insert(newPicture, picture[index + 1]); table.insert(newPicture, picture[index + 2]); table.insert(newPicture, picture[index + 3]) - picture[index], picture[index + 1], picture[index + 2], picture[index + 3] = nil, nil, nil, nil - end - end - return newPicture -end - -function image.flipHorizontal(picture) - local newPicture = {}; newPicture.width = picture.width; newPicture.height = picture.height - for j = 1, picture.height do - for i = picture.width, 1, -1 do - local index = convertCoordsToIndex(i, j, picture.width) - table.insert(newPicture, picture[index]); table.insert(newPicture, picture[index + 1]); table.insert(newPicture, picture[index + 2]); table.insert(newPicture, picture[index + 3]) - picture[index], picture[index + 1], picture[index + 2], picture[index + 3] = nil, nil, nil, nil - end - end - return newPicture -end - -function image.rotate(picture, angle) - local function rotateBy90(picture) - local newPicture = {}; newPicture.width = picture.height; newPicture.height = picture.width - for i = 1, picture.width do - for j = picture.height, 1, -1 do - local index = convertCoordsToIndex(i, j, picture.width) - table.insert(newPicture, picture[index]); table.insert(newPicture, picture[index + 1]); table.insert(newPicture, picture[index + 2]); table.insert(newPicture, picture[index + 3]) - picture[index], picture[index + 1], picture[index + 2], picture[index + 3] = nil, nil, nil, nil - end - end - return newPicture - end - - local function rotateBy180(picture) - local newPicture = {}; newPicture.width = picture.width; newPicture.height = picture.height - for j = picture.height, 1, -1 do - for i = picture.width, 1, -1 do - local index = convertCoordsToIndex(i, j, picture.width) - table.insert(newPicture, picture[index]); table.insert(newPicture, picture[index + 1]); table.insert(newPicture, picture[index + 2]); table.insert(newPicture, picture[index + 3]) - picture[index], picture[index + 1], picture[index + 2], picture[index + 3] = nil, nil, nil, nil - end - end - return newPicture - end - - local function rotateBy270(picture) - local newPicture = {}; newPicture.width = picture.height; newPicture.height = picture.width - for i = picture.width, 1, -1 do - for j = 1, picture.height do - local index = convertCoordsToIndex(i, j, picture.width) - table.insert(newPicture, picture[index]); table.insert(newPicture, picture[index + 1]); table.insert(newPicture, picture[index + 2]); table.insert(newPicture, picture[index + 3]) - picture[index], picture[index + 1], picture[index + 2], picture[index + 3] = nil, nil, nil, nil - end - end - return newPicture - end - - if angle == 90 then - return rotateBy90(picture) - elseif angle == 180 then - return rotateBy180(picture) - elseif angle == 270 then - return rotateBy270(picture) - else - error("Can't rotate image: angle must be 90, 180 or 270 degrees.") - end -end - ------------------------------------------- Функции для работы с цветом ----------------------------------------------- - -function image.hueSaturationBrightness(picture, hue, saturation, brightness) - local function calculateBrightnessChanges(color) - local h, s, b = colorlib.HEXtoHSB(color) - b = b + brightness; if b < 0 then b = 0 elseif b > 100 then b = 100 end - s = s + saturation; if s < 0 then s = 0 elseif s > 100 then s = 100 end - h = h + hue; if h < 0 then h = 0 elseif h > 360 then h = 360 end - return colorlib.HSBtoHEX(h, s, b) - end - - for i = 1, #picture, 4 do - picture[i] = calculateBrightnessChanges(picture[i]) - picture[i + 1] = calculateBrightnessChanges(picture[i + 1]) - end - - return picture -end - -function image.hue(picture, hue) - return image.hueSaturationBrightness(picture, hue, 0, 0) -end - -function image.saturation(picture, saturation) - return image.hueSaturationBrightness(picture, 0, saturation, 0) -end - -function image.brightness(picture, brightness) - return image.hueSaturationBrightness(picture, 0, 0, brightness) -end - -function image.blackAndWhite(picture) - return image.hueSaturationBrightness(picture, 0, -100, 0) -end - -function image.colorBalance(picture, r, g, b) - local function calculateRGBChanges(color) - local rr, gg, bb = colorlib.HEXtoRGB(color) - rr = rr + r; gg = gg + g; bb = bb + b - if rr < 0 then rr = 0 elseif rr > 255 then rr = 255 end - if gg < 0 then gg = 0 elseif gg > 255 then gg = 255 end - if bb < 0 then bb = 0 elseif bb > 255 then bb = 255 end - return colorlib.RGBtoHEX(rr, gg, bb) - end - - for i = 1, #picture, 4 do - picture[i] = calculateRGBChanges(picture[i]) - picture[i + 1] = calculateRGBChanges(picture[i + 1]) - end - - return picture -end - -function image.invert(picture) - for i = 1, #picture, 4 do - picture[i] = 0xffffff - picture[i] - picture[i + 1] = 0xffffff - picture[i + 1] - end - return picture -end - -function image.photoFilter(picture, color, transparency) - if transparency < 0 then transparency = 0 elseif transparency > 255 then transparency = 255 end - for i = 1, #picture, 4 do - picture[i] = colorlib.alphaBlend(picture[i], color, transparency) - picture[i + 1] = colorlib.alphaBlend(picture[i + 1], color, transparency) - end - return picture -end - -function image.replaceColor(picture, fromColor, toColor) - for i = 1, #picture, 4 do - if picture[i] == fromColor then picture[i] = toColor end - end - return picture -end - ------------------------------------------ Основные функции программы ------------------------------------------------------------------- - ---Сохранить изображение любого поддерживаемого формата -function image.save(path, picture, encodingMethod) - encodingMethod = encodingMethod or 3 - --Создать папку под файл, если ее нет - fs.makeDirectory(fs.path(path)) - --Получаем формат указанного файла - local fileFormat = getFileFormat(path) - --Оптимизируем картинку - picture = image.optimize(picture) - --Открываем файл - local file = io.open(path, "w") - --Записываем сигнатуру - writeSignature(file) - --Проверяем соответствие формата файла - if fileFormat == constants.compressedFileFormat then - if encodingMethod == 0 or string.lower(encodingMethod) == "raw" then - file:write(string.char(encodingMethod)) - saveRaw(file, picture) - elseif encodingMethod == 1 or string.lower(encodingMethod) == "ocif1" then - file:write(string.char(encodingMethod)) - saveOCIF1(file, picture) - elseif encodingMethod == 2 or string.lower(encodingMethod) == "ocif2" then - file:write(string.char(encodingMethod)) - saveOCIF2(file, picture) - elseif encodingMethod == 3 or string.lower(encodingMethod) == "ocif3" then - file:write(string.char(encodingMethod)) - picture = compressImageColorsTo8Bit(picture) - saveOCIF2(file, picture, true) - else - file:close() - error("Unsupported encoding method.\n") - end - else - file:close() - error("Unsupported file format.\n") - end -end - ---Загрузить изображение любого поддерживаемого формата -function image.load(path) - --Кинуть ошибку, если такого файла не существует - if not fs.exists(path) then error("File \""..path.."\" does not exists.\n") end - --Получаем формат указанного файла - local fileFormat = getFileFormat(path) - --Проверяем соответствие формата файла - if fileFormat == constants.compressedFileFormat then - local file = io.open(path, "rb") - --Читаем сигнатуру файла - readSignature(file) - --Читаем метод обработки изображения - local encodingMethod = string.byte(file:read(1)) - --Читаем файлы в зависимости от метода - --print("Загружаю файл типа " .. encodingMethod) - if encodingMethod == 0 then - return loadRaw(file) - elseif encodingMethod == 1 then - return loadOCIF1(file) - elseif encodingMethod == 2 then - return loadOCIF2(file) - elseif encodingMethod == 3 then - return loadOCIF2(file, true) - else - file:close() - error("Unsupported encoding method.\n") - end - else - file:close() - error("Unsupported file format.\n") - end -end - ---Отрисовка изображения типа 3 (подробнее о типах см. конец файла) -function image.draw(x, y, picture) - --Конвертируем в групповое изображение - picture = image.convertToGroupedImage(picture) - --Все как обычно - x, y = x - 1, y - 1 - - local xPos, yPos, currentBackground - for alpha in pairs(picture) do - for symbol in pairs(picture[alpha]) do - for foreground in pairs(picture[alpha][symbol]) do - if gpu.getForeground ~= foreground then gpu.setForeground(foreground) end - for background in pairs(picture[alpha][symbol][foreground]) do - if gpu.getBackground ~= background then gpu.setBackground(background) end - currentBackground = background - for i = 1, #picture[alpha][symbol][foreground][background], 2 do - xPos, yPos = x + picture[alpha][symbol][foreground][background][i], y + picture[alpha][symbol][foreground][background][i + 1] - - --Если альфа имеется, но она не совсем прозрачна - if (alpha > 0x00 and alpha < 0xFF) or (alpha == 0xFF and symbol ~= " ")then - _, _, currentBackground = gpu.get(xPos, yPos) - currentBackground = colorlib.alphaBlend(currentBackground, background, alpha) - gpu.setBackground(currentBackground) - - gpu.set(xPos, yPos, symbol) - - elseif alpha == 0x00 then - if currentBackground ~= background then - currentBackground = background - gpu.setBackground(currentBackground) - end - - gpu.set(xPos, yPos, symbol) - end - --ecs.wait() - end - end - end - end - end -end - -local function createSaveAndLoadFiles() - ecs.prepareToExit() - ecs.error("Создаю/загружаю изображение") - local cyka = image.load("MineOS/System/OS/Icons/Love.pic") - --local cyka = image.createImage(4, 4) - ecs.error("Рисую загруженное изображение") - image.draw(2, 2, cyka) - ecs.error("Сохраняю его в 4 форматах") - image.save("0.pic", cyka, 0) - image.save("1.pic", cyka, 1) - image.save("2.pic", cyka, 2) - image.save("3.pic", cyka, 3) - ecs.prepareToExit() - ecs.error("Загружаю все 4 формата и рисую их") - local cyka0 = image.load("0.pic") - image.draw(2, 2, cyka0) - local cyka1 = image.load("1.pic") - image.draw(10, 2, cyka1) - local cyka2 = image.load("2.pic") - image.draw(18, 2, cyka2) - local cyka3 = image.load("3.pic") - image.draw(26, 2, cyka3) - ecs.error("Рисую все 3 формата") -end - ------------------------------------------- Место для баловства ------------------------------------------------ - --- ecs.prepareToExit() - --- local cyka = image.load("MineOS/Applications/Piano.app/Resources/Icon.pic") --- image.draw(2, 2, cyka) --- ecs.error(HEXtoSTRING(cyka[1], 6, true)) --- image.draw(8, 2, cyka) --- createSaveAndLoadFiles() - ------------------------------------------------------------------------------------------------------------------------- - -return image - - - - - - - - - - - diff --git a/Beta/MineCode2/m.lua b/Beta/MineCode2/m.lua deleted file mode 100644 index c7b49313..00000000 --- a/Beta/MineCode2/m.lua +++ /dev/null @@ -1,242 +0,0 @@ - -package.loaded.syntax = nil -package.loaded.filemanager = nil - -local fs = require("filesystem") -local syntax = require("syntax") -local ecs = require("ECSAPI") -local term = require("term") -local buffer = require("doubleBuffering") -local unicode = require("unicode") -local context = require("context") -local event = require("event") -local component = require("component") -local filemanager = require("filemanager") -local gpu = component.gpu - -local pathToFile = "OS.lua" -local fileSize = 0 -local indentationWidth = 4 - -local strings -local fromString = 1 -local fromSymbol = 1 -local scrollSpeed = 5 -local showLuaSyntax = true - -local xCursor, yCursor = 1, 1 -local textFieldPosition - -local selection = { - from = {x = 18, y = 6}, - to = {x = 4, y = 8} -} - -local highlightedStrings = { - {number = 31, color = 0xFF4444}, - {number = 32, color = 0xFF4444}, - {number = 34, color = 0x66FF66}, -} - -local constants = { - colors = { - infoPanel = 0xCCCCCC, - infoPanelText = 0x262626, - topBar = 0xDDDDDD, - topBarButton = 0xCCCCCC, - topBarButtonText = 0x262626, - topMenu = 0xFFFFFF, - topMenuText = 0x262626, - }, - buttons = { - launch = "‣", - toggleSyntax = "*" - }, - sizes = { - xCode = 31, - yCode = 5, - widthOfManager = 30, - } -} - ---------------------------------------------------------------------------- - ---Объекты для тача -local obj = {} -local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} -end - -local function readFile(path) - local massivStrok = {} - if fs.exists(path) then - fileSize = math.floor(fs.size(path) / 1024) - local file = io.open(path, "r") - for line in file:lines() do - line = string.gsub(line, " ", string.rep(" ", indentationWidth)) - table.insert(massivStrok, line) - end - file:close() - else - ecs.error("Файл не существует!") - end - - return massivStrok -end - -local function drawInfoPanel() - local width = math.floor(buffer.screen.width * 0.3) - local x, y = math.floor(buffer.screen.width / 2 - width / 2), 2 - - buffer.square(x, y, width, 3, constants.colors.infoPanel, 0x000000, " ") - - local textArray = { - "Файл: " .. pathToFile, - "Размер: " .. fileSize .. " KB", - "Позиция курсора: " .. xCursor .. "x" .. yCursor, - } - - for i = 1, #textArray do - textArray[i] = ecs.stringLimit("end", textArray[i], width) - x = math.floor(buffer.screen.width / 2 - unicode.len(textArray[i]) / 2) - - buffer.text(x, y, constants.colors.infoPanelText, textArray[i]) - - y = y + 1 - end -end - -local function drawTopBar() - obj["TopBarButtons"] = {} - - local x, y = 1, 2 - local buttonWidth = 7 - buffer.square(x, y, buffer.screen.width, 3, constants.colors.topBar, 0x000000, " ") - - local buttonNames = { - constants.buttons.launch, - constants.buttons.toggleSyntax, - } - - for i = 1, #buttonNames do - newObj("TopBarButtons", buttonNames[i], buffer.button(x, y, buttonWidth, 3, constants.colors.topBarButton, constants.colors.topBarButtonText, buttonNames[i])) - x = x + buttonWidth + 1 - end -end - -local function drawTopMenu() - local x, y = 1, 1 - - buffer.square(x, y, buffer.screen.width, 1, constants.colors.topMenu, 0x000000, " ") - - local buttonNames = { - "Файл", - "Правка", - "Вид", - "О программе" - } - - for i = 1, #buttonNames do - local length = unicode.len(buttonNames[i]) + 2 - buffer.button(x, y, length, 1, constants.colors.topMenu, constants.colors.topMenuText, buttonNames[i]) - x = x + length - end -end - -local function drawCode() - textFieldPosition = syntax.viewCode(constants.sizes.xCode, constants.sizes.yCode, buffer.screen.width - constants.sizes.xCode + 1, buffer.screen.height - 4, strings, fromSymbol, fromString, showLuaSyntax, selection, highlightedStrings) -end - -local function launch() - local callback, reason = loadfile(pathToFile) - if callback then - ecs.prepareToExit() - local success, reason = pcall(callback) - if success then - ecs.prepareToExit() - print("Программа успешно выполнена!") - else - ecs.error("Ошибка при выполнении программы: " .. reason) - end - else - ecs.error("Ошибка при запуске программы: " .. reason) - end -end - --- local function convertCoordsToCursor(x, y) - --- end - -local function drawFileManager() - filemanager.draw(1, constants.sizes.yCode, constants.sizes.widthOfManager, buffer.screen.height - 4, fs.path(pathToFile), 1) -end - -local function drawAll() - drawTopBar() - drawInfoPanel() - drawTopMenu() - drawFileManager() - drawCode() -end - ---------------------------------------------------------------------------- - -buffer.square(1, 1, buffer.screen.width, buffer.screen.height, ecs.colors.red, 0xFFFFFF, " ") -buffer.draw(true) - -strings = readFile(pathToFile) - -drawAll() - ---------------------------------------------------------------------------- - -while true do - local e = { event.pull() } - if e[1] == "touch" then - for key in pairs(obj.TopBarButtons) do - if ecs.clickedAtArea(e[3], e[4], obj.TopBarButtons[key][1], obj.TopBarButtons[key][2], obj.TopBarButtons[key][3], obj.TopBarButtons[key][4]) then - buffer.button(obj.TopBarButtons[key][1], obj.TopBarButtons[key][2], 7, 3, ecs.colors.blue, ecs.colors.white, key) - buffer.draw() - os.sleep(0.2) - buffer.button(obj.TopBarButtons[key][1], obj.TopBarButtons[key][2], 7, 3, constants.colors.topBarButton, constants.colors.topBarButtonText, key) - buffer.draw() - - if key == constants.buttons.launch then - launch() - drawAll() - elseif key == constants.buttons.toggleSyntax then - showLuaSyntax = not showLuaSyntax - drawAll() - end - - break - end - end - elseif e[1] == "scroll" then - if e[5] == 1 then - if fromString > scrollSpeed then - fromString = fromString - scrollSpeed - drawInfoPanel() - drawCode() - end - else - if fromString < (#strings - scrollSpeed) then - fromString = fromString + scrollSpeed - drawInfoPanel() - drawCode() - end - end - end -end - - - - - - - - - - - diff --git a/Beta/MineCode2/syntax.lua b/Beta/MineCode2/syntax.lua deleted file mode 100644 index 4b95458d..00000000 --- a/Beta/MineCode2/syntax.lua +++ /dev/null @@ -1,318 +0,0 @@ -local gpu = require("component").gpu -local buffer = require("doubleBuffering") -local unicode = require("unicode") -local syntax = {} - ----------------------------------------------------------------------------------------------------------------------------------------- - ---Стандартные цветовые схемы -syntax.colorSchemes = { - midnight = { - background = 0x262626, - text = 0xffffff, - strings = 0xff2024, - loops = 0xffff98, - comments = 0xa2ffb7, - boolean = 0xffcc66, - logic = 0xffcc66, - numbers = 0x24c0ff, - functions = 0xffcc66, - compares = 0xffff98, - lineNumbers = 0x444444, - lineNumbersText = 0xDDDDDD, - scrollBar = 0x444444, - scrollBarPipe = 0x24c0ff, - selection = 0x99B2F2, - }, - sunrise = { - background = 0xffffff, - text = 0x262626, - strings = 0x880000, - loops = 0x24c0ff, - comments = 0xa2ffb7, - boolean = 0x19c0cc, - logic = 0x880000, - numbers = 0x24c0ff, - functions = 0x24c0ff, - compares = 0x880000, - lineNumbers = 0x444444, - lineNumbersText = 0xDDDDDD, - scrollBar = 0x444444, - scrollBarPipe = 0x24c0ff, - selection = 0x99B2F2, - }, -} - ---Текущая цветовая схема -local currentColorScheme = {} ---Шаблоны поиска -local patterns - ----------------------------------------------------------------------------------------------------------------------------------------- - ---Пересчитать цвета шаблонов ---Приоритет поиска шаблонов снижается сверху вниз -local function definePatterns() - patterns = { - --Комментарии - { pattern = "%-%-.*", color = currentColorScheme.comments, cutFromLeft = 0, cutFromRight = 0 }, - - --Строки - { pattern = "\"[^\"\"]*\"", color = currentColorScheme.strings, cutFromLeft = 0, cutFromRight = 0 }, - - --Циклы, условия, объявления - { pattern = "while ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "do$", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "do ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "end$", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "end ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "for ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = " in ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "repeat ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "if ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "then", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "until ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "return", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "local ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "function ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "else$", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "else ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = "elseif ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 }, - - --Состояния переменной - { pattern = "true", color = currentColorScheme.boolean, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "false", color = currentColorScheme.boolean, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "nil", color = currentColorScheme.boolean, cutFromLeft = 0, cutFromRight = 0 }, - - --Функции - { pattern = "%s([%a%d%_%-%.]*)%(", color = currentColorScheme.functions, cutFromLeft = 0, cutFromRight = 1 }, - - --And, or, not, break - { pattern = " and ", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = " or ", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = " not ", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 1 }, - { pattern = " break$", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "^break", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = " break ", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 0 }, - - --Сравнения и мат. операции - { pattern = "<=", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = ">=", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "<", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = ">", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "==", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "~=", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "=", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "%+", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "%-", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "%*", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "%/", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "%.%.", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "%#", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "#^", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 }, - - --Числа - { pattern = "%s(0x)(%w*)", color = currentColorScheme.numbers, cutFromLeft = 0, cutFromRight = 0 }, - { pattern = "(%s)([%d%.]*)", color = currentColorScheme.numbers, cutFromLeft = 0, cutFromRight = 0 }, - } -end - ---Костыльная замена обычному string.find() ---Работает медленнее, но хотя бы поддерживает юникод -function unicode.find(str, pattern, init, plain) - -- checkArg(1, str, "string") - -- checkArg(2, pattern, "string") - -- checkArg(3, init, "number", "nil") - - if init then - if init < 0 then - init = -#unicode.sub(str,init) - elseif init > 0 then - init = #unicode.sub(str, 1, init - 1) + 1 - end - end - - a, b = string.find(str, pattern, init, plain) - - if a then - local ap, bp = str:sub(1, a - 1), str:sub(a,b) - a = unicode.len(ap) + 1 - b = a + unicode.len(bp) - 1 - return a, b - else - return a - end -end - ---Объявить новую цветовую схему -function syntax.setColorScheme(colorScheme) - --Выбранная цветовая схема - currentColorScheme = colorScheme - --Пересчитываем шаблоны - definePatterns() -end - ----------------------------------------------------------------------------------------------------------------------------------------- - ---Проанализировать строку и создать на ее основе цветовую карту -function syntax.highlight(x, y, text, fromSymbol, limit) - --Кароч вооот, хыыы - local searchFrom, starting, ending - --Загоняем в буфер всю строку базового цвета - buffer.text(x - fromSymbol + 1, y, currentColorScheme.text, text) - --Перебираем шаблоны - for i = #patterns, 1, -1 do - searchFrom = 1 - --Перебираем весь текст, а то мало ли шаблон дохуя раз встречается - while true do - starting, ending = unicode.find(text, patterns[i].pattern, searchFrom) - if starting and ending then - buffer.text(x + starting - fromSymbol, y, patterns[i].color, unicode.sub(text, starting, ending - patterns[i].cutFromRight)) - if ending > limit then break end - searchFrom = ending + 1 - else - break - end - end - end -end - -function syntax.convertFileToStrings(path) - local array = {} - local file = io.open(path, "r") - for line in file:lines() do - line = string.gsub(line, " ", string.rep(" ", 4)) - table.insert(array, line) - end - file:close() - return array -end - --- Открыть окно-просмотрщик кода -function syntax.viewCode(x, y, width, height, strings, fromSymbol, fromString, highlightLuaSyntax, selection, highlightedStrings) - --Рассчитываем максимальное количество строк, которое мы будем отображать - local maximumNumberOfAvailableStrings, yPos - if strings[fromString + height - 1] then - maximumNumberOfAvailableStrings = fromString + height - 1 - else - maximumNumberOfAvailableStrings = #strings - end - --Рассчитываем ширину полоски с номерами строк - local widthOfStringCounter = unicode.len(maximumNumberOfAvailableStrings) + 2 - --Рассчитываем стратовую позицию текстового поля - local textFieldPosition = x + widthOfStringCounter - local widthOfText = width - widthOfStringCounter - 3 - - --Рисуем подложку под текст - buffer.square(textFieldPosition, y, width - widthOfStringCounter - 1, height, currentColorScheme.background, 0xFFFFFF, " ") - --Рисуем скроллбар - buffer.scrollBar(x + width - 1, y, 1, height, #strings, fromString, currentColorScheme.scrollBar, currentColorScheme.scrollBarPipe) - --Рисуем номера строк - buffer.square(x, y, widthOfStringCounter, height, currentColorScheme.lineNumbers, 0xFFFFFF, " ") - - --Подсвечиваем некоторые строки, если указано - if highlightedStrings then - for i = 1, #highlightedStrings do - if highlightedStrings[i].number >= fromString and highlightedStrings[i].number < fromString + height then - buffer.square(x, y + highlightedStrings[i].number - fromString, width - 1, 1, highlightedStrings[i].color, 0xFFFFFF, " ") - buffer.square(x, y + highlightedStrings[i].number - fromString, widthOfStringCounter, 1, currentColorScheme.lineNumbers, 0xFFFFFF, " ", 60) - end - end - end - - yPos = y - for i = fromString, maximumNumberOfAvailableStrings do - buffer.text(x + widthOfStringCounter - unicode.len(i) - 1, yPos, currentColorScheme.text, tostring(i)) - yPos = yPos + 1 - end - - --Рисуем выделение, если оно имеется - if selection then - --Считаем высоту выделения - local heightOfSelection = selection.to.y - selection.from.y + 1 - --Если высота выделения > 1 - if heightOfSelection > 1 then - --Верхнее выделение - if selection.from.x < fromSymbol + widthOfText and selection.from.y >= fromString and selection.from.y < fromString + height then - local cyka = textFieldPosition + selection.from.x - fromSymbol - if cyka < textFieldPosition then - cyka = textFieldPosition - end - buffer.square(cyka, y + selection.from.y - fromString, widthOfText - cyka + widthOfStringCounter + 2 + x, 1, currentColorScheme.selection, 0xFFFFFF, " ") - end - --Средние выделения - if heightOfSelection > 2 then - for i = 1, heightOfSelection - 2 do - if selection.from.y + i >= fromString and selection.from.y + i < fromString + height then - buffer.square(textFieldPosition, y + selection.from.y + i - fromString, widthOfText + 2, 1, currentColorScheme.selection, 0xFFFFFF, " ") - end - end - end - --Нижнее выделение - if selection.to.x >= fromSymbol and selection.to.y >= fromString and selection.to.y < fromString + height then - buffer.square(textFieldPosition, y + selection.to.y - fromString, selection.to.x - fromSymbol + 1, 1, currentColorScheme.selection, 0xFFFFFF, " ") - end - elseif heightOfSelection == 1 then - local cyka = selection.to.x - if cyka > fromSymbol + widthOfText - 1 then cyka = fromSymbol + widthOfText - 1 end - buffer.square(textFieldPosition + selection.from.x, selection.from.y, cyka - selection.from.x, 1, currentColorScheme.selection, 0xFFFFFF, " ") - end - end - - --Выставляем ограничение прорисовки буфера - textFieldPosition = textFieldPosition + 1 - buffer.setDrawLimit(textFieldPosition, y, widthOfText, height) - - --Рисуем текст - yPos = y - for i = fromString, maximumNumberOfAvailableStrings do - --Учитываем опциональную подсветку ситнаксиса - if highlightLuaSyntax then - syntax.highlight(textFieldPosition, yPos, strings[i], fromSymbol, widthOfText) - else - buffer.text(textFieldPosition, yPos, currentColorScheme.text, unicode.sub(strings[i], fromSymbol, widthOfText)) - end - - yPos = yPos + 1 - end - - --Рисуем изменения из буфера - buffer.draw() - --Убираем ограничение отрисовки - buffer.resetDrawLimit() - - return textFieldPosition -end - ----------------------------------------------------------------------------------------------------------------- - --- Стартовое объявление цветовой схемы при загрузке библиотеки -syntax.setColorScheme(syntax.colorSchemes.midnight) - --- -- Епты бля! --- local strings = syntax.convertFileToStrings("MineOS/Applications/Highlight.app/Resources/TestFile.txt") --- local strings = syntax.convertFileToStrings("OS.lua") - --- local xSize, ySize = gpu.getResolution() --- buffer.square(1, 1, xSize, ySize, ecs.colors.red, 0xFFFFFF, " ") --- buffer.draw(true) - --- local selection = { --- from = {x = 8, y = 6}, --- to = {x = 16, y = 12} --- } - --- local highlightedStrings = { --- {number = 31, color = 0xFF4444}, --- {number = 32, color = 0xFF4444}, --- } - --- syntax.viewCode(20, 5, 100, 40, strings, 1, 20, true, selection, highlightedStrings) - ----------------------------------------------------------------------------------------------------------------- - -return syntax - - - - diff --git a/Beta/PS3.lua b/Beta/PS3.lua deleted file mode 100644 index d3817531..00000000 --- a/Beta/PS3.lua +++ /dev/null @@ -1,833 +0,0 @@ - ------------------------------------------------- Копирайт -------------------------------------------------------------- - -local copyright = [[ - - Photoshop v3.0 (закрытая бета) - - Автор: IT - Контакты: https://vk.com/id7799889 - Соавтор: Pornogion - Контакты: https://vk.com/id88323331 - -]] - ------------------------------------------------- Библиотеки -------------------------------------------------------------- - ---Не требующиеся для MineOS ---local ecs = require("ECSAPI") ---local fs = require("filesystem") ---local unicode = require("unicode") ---local context = require("context") - ---Обязательные -local colorlib = require("colorlib") -local palette = require("palette") -local event = require("event") -local image = require("image") -local gpu = component.gpu - ------------------------------------------------- Переменные -------------------------------------------------------------- - ---Массив главного изображения -local masterPixels = { - width = 0, - height = 0, -} - ---Базовая цветовая схема программы -local colors = { - toolbar = 0x535353, - toolbarInfo = 0x3d3d3d, - toolbarButton = 0x3d3d3d, - toolbarButtonText = 0xeeeeee, - drawingArea = 0x262626, - console = 0x3d3d3d, - consoleText = 0x999999, - transparencyWhite = 0xffffff, - transparencyGray = 0xcccccc, - transparencyVariable = 0xffffff, - oldBackground = 0x0, - oldForeground = 0x0, - topMenu = 0xeeeeee, - topMenuText = 0x262626, -} - ---Различные константы и размеры тулбаров и кликабельных зон -local sizes = { - widthOfLeftBar = 6, -} -sizes.heightOfTopBar = 3 -sizes.xSize, sizes.ySize = gpu.getResolution() -sizes.xStartOfDrawingArea = sizes.widthOfLeftBar + 1 -sizes.xEndOfDrawingArea = sizes.xSize -sizes.yStartOfDrawingArea = 2 + sizes.heightOfTopBar -sizes.yEndOfDrawingArea = sizes.ySize - 1 -sizes.widthOfDrawingArea = sizes.xEndOfDrawingArea - sizes.xStartOfDrawingArea + 1 -sizes.heightOfDrawingArea = sizes.yEndOfDrawingArea - sizes.yStartOfDrawingArea + 1 -sizes.heightOfLeftBar = sizes.ySize - 1 - ---Для изображения -local function reCalculateImageSizes() - sizes.widthOfImage = masterPixels.width - sizes.heightOfImage = masterPixels.height - sizes.sizeOfPixelData = 4 - sizes.xStartOfImage = 9 - sizes.yStartOfImage = 6 - sizes.xEndOfImage = sizes.xStartOfImage + sizes.widthOfImage - 1 - sizes.yEndOfImage = sizes.yStartOfImage + sizes.heightOfImage - 1 -end -reCalculateImageSizes() - ---Инструменты -sizes.heightOfInstrument = 3 -sizes.yStartOfInstruments = 2 + sizes.heightOfTopBar -local instruments = { - -- {"⮜", "Move"}, - -- {"✄", "Crop"}, - {"✎", "Brush"}, - {"❎", "Eraser"}, - {"⃟", "Fill"}, - {"Ⓣ", "Text"}, -} -local currentInstrument = 1 -local currentBackground = 0x6649ff -local currentForeground = 0x3ff80 -local currentAlpha = 0x00 -local currentSymbol = " " -local currentBrushSize = 1 -local savePath - ---Верхний тулбар -local topToolbar = {{"PS", ecs.colors.blue}, {"Файл"}, {"Изображение"}, {"Инструменты"}, {"О программе"}} - ------------------------------------------------- Функции отрисовки -------------------------------------------------------------- - ---Объекты для тача -local obj = {} -local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} -end - -local function drawTransparentPixel(xPos, yPos, i, j) - if j % 2 == 0 then - if i % 2 == 0 then - colors.transparencyVariable = colors.transparencyWhite - else - colors.transparencyVariable = colors.transparencyGray - end - else - if i % 2 == 0 then - colors.transparencyVariable = colors.transparencyGray - else - colors.transparencyVariable = colors.transparencyWhite - end - end - gpu.setBackground(colors.transparencyVariable) - gpu.set(xPos, yPos, " ") -end - -local function drawBackground() - ecs.square(sizes.xStartOfDrawingArea, sizes.yStartOfDrawingArea, sizes.widthOfDrawingArea, sizes.heightOfDrawingArea, colors.drawingArea) -end - -local function drawInstruments() - local yPos = sizes.yStartOfInstruments - for i = 1, #instruments do - if currentInstrument == i then - ecs.square(1, yPos, sizes.widthOfLeftBar, sizes.heightOfInstrument, colors.toolbarButton) - else - ecs.square(1, yPos, sizes.widthOfLeftBar, sizes.heightOfInstrument, colors.toolbar) - end - ecs.colorText(3, yPos + 1, colors.toolbarButtonText, instruments[i][1]) - - newObj("Instruments", i, 1, yPos, sizes.widthOfLeftBar, yPos + sizes.heightOfInstrument - 1) - - yPos = yPos + sizes.heightOfInstrument - end -end - -local function drawColors() - local xPos, yPos = 2, sizes.ySize - 4 - ecs.square(xPos, yPos, 3, 2, currentBackground) - ecs.square(xPos + 3, yPos + 1, 1, 2, currentForeground) - ecs.square(xPos + 1, yPos + 2, 2, 1, currentForeground) - ecs.colorTextWithBack(xPos + 1, yPos + 3, 0xaaaaaa, colors.toolbar, "←→") - - newObj("Colors", 1, xPos, yPos, xPos + 2, yPos + 1) - newObj("Colors", 2, xPos + 3, yPos + 1, xPos + 3, yPos + 2) - newObj("Colors", 3, xPos + 1, yPos + 2, xPos + 3, yPos + 2) - newObj("Colors", 4, xPos + 1, yPos + 3, xPos + 2, yPos + 3) -end - -local function drawLeftBar() - ecs.square(1, 2, sizes.widthOfLeftBar, sizes.heightOfLeftBar, colors.toolbar) - drawInstruments() - drawColors() -end - -local function drawTopMenu() - ecs.square(1, 1, sizes.xSize, 1, colors.topMenu) - local xPos = 3 - - for i = 1, #topToolbar do - ecs.colorText(xPos, 1, topToolbar[i][2] or colors.topMenuText, topToolbar[i][1]) - - if i > 1 then - newObj("TopMenu", topToolbar[i][1], xPos, 1, xPos + unicode.len(topToolbar[i][1]) - 1, 1) - end - - xPos = xPos + unicode.len(topToolbar[i][1]) + 2 - end -end - -local function drawTopBar() - - local topBarInputs = { {"Размер кисти", currentBrushSize}, {"Прозрачность", math.floor(currentAlpha)}} - - ecs.square(1, 2, sizes.xSize, sizes.heightOfTopBar, colors.toolbar) - local xPos, yPos = 3, 3 - local limit = 8 - - --ecs.error("сукак") - - for i = 1, #topBarInputs do - ecs.colorTextWithBack(xPos, yPos, 0xeeeeee, colors.toolbar, topBarInputs[i][1]) - - xPos = xPos + unicode.len(topBarInputs[i][1]) + 1 - ecs.inputText(xPos, yPos, limit, tostring(topBarInputs[i][2]), 0xffffff, 0x262626, true) - - newObj("TopBarInputs", i, xPos, yPos, xPos + limit - 1, yPos, limit) - - if i == 2 then xPos = xPos + 3 end - - xPos = xPos + limit + 2 - end - -end - -local function createEmptyMasterPixels() - --Очищаем мастерпиксельс и задаем ширину с высотой - masterPixels = {} - masterPixels.width = sizes.widthOfImage - masterPixels.height = sizes.heightOfImage - --Создаем пустой мастерпиксельс - for j = 1, sizes.heightOfImage * sizes.widthOfImage do - table.insert(masterPixels, 0x000000) - table.insert(masterPixels, 0x000000) - table.insert(masterPixels, 0xFF) - table.insert(masterPixels, " ") - end -end - ---Формула конвертации итератора массива в абсолютные координаты пикселя изображения -local function convertIteratorToCoords(iterator) - --Приводим итератор к корректному виду (1 = 1, 5 = 2, 9 = 3, 13 = 4, 17 = 5, ...) - iterator = (iterator + sizes.sizeOfPixelData - 1) / sizes.sizeOfPixelData - --Получаем остаток от деления итератора на ширину изображения - local ostatok = iterator % sizes.widthOfImage - --Если остаток равен 0, то х равен ширине изображения, а если нет, то х равен остатку - local x = (ostatok == 0) and sizes.widthOfImage or ostatok - --А теперь как два пальца получаем координату по Y - local y = math.ceil(iterator / sizes.widthOfImage) - --Очищаем остаток из оперативки - ostatok = nil - --Возвращаем координаты - return x, y -end - ---Формула конвертации абсолютных координат пикселя изображения в итератор для массива -local function convertCoordsToIterator(x, y) - --Конвертируем координаты в итератор - return (sizes.widthOfImage * (y - 1) + x) * sizes.sizeOfPixelData - sizes.sizeOfPixelData + 1 -end - -local function console(text) - ecs.square(sizes.xStartOfDrawingArea, sizes.ySize, sizes.widthOfDrawingArea, 1, colors.console) - local _, total, used = ecs.getInfoAboutRAM() - ecs.colorText(sizes.xEndOfDrawingArea - 15, sizes.ySize, colors.consoleText, used.."/"..total.." KB RAM") - gpu.set(sizes.xStartOfDrawingArea + 1, sizes.ySize, text) - _, total, used = nil, nil, nil -end - -local function drawPixel(x, y, i, j, iterator) - --Получаем данные о пикселе - local background, foreground, alpha, symbol = masterPixels[iterator], masterPixels[iterator + 1], masterPixels[iterator + 2], masterPixels[iterator + 3] - --Если пиксель не прозрачный - if alpha == 0x00 then - gpu.setBackground(background) - gpu.setForeground(foreground) - gpu.set(x, y, symbol) - --Если пиксель прозрачнее непрозрачного - elseif alpha > 0x00 then - --Рисуем прозрачный пиксель - drawTransparentPixel(x, y, i, j) - --Ебать я красавчик! Даже без гпу.гет() сделал! - gpu.setBackground(colorlib.alphaBlend(colors.transparencyVariable, background, alpha)) - gpu.setForeground(foreground) - gpu.set(x, y, symbol) - end - background, foreground, alpha, symbol = nil, nil, nil, nil -end - -local function drawImage() - --Стартовые нужности - local xPixel, yPixel = 1, 1 - local xPos, yPos = sizes.xStartOfImage, sizes.yStartOfImage - --Перебираем массив мастерпиксельса - for i = 1, #masterPixels, 4 do - --Если пиксель входит в разрешенную зону рисования - if xPos >= sizes.xStartOfDrawingArea and xPos <= sizes.xEndOfDrawingArea and yPos >= sizes.yStartOfDrawingArea and yPos <= sizes.yEndOfDrawingArea then - --Рисуем пиксель - drawPixel(xPos, yPos, xPixel, yPixel, i) - end - --Всякие расчеты координат - xPixel = xPixel + 1 - xPos = xPos + 1 - if xPixel > sizes.widthOfImage then xPixel = 1; xPos = sizes.xStartOfImage; yPixel = yPixel + 1; yPos = yPos + 1 end - end -end - -local function drawBackgroundAndImage() - drawBackground() - drawImage() -end - -local function drawAll() - --Очищаем экран - ecs.prepareToExit() - --И консольку! - console("Весь интерфейс перерисован!") - --Рисуем тулбары - drawBackground() - drawLeftBar() - drawTopBar() - drawTopMenu() - --Рисуем картинку - drawBackgroundAndImage() -end - ------------------------------------------------- Функции расчета -------------------------------------------------------------- - -local function move(direction) - if direction == "up" then - sizes.yStartOfImage = sizes.yStartOfImage - 2 - elseif direction == "down" then - sizes.yStartOfImage = sizes.yStartOfImage + 2 - elseif direction == "left" then - sizes.xStartOfImage = sizes.xStartOfImage - 2 - elseif direction == "right" then - sizes.xStartOfImage = sizes.xStartOfImage + 2 - end - drawBackgroundAndImage() -end - -local function setPixel(iterator, background, foreground, alpha, symbol) - masterPixels[iterator] = background - masterPixels[iterator + 1] = foreground - masterPixels[iterator + 2] = alpha - masterPixels[iterator + 3] = symbol -end - -local function swapColors() - local tempColor = currentForeground - currentForeground = currentBackground - currentBackground = tempColor - tempColor = nil - drawColors() - console("Цвета поменяны местами.") -end - -local function inputText(x, y, limit) - local oldPixels = ecs.rememberOldPixels(x,y-1,x+limit-1,y+1) - - local text = "" - local inputPos = 1 - - local function drawThisShit() - for i=1,inputPos do - ecs.invertedText(x + i - 1, y + 1, "─") - ecs.adaptiveText(x + i - 1, y - 1, " ", currentBackground) - end - ecs.invertedText(x + inputPos - 1, y + 1, "▲")--"▲","▼" - ecs.invertedText(x + inputPos - 1, y - 1, "▼") - ecs.adaptiveText(x, y, ecs.stringLimit("start", text, limit, false), currentBackground) - end - - drawThisShit() - - while true do - local e = {event.pull()} - if e[1] == "key_down" then - if e[4] == 14 then - if unicode.len(text) >= 1 then - text = unicode.sub(text, 1, -2) - if unicode.len(text) < (limit - 1) then - inputPos = inputPos - 1 - end - ecs.drawOldPixels(oldPixels) - drawThisShit() - end - elseif e[4] == 28 then - break - else - local symbol = ecs.convertCodeToSymbol(e[3]) - if symbol ~= nil then - text = text .. symbol - if unicode.len(text) < limit then - inputPos = inputPos + 1 - end - drawThisShit() - end - end - elseif e[1] == "clipboard" then - if e[3] then - text = text .. e[3] - if unicode.len(text) < limit then - inputPos = inputPos + unicode.len(e[3]) - end - drawThisShit() - end - end - end - - ecs.drawOldPixels(oldPixels) - if text == "" then text = " " end - return text -end - -local function saveTextToPixels(x, y, text) - local sText = unicode.len(text) - local iterator - x = x - 1 - for i = 1, sText do - if x + i > sizes.widthOfImage then break end - iterator = convertCoordsToIterator(x + i, y) - setPixel(iterator, masterPixels[iterator], currentBackground, masterPixels[iterator + 2], unicode.sub(text, i, i)) - end -end - -local function flipVertical(massiv) - local newMassiv = {} - newMassiv.width, newMassiv.height = massiv.width, massiv.height - - local iterator = #masterPixels - while iterator >= 1 do - table.insert(newMassiv, masterPixels[iterator - 3]) - table.insert(newMassiv, masterPixels[iterator - 2]) - table.insert(newMassiv, masterPixels[iterator - 1]) - table.insert(newMassiv, masterPixels[iterator]) - - masterPixels[iterator], masterPixels[iterator - 1], masterPixels[iterator - 2], masterPixels[iterator - 3] = nil, nil, nil, nil - - iterator = iterator - 4 - end - - return newMassiv -end - -local function flipHorizontal( picture ) - local blockSize = picture.width * 4 - - local buffer = nil - local startBlock = nil - local endPixel = nil - - for j=1, picture.height, 1 do - startBlock = picture.width * 4 * (j-1) - - for pixel=4, blockSize/2, 4 do - endPixel = blockSize-(pixel-4) - - --Foreground - buffer = picture[pixel-3+startBlock] - picture[pixel-3+startBlock] = picture[endPixel-3+startBlock] - picture[endPixel-3+startBlock] = buffer - - --Background - buffer = picture[pixel-2+startBlock] - picture[pixel-2+startBlock] = picture[endPixel-2+startBlock] - picture[endPixel-2+startBlock] = buffer - - --Alpha - buffer = picture[pixel-1+startBlock] - picture[pixel-1+startBlock] = picture[endPixel-1+startBlock] - picture[endPixel-1+startBlock] = buffer - - --Char - buffer = picture[pixel-0+startBlock] - picture[pixel-0+startBlock] = picture[endPixel-0+startBlock] - picture[endPixel-0+startBlock] = buffer - end - end -end - -local function doFlip(horizontal) - if horizontal then - flipHorizontal(masterPixels) - else - masterPixels = flipVertical(masterPixels) - end - drawImage() -end - -local function invertColors() - for i = 1, #masterPixels, 4 do - masterPixels[i] = 0xFFFFFF - masterPixels[i] - masterPixels[i + 1] = 0xFFFFFF - masterPixels[i + 1] - end - drawImage() -end - -local function blackAndWhite() - for i = 1, #masterPixels, 4 do - local hh, ss, bb = colorlib.HEXtoHSB(masterPixels[i]); ss = 0 - masterPixels[i] = colorlib.HSBtoHEX(hh, ss, bb) - - hh, ss, bb = colorlib.HEXtoHSB(masterPixels[i + 1]); ss = 0 - masterPixels[i + 1] = colorlib.HSBtoHEX(hh, ss, bb) - end - drawImage() -end - -local function new() - local data = ecs.universalWindow("auto", "auto", 30, ecs.windowColors.background, false, {"EmptyLine"}, {"CenterText", 0x262626, "Новый документ"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, "Ширина"}, {"Input", 0x262626, 0x880000, "Высота"}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "Ok!"}}) - - data[1] = tonumber(data[1]) or 51 - data[2] = tonumber(data[2]) or 19 - - sizes.widthOfImage, sizes.heightOfImage = data[1], data[2] - sizes.xStartOfImage = 9 - sizes.yStartOfImage = 6 - sizes.xEndOfImage = sizes.xStartOfImage + sizes.widthOfImage - 1 - sizes.yEndOfImage = sizes.yStartOfImage + sizes.heightOfImage - 1 - - createEmptyMasterPixels() - drawAll() -end - ---Обычная рекурсивная заливка -local function fill(x, y, startColor, fillColor) - local function doFill(xStart, yStart) - local iterator = convertCoordsToIterator(xStart, yStart) - - --Завершаем функцию, если цвет в массиве не такой, какой мы заливаем - if masterPixels[iterator] ~= startColor or masterPixels[iterator] == fillColor then return end - - --Заливаем в память - masterPixels[iterator] = fillColor - masterPixels[iterator + 2] = currentAlpha - - doFill(xStart + 1, yStart) - doFill(xStart - 1, yStart) - doFill(xStart, yStart + 1) - doFill(xStart, yStart - 1) - - iterator = nil - end - doFill(x, y) -end - ---Кисть -local function brush(x, y, background, foreground, alpha, symbol) - --Смещение влево и вправо относительно указанного центра кисти - local position = math.floor(currentBrushSize / 2) - local newIterator - --Сдвигаем х и у на смещение - x, y = x - position, y - position - --Считаем ширину/высоту кисти - local brushSize = position * 2 + 1 - --Перебираем кисть по ширине и высоте - for cyka = 1, brushSize do - for pidor = 1, brushSize do - --Если этот кусочек входит в границы рисовабельной зоны, то - if x >= 1 and x <= sizes.widthOfImage and y >= 1 and y <= sizes.heightOfImage then - - --Считаем новый итератор для кусочка кисти - newIterator = convertCoordsToIterator(x, y) - - --Если указанная прозрачность не максимальна - if alpha < 0xFF then - --Если пиксель в массиве ни хуя не прозрачный, то оставляем его таким же, разве что цвет меняем на сблендированный - if masterPixels[newIterator + 2] == 0x00 then - local gettedBackground = colorlib.alphaBlend(masterPixels[newIterator], background, alpha) - setPixel(newIterator, gettedBackground, foreground, 0x00, symbol) - --А если прозрачный - else - --Если его прозоачность максимальная - if masterPixels[newIterator + 2] == 0xFF then - setPixel(newIterator, background, foreground, alpha, symbol) - --Если не максимальная - else - local newAlpha = masterPixels[newIterator + 2] - (0xFF - alpha) - if newAlpha < 0x00 then newAlpha = 0x00 end - setPixel(newIterator, background, foreground, newAlpha, symbol) - end - end - --Если указанная прозрачность максимальна, т.е. равна 0xFF - else - setPixel(newIterator, 0x000000, 0x000000, 0xFF, " ") - end - --Рисуем пиксель из мастерпиксельса - drawPixel(x + sizes.xStartOfImage - 1, y + sizes.yStartOfImage - 1, x, y, newIterator) - end - - x = x + 1 - end - x = x - brushSize - y = y + 1 - end -end - ------------------------------------------------- Старт программы -------------------------------------------------------------- - ---Создаем пустой мастерпиксельс ---createEmptyMasterPixels() - ---Рисуем весь интерфейс -drawAll() -new() - -while true do - local e = {event.pull()} - if e[1] == "touch" or e[1] == "drag" then - --Левый клик - if e[5] == 0 then - --Если кликнули на рисовабельную зонку - if ecs.clickedAtArea(e[3], e[4], sizes.xStartOfImage, sizes.yStartOfImage, sizes.xEndOfImage, sizes.yEndOfImage) then - - local x, y = e[3] - sizes.xStartOfImage + 1, e[4] - sizes.yStartOfImage + 1 - local iterator = convertCoordsToIterator(x, y) - - --Кисть - if currentInstrument == 1 then - - --Если нажата клавиша альт - if keyboard.isKeyDown(56) then - local _, _, gettedBackground = gpu.get(e[3], e[4]) - currentBackground = gettedBackground - drawColors() - - --Если обычная кисть, просто кисть, вообще всем кистям кисть - else - - brush(x, y, currentBackground, currentForeground, currentAlpha, currentSymbol) - - --Пишем что-то в консоли - console("Кисть: клик на точку "..e[3].."x"..e[4]..", координаты в изображении: "..x.."x"..y..", индекс массива изображения: "..iterator) - end - --Ластик - elseif currentInstrument == 2 then - - brush(x, y, currentBackground, currentForeground, 0xFF, currentSymbol) - - console("Ластик: клик на точку "..e[3].."x"..e[4]..", координаты в изображении: "..x.."x"..y..", индекс массива изображения: "..iterator) - - --Текст - elseif currentInstrument == 4 then - local limit = sizes.widthOfImage - x + 1 - local text = inputText(e[3], e[4], limit) - saveTextToPixels(x, y, text) - drawImage() - - --Заливка - elseif currentInstrument == 3 then - - fill(x, y, masterPixels[iterator], currentBackground) - - drawImage() - - end - - iterator, x, y = nil, nil, nil - - end - - --Цвета - for key in pairs(obj["Colors"]) do - if ecs.clickedAtArea(e[3], e[4], obj["Colors"][key][1], obj["Colors"][key][2], obj["Colors"][key][3], obj["Colors"][key][4]) then - if key == 1 then - currentBackground = palette.draw("auto", "auto", currentBackground) or currentBackground - drawColors() - elseif key == 2 or key == 3 then - currentForeground = palette.draw("auto", "auto", currentForeground) or currentForeground - drawColors() - elseif key == 4 then - ecs.colorTextWithBack(obj["Colors"][key][1], obj["Colors"][key][2], 0xFF0000, colors.toolbar, "←→") - os.sleep(0.2) - swapColors() - end - break - end - end - - --Инструменты - for key in pairs(obj["Instruments"]) do - if ecs.clickedAtArea(e[3], e[4], obj["Instruments"][key][1], obj["Instruments"][key][2], obj["Instruments"][key][3], obj["Instruments"][key][4]) then - currentInstrument = key - drawInstruments() - break - end - end - - --Верхний меню-бар - for key in pairs(obj["TopMenu"]) do - if ecs.clickedAtArea(e[3], e[4], obj["TopMenu"][key][1], obj["TopMenu"][key][2], obj["TopMenu"][key][3], obj["TopMenu"][key][4]) then - ecs.square(obj["TopMenu"][key][1] - 1, obj["TopMenu"][key][2], unicode.len(key) + 2, 1, ecs.colors.blue) - ecs.colorText(obj["TopMenu"][key][1], obj["TopMenu"][key][2], 0xffffff, key) - local action - - if key == "Файл" then - action = context.menu(obj["TopMenu"][key][1] - 1, obj["TopMenu"][key][2] + 1, {"Новый"}, {"Открыть"}, "-", {"Сохранить", (savePath == nil)}, {"Сохранить как"}, "-", {"Выход"}) - elseif key == "Изображение" then - action = context.menu(obj["TopMenu"][key][1] - 1, obj["TopMenu"][key][2] + 1, {"Отразить по горизонтали"}, {"Отразить по вертикали"}, "-", {"Инвертировать цвета"}, {"Черно-белый фильтр"}) - elseif key == "Инструменты" then - action = context.menu(obj["TopMenu"][key][1] - 1, obj["TopMenu"][key][2] + 1, {"Кисть"}, {"Ластик"}, {"Заливка"}, {"Текст"}) - elseif key == "О программе" then - ecs.universalWindow("auto", "auto", 36, 0xeeeeee, true, {"EmptyLine"}, {"CenterText", 0x880000, "Photoshop v3.0 (public beta)"}, {"EmptyLine"}, {"CenterText", 0x262626, "Авторы:"}, {"CenterText", 0x555555, "Тимофеев Игорь"}, {"CenterText", 0x656565, "vk.com/id7799889"}, {"CenterText", 0x656565, "Трифонов Глеб"}, {"CenterText", 0x656565, "vk.com/id88323331"}, {"EmptyLine"}, {"CenterText", 0x262626, "Тестеры:"}, {"CenterText", 0x656565, "Шестаков Тимофей"}, {"CenterText", 0x656565, "vk.com/id113499693"}, {"CenterText", 0x656565, "Вечтомов Роман"}, {"CenterText", 0x656565, "vk.com/id83715030"}, {"CenterText", 0x656565, "Омелаенко Максим"}, {"CenterText", 0x656565, "vk.com/paladincvm"}, {"EmptyLine"},{"Button", {0xbbbbbb, 0xffffff, "OK"}}) - end - - if action == "Выход" then - ecs.prepareToExit() - return - elseif action == "Отразить по горизонтали" then - doFlip(true) - elseif action == "Отразить по вертикали" then - doFlip(false) - elseif action == "Инвертировать цвета" then - invertColors() - elseif action == "Черно-белый фильтр" then - blackAndWhite() - elseif action == "Ластик" then - currentInstrument = 2 - drawInstruments() - elseif action == "Кисть" then - currentInstrument = 1 - drawInstruments() - elseif action == "Текст" then - currentInstrument = 4 - drawInstruments() - elseif action == "Заливка" then - currentInstrument = 3 - drawInstruments() - elseif action == "Новый" then - new() - - elseif action == "Сохранить как" then - local data = ecs.universalWindow("auto", "auto", 30, ecs.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Сохранить как"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, "Путь"}, {"Selector", 0x262626, 0x880000, ".PIC", ".RAWPIC"}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK"}}) - data[1] = data[1] or "Untitled" - data[2] = unicode.lower(data[2] or "PIC") - local fileName = data[1]..data[2] - image.save(fileName, masterPixels) - savePath = fileName - - elseif action == "Сохранить" then - image.save(savePath, masterPixels) - - elseif action == "Открыть" then - local data = ecs.universalWindow("auto", "auto", 30, ecs.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Открыть"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, "Путь"}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK"}}) - local fileFormat = ecs.getFileFormat(data[1]) - - if not data[1] then - ecs.error("Некорректное имя файла!") - elseif not fs.exists(data[1]) then - ecs.error("Файл\""..data[1].."\" не существует!") - elseif fileFormat ~= ".pic" and fileFormat ~= ".rawpic" then - ecs.error("Формат файла \""..fileFormat.."\" не поддерживается!") - else - masterPixels = image.load(data[1]) - reCalculateImageSizes() - drawImage() - end - end - - drawTopMenu() - break - end - end - - --Топбар - for key in pairs(obj["TopBarInputs"]) do - if ecs.clickedAtArea(e[3], e[4], obj["TopBarInputs"][key][1], obj["TopBarInputs"][key][2], obj["TopBarInputs"][key][3], obj["TopBarInputs"][key][4]) then - local input = ecs.inputText(obj["TopBarInputs"][key][1], obj["TopBarInputs"][key][2], obj["TopBarInputs"][key][5], "", 0xffffff, 0x262626) - input = tonumber(input) - - if input then - if key == 1 then - if input > 0 and input < 10 then currentBrushSize = input end - elseif key == 2 then - if input > 0 and input <= 255 then currentAlpha = input end - end - end - - drawTopBar() - - break - end - end - else - --Если кликнули на рисовабельную зонку - if ecs.clickedAtArea(e[3], e[4], sizes.xStartOfImage, sizes.yStartOfImage, sizes.xEndOfImage, sizes.yEndOfImage) then - - local x, y, width, height = e[3], e[4], 30, 12 - - --А это чтоб за края экрана не лезло - if y + height >= sizes.ySize then y = sizes.ySize - height end - if x + width + 1 >= sizes.xSize then x = sizes.xSize - width - 1 end - - currentBrushSize, currentAlpha = table.unpack(ecs.universalWindow(x, y, width, 0xeeeeee, true, {"EmptyLine"}, {"CenterText", 0x880000, "Параметры кисти"}, {"Slider", 0x262626, 0x880000, 1, 10, currentBrushSize, "Размер: ", " px"}, {"Slider", 0x262626, 0x880000, 0, 255, currentAlpha, "Прозрачность: ", ""}, {"EmptyLine"}, {"Button", {0xbbbbbb, 0xffffff, "OK"}})) - drawTopBar() - end - end - - elseif e[1] == "key_down" then - --Стрелки - if e[4] == 200 then - move("up") - elseif e[4] == 208 then - move("down") - elseif e[4] == 203 then - move("left") - elseif e[4] == 205 then - move("right") - --Пробел - elseif e[4] == 57 then - drawAll() - --X - elseif e[4] == 45 then - swapColors() - --B - elseif e[4] == 48 then - currentInstrument = 1 - drawInstruments() - --E - elseif e[4] == 18 then - currentInstrument = 2 - drawInstruments() - --T - elseif e[4] == 20 then - currentInstrument = 4 - drawInstruments() - - --G - elseif e[4] == 34 then - currentInstrument = 3 - drawInstruments() - --D - elseif e[4] == 32 then - currentBackground = 0x000000 - currentForeground = 0xFFFFFF - currentAlpha = 0x00 - drawColors() - end - elseif e[1] == "scroll" then - - end -end - ------------------------------------------------- Выход из программы -------------------------------------------------------------- - - - - diff --git a/Beta/Printer.lua b/Beta/Printer.lua deleted file mode 100644 index 684e1da8..00000000 --- a/Beta/Printer.lua +++ /dev/null @@ -1,344 +0,0 @@ - ------------------------------------------- Библиотеки ----------------------------------------------------------------- - - -local component = require("component") -local colorlib = require("colorlib") -local event = require("event") -local gpu = component.gpu -local printer = component.printer3d -local hologram = component.hologram - ------------------------------------------- Переменные ----------------------------------------------------------------- - -local pixels = {} - -local model = { - label = "Sosi hui", - tooltip = "mamu ebal", - buttonMode = true, - redstoneEmitter = true, - active = { - {x = 1, y = 1, z = 1, x2 = 1, y2 = 1, z2 = 12}, - - {x = 1, y = 8, z = 1, x2 = 8, y2 = 8, z2 = 16}, - - {x = 16, y = 16, z = 16, x2 = 16, y2 = 16, z2 = 16}, - }, - passive = {} -} - -local colors = { - objects = 0x3349FF, - points = 0xFFFFFF, - border = 0xFFFF00, - background = 0x262626, - rightBar = 0x383838, - lines = 0x222222, - -} -local countOfShapes = printer.getMaxShapeCount() -local adder = 360 / countOfShapes -local hue = 0 -colors.shapes = {} -for i = 1, countOfShapes do - table.insert(colors.shapes, colorlib.HSBtoHEX(hue, 100, 100)) - hue = hue + adder -end - -local sizes = {} -sizes.oldResolutionWidth, sizes.oldResolutionHeight = gpu.getResolution() -sizes.xSize, sizes.ySize = gpu.maxResolution() --- -sizes.widthOfRightBar, sizes.heightOfRightBar = 36, sizes.ySize -sizes.xStartOfRightBar, sizes.yStartOfRightBar = sizes.xSize - sizes.widthOfRightBar + 1, 1 --- -sizes.widthOfHorizontal = sizes.xSize - sizes.widthOfRightBar -sizes.xStartOfVertical, sizes.yStartOfVertical = math.floor(sizes.widthOfHorizontal / 2), 1 -sizes.xStartOfHorizontal, sizes.yStartOfHorizontal = 1, math.floor(sizes.ySize / 2) --- -sizes.widthOfPixel, sizes.heightOfPixel = 2, 1 -sizes.image = {} - -sizes.image[1] = {x = math.floor(sizes.xStartOfVertical / 2 - (sizes.widthOfPixel * 16) / 2), y = math.floor(sizes.yStartOfHorizontal / 2 - (sizes.heightOfPixel * 16) / 2)} -sizes.image[2] = {x = sizes.xStartOfVertical + sizes.image[1].x + 1, y = sizes.image[1].y} -sizes.image[3] = {x = sizes.image[1].x, y = sizes.yStartOfHorizontal + sizes.image[1].y + 1} -sizes.image[4] = {x = sizes.image[2].x, y = sizes.image[3].y} - -local holoOutlineX, holoOutlineY, holoOutlineZ = 16, 24, 16 -local currentShape = 1 -local currentLayer = 1 - ------------------------------------------- Функции ----------------------------------------------------------------- - -local function drawTransparentBackground(x, y, color1, color2) - local xPos, yPos = x, y - local color - for j = 1, 16 do - for i = 1, 16 do - if i % 2 == 0 then - if j % 2 == 0 then - color = color1 - else - color = color2 - end - else - if j % 2 == 0 then - color = color2 - else - color = color1 - end - end - ecs.square(xPos, yPos, sizes.widthOfPixel, sizes.heightOfPixel, color) - xPos = xPos + sizes.widthOfPixel - end - xPos = x - yPos = yPos + sizes.heightOfPixel - end -end - -local function changePalette() - hologram.setPaletteColor(1, colors.objects) - hologram.setPaletteColor(2, colors.points) - hologram.setPaletteColor(3, colors.border) -end - -local function drawShapesList(x, y) - local xPos, yPos = x, y - local color - for i = 1, countOfShapes do - color = 0x000000 - if i == currentShape then color = colors.shapes[i] end - ecs.drawButton(xPos, yPos, 4, 1, tostring(i), color, 0xFFFFFF ) - xPos = xPos + 5 - if i % 6 == 0 then xPos = x; yPos = yPos + 2 end - end -end - -local function drawInfo(y, info) - ecs.square(sizes.xStartOfRightBar, y, sizes.widthOfRightBar, 1, 0x000000) - ecs.colorText(sizes.xStartOfRightBar + 2, y, 0xFFFFFF, info) -end - -local function drawRightBar() - local xPos, yPos = sizes.xStartOfRightBar, sizes.yStartOfRightBar - ecs.square(xPos, yPos, sizes.widthOfRightBar, sizes.heightOfRightBar, colors.rightBar) - - drawInfo(yPos, "Работа с моделью"); yPos = yPos + 2 - - yPos = yPos + 5 - - drawInfo(yPos, "Работа с объектом"); yPos = yPos + 2 - - yPos = yPos + 5 - - drawInfo(yPos, "Выбор объекта"); yPos = yPos + 3 - drawShapesList(xPos + 2, yPos); yPos = yPos + (countOfShapes / 6 * 2) + 1 - - drawInfo(yPos, "Управление голограммой"); yPos = yPos + 2 - - yPos = yPos + 5 - - - drawInfo(yPos, "Управление принтером"); yPos = yPos + 2 - - yPos = yPos + 5 - - -end - -local function drawLines() - ecs.square(sizes.xStartOfVertical, sizes.yStartOfVertical, 2, sizes.ySize,colors.lines) - ecs.square(sizes.xStartOfHorizontal, sizes.yStartOfHorizontal, sizes.widthOfHorizontal , 1, colors.lines) -end - -local function drawViewArray(x, y, massiv) - local xPos, yPos = x, y - for i = 1, #massiv do - for j = 1, #massiv[i] do - if massiv[i][j] ~= "#" then - ecs.square(xPos, yPos, sizes.widthOfPixel, sizes.heightOfPixel, massiv[i][j]) - end - xPos = xPos + sizes.widthOfPixel - end - xPos = x - yPos = yPos + sizes.heightOfPixel - end -end - ---Нарисовать вид спереди -local function drawFrontView() - local massiv = {} - for i = 1, 16 do - massiv[i] = {} - for j = 1, 16 do - massiv[i][j] = "#" - end - end - for x = 1, #pixels do - for y = 1, #pixels[x] do - for z = 1, #pixels[x][y] do - if pixels[x][y][z] ~= "#" then - massiv[y][x] = pixels[x][y][z] - end - end - end - end - drawViewArray(sizes.image[1].x, sizes.image[1].y, massiv) -end - ---Нарисовать вид сверху -local function drawTopView() - local massiv = {} - for i = 1, 16 do - massiv[i] = {} - for j = 1, 16 do - massiv[i][j] = "#" - end - end - for x = 1, #pixels do - for y = 1, #pixels[x] do - for z = 1, #pixels[x][y] do - if pixels[x][y][z] ~= "#" then - massiv[z][x] = pixels[x][y][z] - end - end - end - end - drawViewArray(sizes.image[3].x, sizes.image[3].y, massiv) -end - ---Нарисовать вид сбоку -local function drawSideView() - local massiv = {} - for i = 1, 16 do - massiv[i] = {} - for j = 1, 16 do - massiv[i][j] = "#" - end - end - for x = 1, #pixels do - for y = 1, #pixels[x] do - for z = 1, #pixels[x][y] do - if pixels[x][y][z] ~= "#" then - massiv[y][z] = pixels[x][y][z] - end - end - end - end - drawViewArray(sizes.image[2].x, sizes.image[2].y, massiv) -end - ---Сконвертировать массив объектов в трехмерный массив 3D-изображения -local function render() - pixels = {} - - for x = 1, 16 do - pixels[x] = {} - for y = 1, 16 do - pixels[x][y] = {} - for z = 1, 16 do - pixels[x][y][z] = "#" - end - end - end - - for x = 1, 16 do - for y = 1, 16 do - for z = 1, 16 do - for i = 1, #model.active do - if (x >= model.active[i].x and x <= model.active[i].x2) and (y >= model.active[i].y and y <= model.active[i].y2) and (z >= model.active[i].z and z <= model.active[i].z2) then - pixels[x][y][z] = colors.shapes[i] - --hologram.set(x, y, z, 1) - end - end - end - end - end -end - -local function drawBorder() - for i = 0, 17 do - hologram.set(i + holoOutlineX, holoOutlineY - currentLayer, holoOutlineZ, 3) - hologram.set(i + holoOutlineX, holoOutlineY - currentLayer, 17 + holoOutlineZ, 3) - hologram.set(holoOutlineX, holoOutlineY - currentLayer, i + holoOutlineZ, 3) - hologram.set(17 + holoOutlineX, holoOutlineY - currentLayer, i + holoOutlineZ, 3) - end -end - -local function drawFrame() - --Верхний левый - for i = 1, 2 do hologram.set(i + holoOutlineX - 1, holoOutlineY - 1, holoOutlineZ, 2) end - hologram.set(holoOutlineX, holoOutlineY - 1, holoOutlineZ + 1, 2) - hologram.set(holoOutlineX, holoOutlineY - 2, holoOutlineZ, 2) - --Верхний левый - for i = 1, 2 do hologram.set(i + holoOutlineX - 1, holoOutlineY - 16, holoOutlineZ, 2) end - hologram.set(holoOutlineX, holoOutlineY - 16, holoOutlineZ + 1, 2) - hologram.set(holoOutlineX, holoOutlineY - 15, holoOutlineZ, 2) -end - -local function drawModelOnHolo() - hologram.clear() - for x = 1, #pixels do - for y = 1, #pixels[x] do - for z = 1, #pixels[x][y] do - if pixels[x][y][z] ~= "#" then - hologram.set(x + holoOutlineX, holoOutlineY - y, z + holoOutlineZ, 1) - end - end - end - end - - drawBorder() - --drawFrame() -end - -local function drawAllViews() - render() - drawModelOnHolo() - drawFrontView() - drawTopView() - drawSideView() - - drawTransparentBackground(sizes.image[4].x, sizes.image[4].y, 0xFFFFFF, 0xDDDDDD) -end - -local function drawAll() - drawLines() - drawAllViews() - drawRightBar() -end - ------------------------------------------- Программа ----------------------------------------------------------------- - -if sizes.xSize < 150 then ecs.error("Этой программе требуется монитор и видеокарта 3 уровня."); return end - -gpu.setResolution(sizes.xSize, sizes.ySize) - -ecs.prepareToExit() -changePalette() -drawAll() - -while true do - local e = {event.pull()} - if e[1] == "scroll" then - if e[5] == 1 then - if currentLayer > 1 then currentLayer = currentLayer - 1;drawModelOnHolo() end - else - if currentLayer < 16 then currentLayer = currentLayer + 1;drawModelOnHolo() end - end - end -end - ------------------------------------------- Выход из программы ----------------------------------------------------------------- - -gpu.setResolution(sizes.oldResolutionWidth, sizes.oldResolutionHeight) - - - - - - - - - diff --git a/Beta/Reactor.lua b/Beta/Reactor.lua deleted file mode 100644 index 3531b357..00000000 --- a/Beta/Reactor.lua +++ /dev/null @@ -1,18 +0,0 @@ -local ecs = require("ECSAPI") -local components = require("component") - - -local function getInfoAboutReactors() - local massiv = {} - for component, address in pairs(components) do - if component == "reactor_chamber" then - table.insert(massiv, components.proxy(address)) - end - end -end - -local reactors = getInfoAboutReactors() - -for i = 1, #reactors do - print(reactors[i]) -end \ No newline at end of file diff --git a/Beta/Shop2.lua b/Beta/Shop2.lua deleted file mode 100644 index 00109fc1..00000000 --- a/Beta/Shop2.lua +++ /dev/null @@ -1,1073 +0,0 @@ - ------------------------------------------- Библиотеки ----------------------------------------------------------------- - -local event = require("event") -local component = require("component") -local unicode = require("unicode") -local fs = require("filesystem") -local sides = require("sides") -local serialization = require("serialization") -local chestSide = sides.up -local gpu = component.gpu -local inventoryController - -if not component.isAvailable("inventory_controller") then - ecs.error("Данная программа требует подключенный Адаптер с вставленным в него улучшением \"Контроллер инвентаря\", при этом на сам адаптер сверху необходимо поставить сундук, в который будут поступать предметы для продажи.") - return -else - inventoryController = component.inventory_controller -end - ------------------------------------------- Переменные ----------------------------------------------------------------- - -local colors = { - ["background"] = 0x262626, - ["topbar"] = 0xffffff, - ["topbarText"] = 0x444444, - ["topbarActive"] = ecs.colors.blue, - ["topbarActiveText"] = 0xffffff, - ["inventoryBorder"] = 0xffffff, - ["inventoryBorderSelect"] = ecs.colors.blue, - ["inventoryBorderSelectText"] = 0xffffff, - ["inventoryText"] = 0x262626, - ["inventoryTextDarker"] = 0x666666, - ["sellButtonColor"] = ecs.colors.blue, - ["sellButtonTextColor"] = 0xffffff, - rarity = { - ["Common"] = 0xB0C3D9, - ["Uncommon"] = 0x5E98D9, - ["Rare"] = 0x4B69FF, - ["Mythical"] = 0x8847FF, - ["Legendary"] = 0xD32CE6, - ["Immortal"] = 0xE4AE33, - ["Arcana"] = 0xADE55C, - ["Ancient"] = 0xEB4B4B - } -} - ---Массив админшопа с базовой информацией о блоках -local adminShop = { - ["minecraft:stone"] = { - [0] = { - ["price"] = 4, - ["rarity"] = "Uncommon", - }, - }, - ["minecraft:diamond"] = { - [0] = { - ["price"] = 200, - ["rarity"] = "Legendary", - }, - }, - ["minecraft:grass"] = { - [0] = { - ["price"] = 4, - ["rarity"] = "Uncommon", - }, - }, - ["minecraft:cobblestone"] = { - [0] = { - ["price"] = 2, - ["rarity"] = "Common", - }, - }, - ["minecraft:dirt"] = { - [0] = { - ["price"] = 2, - ["rarity"] = "Common", - }, - }, - ["minecraft:iron_ore"] = { - [0] = { - ["price"] = 20, - ["rarity"] = "Rare", - }, - }, - ["minecraft:gold_ore"] = { - [0] = { - ["price"] = 40, - ["rarity"] = "Mythical", - }, - }, - ["minecraft:coal_ore"] = { - [0] = { - ["price"] = 5, - ["rarity"] = "Uncommon", - }, - }, - ["minecraft:wool"] = { - [0] = { - ["price"] = 10, - ["rarity"] = "Uncommon", - }, - [15] = { - ["price"] = 15, - ["rarity"] = "Uncommon", - }, - [14] = { - ["price"] = 15, - ["rarity"] = "Uncommon", - }, - }, - ["minecraft:redstone"] = { - [0] = { - ["price"] = 10, - ["rarity"] = "Rare", - }, - }, - ["minecraft:log"] = { - [0] = { - ["price"] = 3, - ["rarity"] = "Common", - }, - }, - ["IC2:itemOreIridium"] = { - [0] = { - ["price"] = 50000, - ["rarity"] = "Arcana", - }, - }, -} - ---Массив инвентаря конкретного игрока -local massivWithProfile = { - -- ["nickname"] = "IT", - -- ["money"] = 100, - -- ["inventory"] = { - -- { - -- ["id"] = "minecraft:stone", - -- ["label"] = "Stone", - -- ["data"] = 0, - -- ["count"] = 64, - -- }, - -- { - -- ["id"] = "minecraft:grass", - -- ["data"] = 0, - -- ["label"] = "Grass", - -- ["count"] = 32, - -- }, - -- { - -- ["id"] = "minecraft:wool", - -- ["data"] = 0, - -- ["label"] = "Red wool", - -- ["count"] = 12, - -- }, - -- { - -- ["id"] = "minecraft:diamond", - -- ["data"] = 0, - -- ["label"] = "Diamond", - -- ["count"] = 999, - -- }, - -- { - -- ["id"] = "minecraft:cobblestone", - -- ["data"] = 0, - -- ["label"] = "Cobblestone", - -- ["count"] = 47000, - -- }, - -- { - -- ["id"] = "minecraft:redstone", - -- ["data"] = 0, - -- ["label"] = "Redstone", - -- ["count"] = 12000, - -- }, - -- { - -- ["id"] = "minecraft:iron_ore", - -- ["data"] = 0, - -- ["label"] = "Iron ore", - -- ["count"] = 572, - -- }, - -- { - -- ["id"] = "minecraft:gold_ore", - -- ["data"] = 0, - -- ["label"] = "Gold ore", - -- ["count"] = 246, - -- }, - -- { - -- ["id"] = "minecraft:coal_ore", - -- ["data"] = 0, - -- ["label"] = "Coal ore", - -- ["count"] = 11, - -- }, - -- { - -- ["id"] = "IC2:itemOreIridium", - -- ["data"] = 0, - -- ["label"] = "Iridium Ore", - -- ["count"] = 5, - -- }, - -- { - -- ["id"] = "minecraft:log", - -- ["data"] = 0, - -- ["label"] = "Log", - -- ["count"] = 124782, - -- }, - -- }, -} - ---Массив торговой площадки -local market = { - ["minecraft:diamond"] = { - [0] = { - ["label"] = "Diamond", - { - ["nickname"] = "Daun228", - ["count"] = 228, - ["price"] = 150, - }, - }, - }, - ["minecraft:log"] = { - [0] = { - ["label"] = "Log", - { - ["nickname"] = "CykaRotEbal", - ["count"] = 121304, - ["price"] = 21.8, - }, - }, - }, - ["minecraft:iron_ore"] = { - [0] = { - ["label"] = "Iron Ore", - { - ["nickname"] = "Blyad", - ["count"] = 2424194, - ["price"] = 20, - }, - }, - }, - ["minecraft:gold_ore"] = { - [0] = { - ["label"] = "Gold Ore", - { - ["nickname"] = "EEOneGuy", - ["count"] = 5, - ["price"] = 5, - }, - { - ["nickname"] = "Pidar", - ["count"] = 10, - ["price"] = 10, - }, - { - ["nickname"] = "Mamoeb", - ["count"] = 15, - ["price"] = 15, - }, - }, - }, -} - - -local moneySymbol = "$" -local adminSellMultiplyer = 0.5 -local comissionMultiplyer = 0.04 - -local username = "ECS" -local currentMode = 2 - -local xSize, ySize = gpu.getResolution() - -local widthOfOneItemElement = 12 -local heightOfOneItemElement = widthOfOneItemElement / 2 - ------------------------------------------- Функции сохранения ----------------------------------------------------------------- - -local shopPath = "System/Shop/" -local databasePath = shopPath .. "Users/" -local marketPath = shopPath .. "Market.txt" -local adminShopPath = shopPath .. "AdminShop.txt" -local adminMoneyPath = shopPath .. "AdminMoney.txt" -local logPath = shopPath .. "Shop.log" - -local function init() - fs.makeDirectory(databasePath) -end - -local function saveUser(massiv) - local file = io.open(databasePath .. massiv.nickname .. ".txt", "w") - file:write(serialization.serialize(massiv)) - file:close() -end - -local function createNewUser(nickname) - local massiv = { - ["nickname"] = nickname, - ["money"] = 0, - ["inventory"] = { - { - ["id"] = "minecraft:cobblestone", - ["label"] = "Stone", - ["data"] = 0, - ["count"] = 1, - }, - }, - } - saveUser(massiv) - return massiv -end - -local function loadUser(nickname) - if not fs.exists(databasePath .. nickname .. ".txt") then - return createNewUser(nickname) - else - local file = io.open(databasePath .. nickname .. ".txt", "r") - local text = file:read("*a") - file:close() - return serialization.unserialize(text) - end -end - -local function saveMarket() - local file = io.open(marketPath, "w") - file:write(serialization.serialize(market)) - file:close() -end - -local function loadMarket() - if not fs.exists(marketPath) then - saveMarket() - else - local file = io.open(marketPath, "r") - local text = file:read("*a") - file:close() - market = serialization.unserialize(text) - end -end - -local function loadAdminShop() - if not fs.exists(adminShopPath) then - local file = io.open(adminShopPath, "w") - file:write(serialization.serialize(adminShop)) - file:close() - else - local file = io.open(adminShopPath, "r") - local text = file:read("*a") - file:close() - adminShop = serialization.unserialize(text) - end -end - -local function saveAdminMoney(money) - local file = io.open(adminMoneyPath, "w") - file:write(tostring(money)) - file:close() -end - -local function loadAdminMoney() - if not fs.exists(adminMoneyPath) then - saveAdminMoney(0) - return 0 - else - local file = io.open(adminMoneyPath, "r") - local text = file:read("*a") - file:close() - return tonumber(text) - end -end - -local function addMoneyToAdmins(money) - local currentAdminsMoney = loadAdminMoney() - currentAdminsMoney = currentAdminsMoney + money - saveAdminMoney(currentAdminsMoney) -end - -local function log(text) - local file = io.open(logPath, "a") - file:write(text, "\n") - file:close() -end - ------------------------------------------- Функции ----------------------------------------------------------------- - ---Обжекты -local obj = {} -local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} -end - ---Округление до опред. кол-ва знаков после запятой -local function round(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult -end - ---Сконвертировать кол-во предметов в более компактный вариант -local function prettyItemCount(count) - if count >= 1000000 then - return tostring(round(count / 1000000, 2)) .. "M" - elseif count >= 1000 then - return tostring(round(count / 1000, 2)) .. "K" - end - return tostring(count) -end - ---Фиксим число до 2-х знаков после запятой -local function fixMoney(money) - return round(money, 2) -end - ---Взымаем комиссию с купли/продажи -local function comission(money) - return fixMoney(money - money * comissionMultiplyer) -end - ---Добавление предмета в инвентарь -local function addItemToInventory(id, data, label, count) - --Переменная успеха, означающая, что такой предмет уже есть, - --и что его количество успешно увеличилось - local success = false - --Перебираем весь массив инвентаря и смотрим, есть ли чет такое - for i = 1, #massivWithProfile.inventory do - if id == massivWithProfile.inventory[i].id then - if data == massivWithProfile.inventory[i].data then - massivWithProfile.inventory[i].count = massivWithProfile.inventory[i].count + count - success = true - break - end - end - end - - --Если такого предмета нет, то создать новый слот в инвентаре - if not success then - table.insert(massivWithProfile.inventory, { ["id"] = id, ["data"] = data, ["label"] = label, ["count"] = count } ) - end -end - ---Удалить кол-во предмета из инвентаря -local function removeItemFromInventory(numberOfItemInInventory, count) - --Небольшая подстраховка, чтобы не удалить больше, чем возможно - local skokaMozhnaUdalit = massivWithProfile.inventory[numberOfItemInInventory].count - if count > skokaMozhnaUdalit then count = skokaMozhnaUdalit end - --Уменьшаем количество этого предмета - massivWithProfile.inventory[numberOfItemInInventory].count = massivWithProfile.inventory[numberOfItemInInventory].count - count - --Если количество равно нулю, то удаляем запись о предмете из инвентаря - if massivWithProfile.inventory[numberOfItemInInventory].count == 0 then - table.remove(massivWithProfile.inventory, numberOfItemInInventory) - end -end - ---Просканировать сундук и добавить в него шмот -local function addToInventoryFromChest() - local counter = 0 - local inventorySize = inventoryController.getInventorySize(chestSide) - for i = 1, inventorySize do - local stack = inventoryController.getStackInSlot(chestSide, i) - if stack then - addItemToInventory(stack.name, stack.damage, stack.label, stack.size) - counter = counter + stack.size - end - end - - return counter -end - ---Продать шмотку одменам -local function sellToAdmins(numberOfItemInInventory, skoka) - local item = massivWithProfile.inventory[numberOfItemInInventory] - if adminShop[item.id] then - if adminShop[item.id][item.data] then - local price = fixMoney(adminShop[item.id][item.data].price * adminSellMultiplyer) - removeItemFromInventory(numberOfItemInInventory, skoka) - massivWithProfile.money = massivWithProfile.money + price * skoka - return (price * skoka) - else - ecs.error("У админов нет даты "..tostring(item.data)..", ищи ошибку, говнокодер ебаный!") - return 0 - end - else - ecs.error("У админов нет ид"..tostring(item.id)..", ищи ошибку, говнокодер ебаный!") - return 0 - end -end - ---Продать шмотку игрокам на ТП -local function sellToPlayers(number, count, priceForOneItem, nameOfSeller) - --Получаем инфо о шмотке - local item = massivWithProfile.inventory[number] - --Удаляем шмотку - removeItemFromInventory(number, count) - --Че будем добавлять на ТП - local govno = { ["nickname"] = nameOfSeller, ["count"] = count, ["price"] = priceForOneItem} - --Добавляем ее на ТП - --Если есть такой ид - if market[item.id] then - --И если есть такая дата - if market[item.id][item.data] then - table.insert(market[item.id][item.data], govno) - else - market[item.id][item.data] = { ["label"] = item.label, govno } - end - else - market[item.id] = { [item.data] = { ["label"] = item.label, govno } } - end -end - ---Анализ торговой площадки ---Выдает успех, если предмет найден ---А также самую лучшую цену, количество предмета на торг. площадке и никнейм самого дешевого -local function getInfoAboutItemOnMarket(id, data) - local price, count, success, nickname, label = nil, 0, false, nil, "CYKA" - --Если в маркете есть такой ид - if market[id] then - --И такая дата - if market[id][data] then - --Перебираем все айтемы на маркете - for i = 1, #market[id][data] do - --Если данных таких нет, то создать стартовые - price = price or market[id][data][i].price - nickname = nickname or market[id][data][i].nickname - - --Если цена меньше, чем другие, то новая цена = этой - if market[id][data][i].price < price then - price = market[id][data][i].price - nickname = market[id][data][i].nickname - end - - --Прибавляем кол-во предметов - count = count + market[id][data][i].count - end - label = market[id][data].label - success = true - end - end - return success, price, count, nickname, label -end - - - ---Нарисовать конкретный айтем -local function drawItem(xPos, yPos, back, fore, text1, text2) - --Рисуем квадратик - ecs.square(xPos, yPos, widthOfOneItemElement, heightOfOneItemElement, back) - --Рисуем текст в рамке - text1 = ecs.stringLimit("end", text1, widthOfOneItemElement - 2) - text2 = ecs.stringLimit("end", prettyItemCount(text2), widthOfOneItemElement - 2) - local x - x = xPos + math.floor(widthOfOneItemElement / 2 - unicode.len(text1) / 2) - ecs.colorText(x, yPos + 2, fore, text1) - x = xPos + math.floor(widthOfOneItemElement / 2 - unicode.len(text2) / 2) - ecs.colorText(x, yPos + 3, fore, text2) - x = nil -end - ---Показ инвентаря -local function showInventory(x, y, page, currentItem) - obj["SellItems"] = nil - obj["SellButtons"] = nil - - local widthOfItemInfoPanel = 26 - local width = math.floor((xSize - widthOfItemInfoPanel - 4) / (widthOfOneItemElement)) - local height = math.floor((ySize - 8) / (heightOfOneItemElement)) - local countOfItems = #massivWithProfile.inventory - local countOfItemsOnOnePage = width * height - local countOfPages = math.ceil(countOfItems / countOfItemsOnOnePage) - local widthOfAllElements = width * widthOfOneItemElement - local heightOfAllElements = height * heightOfOneItemElement - - --Очищаем фоном - ecs.square(x, y, widthOfAllElements, heightOfAllElements, colors.background) - - --Рисуем айтемы - local textColor, borderColor, itemCounter, xPos, yPos = nil, nil, 1 + page * width * height - width * height, x, y - for j = 1, height do - xPos = x - for i = 1, width do - --Если такой предмет вообще существует - if massivWithProfile.inventory[itemCounter] then - --Делаем цвет рамки - if itemCounter == currentItem then - borderColor = colors.inventoryBorderSelect - textColor = colors.inventoryBorderSelectText - else - local cyka = false - if j % 2 == 0 then - if i % 2 ~= 0 then - cyka = true - end - else - if i % 2 == 0 then - cyka = true - end - end - - if cyka then - borderColor = colors.inventoryBorder - else - borderColor = colors.inventoryBorder - 0x111111 - end - textColor = colors.inventoryText - end - - --Рисуем итем - drawItem(xPos, yPos, borderColor, textColor, massivWithProfile.inventory[itemCounter].label, massivWithProfile.inventory[itemCounter].count) - - newObj("SellItems", itemCounter, xPos, yPos, xPos + widthOfOneItemElement - 1, yPos + heightOfOneItemElement - 1) - else - break - end - - itemCounter = itemCounter + 1 - - xPos = xPos + widthOfOneItemElement - end - yPos = yPos + heightOfOneItemElement - end - - --Рисуем инфу о кнкретном айтеме - xPos = x + widthOfAllElements + 2 - yPos = y - widthOfItemInfoPanel = xSize - xPos - 1 - - --Рамку рисуем - ecs.square(xPos, yPos, widthOfItemInfoPanel, ySize - 5, colors.inventoryBorder) - yPos = yPos + 1 - xPos = xPos + 2 - - --Инфа о блоке - local currentRarity = "Common" - if adminShop[massivWithProfile.inventory[currentItem].id] then - if adminShop[massivWithProfile.inventory[currentItem].id][massivWithProfile.inventory[currentItem].data] then - currentRarity = adminShop[massivWithProfile.inventory[currentItem].id][massivWithProfile.inventory[currentItem].data].rarity - end - end - ecs.colorText(xPos, yPos, colors.inventoryText, massivWithProfile.inventory[currentItem].label); yPos = yPos + 1 - ecs.colorText(xPos, yPos, colors.rarity[currentRarity], currentRarity); yPos = yPos + 2 - ecs.colorText(xPos, yPos, colors.inventoryTextDarker, "ID: " .. massivWithProfile.inventory[currentItem].id); yPos = yPos + 1 - ecs.colorText(xPos, yPos, colors.inventoryTextDarker, "Цвет: " .. massivWithProfile.inventory[currentItem].data); yPos = yPos + 1 - ecs.colorText(xPos, yPos, colors.inventoryTextDarker, "Количество: " .. massivWithProfile.inventory[currentItem].count); yPos = yPos + 1 - - --Твой бабос - yPos = yPos + 1 - ecs.colorText(xPos, yPos, colors.inventoryText, "Ваш капитал:"); yPos = yPos + 1 - ecs.colorText(xPos, yPos, colors.inventoryTextDarker, massivWithProfile.money .. moneySymbol); yPos = yPos + 1 - - --Цена админов - yPos = yPos + 1 - local adminPrice = "Отсутствует" - if adminShop[massivWithProfile.inventory[currentItem].id] then - if adminShop[massivWithProfile.inventory[currentItem].id][massivWithProfile.inventory[currentItem].data] then - adminPrice = fixMoney(adminShop[massivWithProfile.inventory[currentItem].id][massivWithProfile.inventory[currentItem].data].price * adminSellMultiplyer) - end - end - ecs.colorText(xPos, yPos, colors.inventoryText, "Цена у админов:"); yPos = yPos + 1 - ecs.colorText(xPos, yPos, colors.inventoryTextDarker, tostring(adminPrice)..moneySymbol) - - --Цена на ТП - yPos = yPos + 2 - local success, price, count = getInfoAboutItemOnMarket(massivWithProfile.inventory[currentItem].id, massivWithProfile.inventory[currentItem].data) - ecs.colorText(xPos, yPos, colors.inventoryText, "Цена на Торговой Площадке:"); yPos = yPos + 1 - if success then - ecs.colorText(xPos, yPos, colors.inventoryTextDarker, "Продается " .. prettyItemCount(count) .. " штук"); yPos = yPos + 1 - ecs.colorText(xPos, yPos, colors.inventoryTextDarker, "Цена стартует от " .. prettyItemCount(price) .. moneySymbol); yPos = yPos + 1 - else - ecs.colorText(xPos, yPos, colors.inventoryTextDarker, "Отсутствует"); yPos = yPos + 1 - end - - --Кнопы - xPos = xPos - 2 - yPos = ySize - 3 - local x1, y1, x2, y2, name - name = "Продать игрокам"; x1, y1, x2, y2 = ecs.drawButton(xPos, yPos, widthOfItemInfoPanel, 3, name, colors.sellButtonColor, colors.sellButtonTextColor); newObj("SellButtons", name, x1, y1, x2, y2, widthOfItemInfoPanel); yPos = yPos - 3 - if adminPrice ~= "Отсутствует" then - name = "Продать админам"; x1, y1, x2, y2 = ecs.drawButton(xPos, yPos, widthOfItemInfoPanel, 3, name, 0x66b6ff, colors.sellButtonTextColor); newObj("SellButtons", name, x1, y1, x2, y2, widthOfItemInfoPanel); yPos = yPos - 3 - end - name = "Пополнить инвентарь"; x1, y1, x2, y2 = ecs.drawButton(xPos, yPos, widthOfItemInfoPanel, 3, name, 0x99dbff, colors.sellButtonTextColor); newObj("SellButtons", name, x1, y1, x2, y2, widthOfItemInfoPanel); yPos = yPos - 3 - - --Перелистывалки - local stro4ka = tostring(page) .. " из " .. tostring(countOfPages) - local sStro4ka = unicode.len(stro4ka) + 2 - xPos = xPos - sStro4ka - 16 - yPos = ySize - 3 - name = "<"; x1, y1, x2, y2 = ecs.drawButton(xPos, yPos, 7, 3, name, colors.sellButtonColor, colors.sellButtonTextColor); newObj("SellButtons", name, x1, y1, x2, y2, 7); xPos = xPos + 7 - ecs.square(xPos, yPos, sStro4ka, 3, colors.inventoryBorder) - ecs.colorText(xPos + 1, yPos + 1, 0x000000, stro4ka); xPos = xPos + sStro4ka - name = ">"; x1, y1, x2, y2 = ecs.drawButton(xPos, yPos, 7, 3, name, colors.sellButtonColor, colors.sellButtonTextColor); newObj("SellButtons", name, x1, y1, x2, y2, 7) - - return countOfPages -end - -local function sell() - - --Если в инвентаре ни хуя нет, то сасируй - if #massivWithProfile.inventory == 0 then - ecs.centerText("xy", 0, "Ваш инвентарь пуст.") - return - end - - --Показываем инвентарь - local xInventory, yInventory, currentPage, currentItem = 3, 5, 1, 1 - local countOfPages - countOfPages = showInventory(xInventory, yInventory, currentPage, currentItem) - - while true do - local e = {event.pull()} - if e[1] == "touch" then - - for key in pairs(obj["SellItems"])do - if ecs.clickedAtArea(e[3], e[4], obj["SellItems"][key][1], obj["SellItems"][key][2], obj["SellItems"][key][3], obj["SellItems"][key][4]) then - currentItem = key - showInventory(xInventory, yInventory, currentPage, currentItem) - break - end - end - - for key in pairs(obj["SellButtons"])do - if ecs.clickedAtArea(e[3], e[4], obj["SellButtons"][key][1], obj["SellButtons"][key][2], obj["SellButtons"][key][3], obj["SellButtons"][key][4]) then - ecs.drawButton(obj["SellButtons"][key][1], obj["SellButtons"][key][2], obj["SellButtons"][key][5], 3, key, ecs.colors.green, 0xffffff) - os.sleep(0.3) - - if key == ">" then - if currentPage < countOfPages then currentPage = currentPage + 1 end - - elseif key == "<" then - if currentPage > 1 then currentPage = currentPage - 1 end - - elseif key == "Пополнить инвентарь" then - ecs.error("Пихай предметы в сундук и жми ок, епта!") - local addedCount = addToInventoryFromChest() - ecs.error("Добавлено "..addedCount.." предметов.") - - elseif key == "Продать админам" then - local maxToSell = massivWithProfile.inventory[currentItem].count - local data = ecs.universalWindow("auto", "auto", 40, 0x444444, true, {"EmptyLine"}, {"CenterText", 0xffffff, "Сколько продаем?"}, {"EmptyLine"}, {"Slider", 0xffffff, 0x33db80, 1, maxToSell, math.floor(maxToSell / 2), "", " шт."}, {"EmptyLine"}, {"Button", {0x33db80, 0xffffff, "Продать"}}) - local count = data[1] - if count then - local money = sellToAdmins(currentItem, count) - ecs.universalWindow("auto", "auto", 40, 0x444444, true, {"EmptyLine"}, {"CenterText", 0xffffff, "Успешно продано!"}, {"CenterText", 0xffffff, "Ты заработал "..money..moneySymbol}, {"EmptyLine"}, {"Button", {0x33db80, 0xffffff, "Ok"}}) - else - ecs.error("Ошибка при продаже! Дебажь!") - end - - elseif key == "Продать игрокам" then - local maxToSell = massivWithProfile.inventory[currentItem].count - local data = ecs.universalWindow("auto", "auto", 36, 0x444444, true, {"EmptyLine"}, {"CenterText", 0xffffff, "Продать игрокам"}, {"EmptyLine"}, {"Input", 0xffffff, 0x33db80, "Цена за штуку"}, {"EmptyLine"}, {"CenterText", 0xffffff, "Количество:"}, {"Slider", 0xffffff, 0x33db80, 1, maxToSell, math.floor(maxToSell / 2), "", " шт."}, {"EmptyLine"}, {"CenterText", 0xffffff, "При каждой продаже с вас"}, {"CenterText", 0xffffff, "взымается комиссия в 4%"}, {"EmptyLine"}, {"Button", {0x33db80, 0xffffff, "Продать"}}) - local price, count = tonumber(data[1]), data[2] - if price then - sellToPlayers(currentItem, count, price, massivWithProfile.nickname) - ecs.universalWindow("auto", "auto", 36, 0x444444, true, {"EmptyLine"}, {"CenterText", 0xffffff, "Ваш предмет выставлен на продажу!"}, {"EmptyLine"}, {"Button", {0x33db80, 0xffffff, "Ok"}}) - else - ecs.error("Ошибка! Неверно указана цена продажи!") - end - end - - countOfPages = showInventory(xInventory, yInventory, currentPage, currentItem) - - break - end - end - - -- for key in pairs(obj["TopButtons"])do - -- if ecs.clickedAtArea(e[3], e[4], obj["TopButtons"][key][1], obj["TopButtons"][key][2], obj["TopButtons"][key][3], obj["TopButtons"][key][4]) then - -- currentMode = key - -- return - -- end - -- end - elseif e[1] == "key_down" then - if e[4] >= 2 and e[4] <= 5 then - --ecs.error("afae") - currentMode = e[4] - 1 - return - end - end - end -end - ---Купить указанное количество указанного предмета у указанного продавца -local function buyFromSeller(id, data, sellerNumber, count) - --Считаем, сколько бабок будет у нас в обиходе - local moneyToWork = count * market[id][data][sellerNumber].price - --Считаем, сколько админы наварят с этого обихода - local moneyForAdmins = round(moneyToWork * comissionMultiplyer, 2) - --Отнимаем бабки у нас с учетом навара админов - massivWithProfile.money = massivWithProfile.money - (moneyToWork + moneyForAdmins) - --Загружаем профиль продавца - local massivWithSellerProfile = loadUser(market[id][data][sellerNumber].nickname) - --Добавляем бабки продавцу - massivWithSellerProfile.money = massivWithSellerProfile.money + comission(moneyToWork) - --Добавляем бабки админам - addMoneyToAdmins(moneyForAdmins) - --Добавляем предметы нам - addItemToInventory(id, data, market[id][data].label, count) - --Удаляем указанное количество предметов с торговой площадки - market[id][data][sellerNumber].count = market[id][data][sellerNumber].count - count - --Сохраняем в лог данные о трансакции - log("Игрок " .. massivWithProfile.nickname .. " приобрел " .. count .. " штук товара \"" .. market[id][data].label .. " (" .. id .. " " .. data .. ")\" у игрока " .. market[id][data][sellerNumber].nickname .. " по цене " .. market[id][data][sellerNumber].price .. moneySymbol .. " за штуку. Сумма трансакции составляет " .. moneyToWork .. moneySymbol .. ", администрация магазина получила " .. moneyForAdmins .. moneySymbol) - --Если количество предметов стало 0, то удалить запись продавца об этом предмете - if market[id][data][sellerNumber].count <= 0 then table.remove(market[id][data], sellerNumber) end - --Если не существует более продавцов данной Даты, то удалить запись о дате - if #market[id][data] <= 0 then market[id] = nil end - --Сохраняем базу данных торговой площадки - saveMarket() - --Сохраняем свой профиль - saveUser(massivWithProfile) - --Сохраняем профиль продавца - saveUser(massivWithSellerProfile) -end - ---Окно покупки -local function buy() - --Если ТП в данный момент пуста, и ничего на ней не продается - - --ecs.error("#market = "..#market) - - -- if #market == 0 then - -- gpu.setForeground(0xFFFFFF) - -- ecs.centerText("x", math.floor(ySize / 2), "Торговая Площадка в данный момент пуста.") - -- ecs.centerText("x", math.floor(ySize / 2) + 1, "Вы можете разместить свое объявление о продаже выше.") - -- end - - local countOfItemsOfMarketToShop = math.floor((ySize - 12) / 4) - local itemOfMarketToShow = 1 - local filteredMakretArray = {} - local itemMarketArray = {} - local currentFilter - local marketSellersList = false - - local currentID, currentData, currentSeller - - local function filter(makretFilter) - filteredMakretArray = {} - - local success, price, count, nickname, label - for id in pairs(market) do - for data in pairs(market[id]) do - - success, price, count, nickname, label = getInfoAboutItemOnMarket(id, data) - - if makretFilter then - if string.find(string.lower(id), string.lower(makretFilter)) then - table.insert(filteredMakretArray, {["id"] = id, ["data"] = data, ["count"] = count, ["price"] = price, ["label"] = label}) - end - else - table.insert(filteredMakretArray, {["id"] = id, ["data"] = data, ["count"] = count, ["price"] = price, ["label"] = label}) - end - - end - end - end - - local function getItemSellers(id, data) - itemMarketArray = {} - for i = 1, #market[id][data] do - table.insert(itemMarketArray, {["nickname"] = market[id][data][i].nickname, ["count"] = market[id][data][i].count, ["price"] = market[id][data][i].price}) - end - end - - local xName, xCountOrSeller, xPrice = 6, math.floor(xSize * 3/7), math.floor(xSize * 4/6) - - local function infoPanel(yPos) - - local width = 40 - local xPos = math.floor(xSize / 2 - width / 2) - - if not marketSellersList then - ecs.border(xPos, yPos, width, 3, 0x262626, 0xFFFFFF) - gpu.set(xPos + 2, yPos + 1, "Поиск по предметам") - - yPos = yPos + 4 - end - - local background, foreground = ecs.colors.blue, 0xFFFFFF - ecs.square(4, yPos, xSize - 7, 1, background) - ecs.colorText(xName, yPos, foreground, (function () if marketSellersList then return "ПРОДАВЕЦ" else return "ПРЕДМЕТ" end end)()) - ecs.colorText(xCountOrSeller, yPos, foreground, "КОЛИЧЕСТВО") - ecs.colorText(xPrice, yPos, foreground, "ЦЕНА") - - yPos = yPos + 2 - - return yPos - end - - local function showItemsList() - - obj["BuyButtons"] = nil - obj["BuyItems"] = nil - - local xPos, yPos = 4, 5 - - ecs.square(1, yPos, xSize, ySize - yPos, 0x262626) - - if marketSellersList then - - gpu.setForeground(0xFFFFFF) - ecs.centerText("x", yPos, "Список продавцов предмета \"" .. currentID .. " " .. currentData .. "\"") - yPos = yPos + 2 - - yPos = infoPanel(yPos) - - countOfItemsOfMarketToShop = math.floor((ySize - yPos - 1) / 4) - - ecs.srollBar(xSize - 1, yPos, 2, countOfItemsOfMarketToShop * 4, #itemMarketArray, itemOfMarketToShow, 0xFFFFFF, ecs.colors.blue) - - for i = itemOfMarketToShow, (itemOfMarketToShow + countOfItemsOfMarketToShop - 1) do - if itemMarketArray[i] then - ecs.square(xPos, yPos, xSize - 7, 3, 0xFFFFFF) - ecs.colorText(xPos + 2, yPos + 1, 0x000000, itemMarketArray[i].nickname ) - gpu.set(xCountOrSeller, yPos + 1, tostring(itemMarketArray[i].count) .. " шт.") - gpu.set(xPrice, yPos + 1, tostring(itemMarketArray[i].price) .. moneySymbol .. " за шт.") - - if itemMarketArray[i].price > massivWithProfile.money or itemMarketArray[i].nickname == massivWithProfile.nickname then - ecs.drawAdaptiveButton(xSize - 13, yPos, 2, 1, "Купить", 0xBBBBBB, 0xFFFFFF) - else - newObj("BuyButtons", i, ecs.drawAdaptiveButton(xSize - 13, yPos, 2, 1, "Купить", 0x66b6ff, 0xFFFFFF)) - end - - yPos = yPos + 4 - end - end - - else - - yPos = infoPanel(yPos) - - countOfItemsOfMarketToShop = math.floor((ySize - yPos - 1) / 4) - - ecs.srollBar(xSize - 1, yPos, 2, countOfItemsOfMarketToShop * 4, #filteredMakretArray, itemOfMarketToShow, 0xFFFFFF, ecs.colors.blue) - - for i = itemOfMarketToShow, (itemOfMarketToShow + countOfItemsOfMarketToShop - 1) do - if filteredMakretArray[i] then - ecs.square(xPos, yPos, xSize - 7, 3, 0xFFFFFF) - ecs.colorText(xPos + 2, yPos + 1, 0x000000, filteredMakretArray[i].label) - gpu.set(xCountOrSeller, yPos + 1, tostring(filteredMakretArray[i].count) .. " шт.") - gpu.set(xPrice, yPos + 1, "От " .. tostring(filteredMakretArray[i].price) .. moneySymbol .. " за шт.") - - newObj("BuyItems", i, xPos, yPos, xPos + xSize - 7 , yPos + 2) - - yPos = yPos + 4 - end - end - end - - end - - filter(currentFilter) - showItemsList() - - while true do - local e = {event.pull()} - - if e[1] == "touch" then - - --Клик на конкретный айтем - if obj["BuyItems"] then - for key in pairs(obj["BuyItems"]) do - if ecs.clickedAtArea(e[3], e[4], obj["BuyItems"][key][1], obj["BuyItems"][key][2], obj["BuyItems"][key][3], obj["BuyItems"][key][4]) then - ecs.square(obj["BuyItems"][key][1], obj["BuyItems"][key][2], obj["BuyItems"][key][3] - obj["BuyItems"][key][1], 3, ecs.colors.blue) - os.sleep(0.2) - --Рисуем - currentID = filteredMakretArray[key].id - currentData = filteredMakretArray[key].data - - marketSellersList = true - getItemSellers(filteredMakretArray[key].id, filteredMakretArray[key].data) - itemOfMarketToShow = 1 - showItemsList() - break - end - end - end - - --Клики на кнопочки "Купить" - if obj["BuyButtons"] then - for key in pairs(obj["BuyButtons"]) do - if ecs.clickedAtArea(e[3], e[4], obj["BuyButtons"][key][1], obj["BuyButtons"][key][2], obj["BuyButtons"][key][3], obj["BuyButtons"][key][4]) then - ecs.drawAdaptiveButton(obj["BuyButtons"][key][1], obj["BuyButtons"][key][2], 2, 1, "Купить", 0xFF4940, 0xFFFFFF) - - local skokaMozhnaKupit = math.min(itemMarketArray[key].count, math.floor(massivWithProfile.money / (itemMarketArray[key].price + round(itemMarketArray[key].price * comissionMultiplyer)))) - - local text = "Сводка по покупке: вы можете купить максимум " .. skokaMozhnaKupit .. " штук. Правила пользовательского соглашения: нажимая кнопку \"Купить\", вы получаете указанное количество предметов по оптимально подобранной цене. Система автоматически найдет наиболее выгодные лоты и перечислит ваши деньги продавцам. Затем указанное количество предметов будет немедленно передано вам в цифровой инвентарь. Автор программы не несет ответственности за утерю наличности из-за любых внешних воздействий на компьютер. Вы сами решаете, доверять подобным сервисам или нет." - - local data = ecs.universalWindow("auto", "auto", 40, 0xDDDDDD, true, {"EmptyLine"}, {"CenterText", 0x262626, "Сколько вы желаете купить?"}, {"EmptyLine"}, {"Slider", 0x262626, 0x880000, 1, skokaMozhnaKupit, 1, "", " шт."}, {"EmptyLine"}, {"TextField", 6, 0xFFFFFF, 0x262626, 0xBBBBBB, ecs.colors.blue, text}, {"EmptyLine"}, {"Switch", 0x3366CC, 0xffffff, 0x262626, "С условиями выше согласен", true}, {"EmptyLine"}, {"Button", {0x33db80, 0xffffff, "Купить"}}) - - if not data[2] then - ecs.universalWindow("auto", "auto", 40, 0xDDDDDD, true, {"EmptyLine"}, {"CenterText", 0x262626, "Для покупки необходимо принять"}, {"CenterText", 0x262626, "условия пользовательского соглашения."}, {"EmptyLine"}, {"Button", {0x33db80, 0xffffff, "OK"}}) - else - buyFromSeller(currentID, currentData, key, data[1]) - end - - --Рефрешим список айтемов ТП - marketSellersList = false - filter(currentFilter) - itemOfMarketToShow = 1 - showItemsList() - - break - end - end - end - - elseif e[1] == "scroll" then - if not marketSellersList then - if e[5] == 1 then - if itemOfMarketToShow > 1 then itemOfMarketToShow = itemOfMarketToShow - 1; showItemsList() end - else - if itemOfMarketToShow < #filteredMakretArray then itemOfMarketToShow = itemOfMarketToShow + 1; showItemsList() end - end - else - if e[5] == 1 then - if itemOfMarketToShow > 1 then itemOfMarketToShow = itemOfMarketToShow - 1; showItemsList() end - else - if itemOfMarketToShow < #itemMarketArray then itemOfMarketToShow = itemOfMarketToShow + 1; showItemsList() end - end - end - elseif e[1] == "key_down" then - if e[4] >= 2 and e[4] <= 5 then - currentMode = e[4] - 1 - return - end - end - end -end - -local function main() - --Рисуем топбар - ecs.drawTopBar(1, 1, xSize, currentMode, colors.topbar, colors.topbarText, {"Главная", "🏠"}, {"Купить", "⟱"}, {"Продать", "⟰"}, {"Лотерея", "☯"}, {"Мой профиль", moneySymbol}) - --Рисуем данные о юзере справа вверху - local text = "§f" .. massivWithProfile.nickname .. "§7, " .. massivWithProfile.money .. moneySymbol - ecs.smartText(xSize - unicode.len(text) + 3, 2, text) - --Рисуем серый фон - ecs.square(1, 4, xSize, ySize - 3, colors.background) -end - ------------------------------------------- Программа ----------------------------------------------------------------- - ---Очищаем экран -ecs.prepareToExit() ---Создание папок, если их нет -init() ---Загрузка файла торговой площадки ---loadMarket() ---Загрузка файла магазина админов -loadAdminShop() - -massivWithProfile = loadUser("IT") - -while true do - main() - - if currentMode == 1 then - currentMode = 2 - --about() - elseif currentMode == 2 then - buy() - elseif currentMode == 3 then - sell() - elseif currentMode == 4 then - currentMode = 2 - --fortune() - else - currentMode = 2 - --user() - end -end - ------------------------------------------- Выход ----------------------------------------------------------------- - - - - - - - - diff --git a/Beta/Tetris.lua b/Beta/Tetris.lua deleted file mode 100644 index ae0d0f51..00000000 --- a/Beta/Tetris.lua +++ /dev/null @@ -1,264 +0,0 @@ - - - --------------------------------------------- Библиотеки ------------------------------------------------------------- - -local component = require("component") -local colorlib = require("colorlib") -local gpu = component.gpu - -local tetris = {} - --------------------------------------------- Переменные ------------------------------------------------------------- - -tetris.screen = { - main = { - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, - {0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, - {0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, - {0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, - {0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, - {0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, - {0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - }, - mini = { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - }, - score = 538, - highScore = 1000, - speed = 1, - level = 1, -} - -local colors = { - tetrisColor = 0xFF5555, - screen = 0xCCDBBF, - pixel = 0x000000, - button = 0xFFFF00, -} - -local function calculateBrightness(color1, brightness) - local color - if brightness < 0 then color = 0x000000 else color = 0xFFFFFF end - brightness = math.abs(brightness) - return colorlib.alphaBlend(color1, color, brightness) -end - -local function recalculateColors() - --Всякие тени, света для корпуса - colors.light1 = calculateBrightness(colors.tetrisColor, 0xCC) - colors.light2 = calculateBrightness(colors.tetrisColor, 0xAA) - colors.light3 = calculateBrightness(colors.tetrisColor, 0x55) - colors.shadow1 = calculateBrightness(colors.tetrisColor, -(0xCC)) - colors.shadow2 = calculateBrightness(colors.tetrisColor, -(0xAA)) - colors.shadow3 = calculateBrightness(colors.tetrisColor, -(0x77)) - --Для кнопочек - if colors.button > 0x777777 then - colors.buttonText = calculateBrightness(colors.button, -(0x77)) - else - colors.buttonText = calculateBrightness(colors.button, 0x77) - end -end - -local sizes = {} -sizes.xScreenOffset = 4 -sizes.yScreenOffset = 3 - --------------------------------------------- Функции ------------------------------------------------------------- - -function tetris.recalculateSizes() - sizes.widthOfScreen = #tetris.screen.main[1] * 2 + (function() if tetris.showInfoPanel then return 10 else return 0 end end)() - sizes.heightOfScreen = #tetris.screen.main -end - -function tetris.generateScreenArray(width, height) - tetris.screen.main = {} - for j = 1, height do - tetris.screen.main[j] = {} - for i = 1, width do - tetris.screen.main[j][i] = 0 - end - end -end - -function tetris.drawOnlyMainScreen() - local xPos, yPos = tetris.xScreen, tetris.yScreen - for j = 1, #tetris.screen.main do - xPos = tetris.xScreen - for i = 1, #tetris.screen.main[j] do - if tetris.screen.main[j][i] == 1 then - gpu.set(xPos, yPos, "⬛") - else - gpu.set(xPos, yPos, "⬜") - end - - xPos = xPos + 2 - end - yPos = yPos + 1 - end - xPos, yPos = nil, nil -end - -function tetris.drawOnlyMiniScreen(x, y) - local xPos, yPos = x, y - for j = 1, #tetris.screen.mini do - xPos = x - for i = 1, #tetris.screen.mini[j] do - if tetris.screen.mini[j][i] == 1 then - gpu.set(xPos, yPos, "⬛") - else - gpu.set(xPos, yPos, "⬜") - end - - xPos = xPos + 2 - end - yPos = yPos + 1 - end - xPos, yPos = nil, nil -end - -function tetris.getPixel(x, y, whichScreen) - return tetris.screen[whichScreen or "main"][y][x] -end - -function tetris.setPixel(x, y, state, whichScreen) - tetris.screen[whichScreen or "main"][y][x] = state -end - -function tetris.changeColors(caseColor, buttonsColor, screenColor, pixelsColor) - colors.tetrisColor = caseColor or colors.tetrisColor - colors.button = buttonsColor or colors.button - colors.screen = screenColor or colors.screen - colors.pixel = pixelsColor or colors.pixel -end - -function tetris.drawScreen() - local xPos, yPos = tetris.xScreen, tetris.yScreen - --Рисуем квадрат экрана - ecs.square(xPos, yPos, sizes.widthOfScreen, sizes.heightOfScreen, colors.screen) - --Делаем цвет пикселей - gpu.setForeground(colors.pixel) - tetris.drawOnlyMainScreen() - - --Если показывать инфопанель = труе, то показать, хули - if tetris.showInfoPanel then - xPos, yPos = xPos + sizes.widthOfScreen - 9, yPos + 1 - - gpu.set(xPos + 1, yPos, "Score:"); yPos = yPos + 1 - gpu.set(xPos + 2, yPos, tostring(tetris.screen.score)); yPos = yPos + 2 - - gpu.set(xPos, yPos, "HiScore:"); yPos = yPos + 1 - gpu.set(xPos + 1, yPos, tostring(tetris.screen.highScore)); yPos = yPos + 2 - - gpu.set(xPos + 2, yPos, "Next:"); yPos = yPos + 1 - - tetris.drawOnlyMiniScreen(xPos, yPos); yPos = yPos + 5 - - gpu.set(xPos + 1, yPos, "Speed:"); yPos = yPos + 1 - gpu.set(xPos + 3, yPos, tostring(tetris.screen.speed)); yPos = yPos + 2 - - gpu.set(xPos + 1, yPos, "Level:"); yPos = yPos + 1 - gpu.set(xPos + 3, yPos, tostring(tetris.screen.level)); yPos = yPos + 2 - end -end - -function tetris.drawButtons() - local xPos, yPos = tetris.x + math.floor(sizes.caseWidth / 2 - 17), tetris.y + (sizes.heightOfScreen + sizes.yScreenOffset * 2 + 6) + 6 - - ecs.drawButton(xPos, yPos, 6, 3, "⮜", colors.button, colors.buttonText) - xPos = xPos + 12 - ecs.drawButton(xPos, yPos, 6, 3, "⮞", colors.button, colors.buttonText) - xPos = xPos - 6 - yPos = yPos - 3 - ecs.drawButton(xPos, yPos, 6, 3, "⮝", colors.button, colors.buttonText) - yPos = yPos + 3 * 2 - ecs.drawButton(xPos, yPos, 6, 3, "⮟", colors.button, colors.buttonText) - - xPos = xPos + 17 - yPos = yPos - 4 - ecs.square(xPos + 2, yPos, 6, 5, colors.button) - ecs.square(xPos, yPos + 1, 10, 3, colors.button) -end - -function tetris.drawCase() - --Делаем перерасчет размеров экрана - tetris.recalculateSizes() - --Рассчитываем размер корпуса - sizes.xSize, sizes.ySize = gpu.getResolution() - sizes.caseWidth = sizes.widthOfScreen + sizes.xScreenOffset * 2 - sizes.heightOfBottomThing = sizes.ySize - (sizes.heightOfScreen + sizes.yScreenOffset * 2 + 6) - tetris.y + 1 - local yPos = tetris.y - --Рисуем верхнюю штучку - ecs.square(tetris.x + 1, yPos, sizes.caseWidth - 2, 1, colors.light2) - yPos = yPos + 1 - --Рисуем всю штучку под экраном - ecs.square(tetris.x, yPos, sizes.caseWidth, sizes.heightOfScreen + sizes.yScreenOffset * 2 - 1, colors.tetrisColor) - ecs.square(tetris.x + sizes.xScreenOffset - 1, yPos + 1, sizes.widthOfScreen + 2, sizes.heightOfScreen + 2, colors.shadow1) - yPos = yPos + sizes.heightOfScreen + sizes.yScreenOffset * 2 - 1 - --Рисуем кольцевую штучку - ecs.square(tetris.x, yPos, sizes.caseWidth, 1, colors.light2); yPos = yPos + 1 - ecs.square(tetris.x, yPos, sizes.caseWidth, 1, colors.light1); yPos = yPos + 1 - ecs.square(tetris.x, yPos, sizes.caseWidth, 2, colors.tetrisColor); yPos = yPos + 2 - ecs.square(tetris.x, yPos, sizes.caseWidth, 1, colors.shadow1); yPos = yPos + 1 - ecs.square(tetris.x, yPos, sizes.caseWidth, 1, colors.shadow2); yPos = yPos + 1 - --Рисуем под кнопочками - ecs.square(tetris.x, yPos, sizes.caseWidth, sizes.heightOfBottomThing, colors.tetrisColor) -end - -function tetris.draw(x, y, screenResolutionWidth, screenResolutionHeight, showInfoPanel) - --Задаем переменную показа инфопанели - tetris.showInfoPanel = showInfoPanel - --Просчитываем цвета - recalculateColors() - --Создаем массив основного экрана нужной ширины и высоты - tetris.generateScreenArray(screenResolutionWidth, screenResolutionHeight) - --Рисуем корпус устройства - tetris.x, tetris.y = x, y - tetris.drawCase() - --Рисуем экран тетриса - tetris.xScreen, tetris.yScreen = tetris.x + sizes.xScreenOffset, tetris.y + sizes.yScreenOffset - tetris.drawScreen() - --Кнопочки рисуем - tetris.drawButtons() -end - --------------------------------------------- Программа ------------------------------------------------------------- - -ecs.prepareToExit() - -tetris.changeColors(0x008800, 0xFFFF00) -tetris.draw(10, 5, 27, 20, false) -tetris.changeColors(0xFF5555, 0xFFFF00) -tetris.draw(80, 5, 10, 20, true) - - - - - - - - - - - - - - - - diff --git a/Beta/bufferNotOptimized.lua b/Beta/bufferNotOptimized.lua deleted file mode 100644 index 825bf8ec..00000000 --- a/Beta/bufferNotOptimized.lua +++ /dev/null @@ -1,553 +0,0 @@ - --- Адаптивная загрузка необходимых библиотек и компонентов -local libraries = { - ["component"] = "component", - ["unicode"] = "unicode", - ["image"] = "image", - ["colorlib"] = "colorlib", -} - -local components = { - ["gpu"] = "gpu", -} - -for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end -for comp in pairs(components) do if not _G[comp] then _G[comp] = _G.component[components[comp]] end end -libraries, components = nil, nil - -local buffer = {} -local debug = false -local sizeOfPixelData = 3 - -------------------------------------------------- Вспомогательные методы ----------------------------------------------------------------- - ---Формула конвертации индекса массива изображения в абсолютные координаты пикселя изображения -local function convertIndexToCoords(index) - --Приводим индекс к корректному виду (1 = 1, 4 = 2, 7 = 3, 10 = 4, 13 = 5, ...) - index = (index + sizeOfPixelData - 1) / sizeOfPixelData - --Получаем остаток от деления индекса на ширину изображения - local ostatok = index % buffer.screen.width - --Если остаток равен 0, то х равен ширине изображения, а если нет, то х равен остатку - local x = (ostatok == 0) and buffer.screen.width or ostatok - --А теперь как два пальца получаем координату по Y - local y = math.ceil(index / buffer.screen.width) - --Очищаем остаток из оперативки - ostatok = nil - --Возвращаем координаты - return x, y -end - ---Формула конвертации абсолютных координат пикселя изображения в индекс для массива изображения -local function convertCoordsToIndex(x, y) - return (buffer.screen.width * (y - 1) + x) * sizeOfPixelData - sizeOfPixelData + 1 -end - -local function printDebug(line, text) - if debug then - ecs.square(1, line, buffer.screen.width, 1, 0x262626) - ecs.colorText(2, line, 0xFFFFFF, text) - end -end - --- Установить ограниченную зону рисования. Все пиксели, не попадающие в эту зону, будут игнорироваться. -function buffer.setDrawLimit(x, y, width, height) - buffer.drawLimit = { x1 = x, y1 = y, x2 = x + width - 1, y2 = y + height - 1 } -end - --- Удалить ограничение зоны рисования, по умолчанию она будет от 1х1 до координат размера экрана. -function buffer.resetDrawLimit() - buffer.drawLimit = {x1 = 1, y1 = 1, x2 = buffer.screen.width, y2 = buffer.screen.height} -end - --- Создать массив буфера с базовыми переменными и базовыми цветами. Т.е. черный фон, белый текст. -function buffer.start() - buffer.screen = {} - buffer.screen.current = {} - buffer.screen.new = {} - buffer.screen.width, buffer.screen.height = gpu.getResolution() - - buffer.resetDrawLimit() - - for y = 1, buffer.screen.height do - for x = 1, buffer.screen.width do - table.insert(buffer.screen.current, 0x010101) - table.insert(buffer.screen.current, 0xFEFEFE) - table.insert(buffer.screen.current, " ") - - table.insert(buffer.screen.new, 0x010101) - table.insert(buffer.screen.new, 0xFEFEFE) - table.insert(buffer.screen.new, " ") - end - end -end - -------------------------------------------------- Методы отрисовки ----------------------------------------------------------------- - --- Получить информацию о пикселе из буфера -function buffer.get(x, y) - local index = convertCoordsToIndex(x, y) - if x >= buffer.drawLimit.x1 and y >= buffer.drawLimit.y1 and x <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then - return buffer.screen.current[index], buffer.screen.current[index + 1], buffer.screen.current[index + 2] - else - error("Невозможно получить указанные значения, так как указанные координаты лежат за пределами экрана.\n") - end -end - --- Установить пиксель в буфере -function buffer.set(x, y, background, foreground, symbol) - local index = convertCoordsToIndex(x, y) - if x >= buffer.drawLimit.x1 and y >= buffer.drawLimit.y1 and x <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then - buffer.screen.new[index] = background - buffer.screen.new[index + 1] = foreground - buffer.screen.new[index + 2] = symbol - end -end - ---Нарисовать квадрат -function buffer.square(x, y, width, height, background, foreground, symbol, transparency) - local index - if transparency then transparency = transparency * 2.55 end - for j = y, (y + height - 1) do - for i = x, (x + width - 1) do - if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then - index = convertCoordsToIndex(i, j) - if transparency then - buffer.screen.new[index] = colorlib.alphaBlend(buffer.screen.new[index], background, transparency) - buffer.screen.new[index + 1] = colorlib.alphaBlend(buffer.screen.new[index + 1], background, transparency) - else - buffer.screen.new[index] = background - buffer.screen.new[index + 1] = foreground - buffer.screen.new[index + 2] = symbol - end - end - end - end -end - ---Очистка экрана, по сути более короткая запись buffer.square -function buffer.clear(color) - buffer.square(1, 1, buffer.screen.width, buffer.screen.height, color or 0x262626, 0xFFFFFF, " ") -end - ---Заливка области изображения (рекурсивная, говно-метод) -function buffer.fill(x, y, background, foreground, symbol) - - local startBackground, startForeground, startSymbol - - local function doFill(xStart, yStart) - local index = convertCoordsToIndex(xStart, yStart) - - if - buffer.screen.new[index] ~= startBackground or - -- buffer.screen.new[index + 1] ~= startForeground or - -- buffer.screen.new[index + 2] ~= startSymbol or - buffer.screen.new[index] == background - -- buffer.screen.new[index + 1] == foreground or - -- buffer.screen.new[index + 2] == symbol - then - return - end - - --Заливаем в память - if xStart >= buffer.drawLimit.x1 and yStart >= buffer.drawLimit.y1 and xStart <= buffer.drawLimit.x2 and yStart <= buffer.drawLimit.y2 then - buffer.screen.new[index] = background - buffer.screen.new[index + 1] = foreground - buffer.screen.new[index + 2] = symbol - end - - doFill(xStart + 1, yStart) - doFill(xStart - 1, yStart) - doFill(xStart, yStart + 1) - doFill(xStart, yStart - 1) - - iterator = nil - end - - local startIndex = convertCoordsToIndex(x, y) - startBackground = buffer.screen.new[startIndex] - startForeground = buffer.screen.new[startIndex + 1] - startSymbol = buffer.screen.new[startIndex + 2] - - doFill(x, y) -end - ---Нарисовать окружность, алгоритм спизжен с вики -function buffer.circle(xCenter, yCenter, radius, background, foreground, symbol) - --Подфункция вставки точек - local function insertPoints(x, y) - buffer.set(xCenter + x * 2, yCenter + y, background, foreground, symbol) - buffer.set(xCenter + x * 2, yCenter - y, background, foreground, symbol) - buffer.set(xCenter - x * 2, yCenter + y, background, foreground, symbol) - buffer.set(xCenter - x * 2, yCenter - y, background, foreground, symbol) - - buffer.set(xCenter + x * 2 + 1, yCenter + y, background, foreground, symbol) - buffer.set(xCenter + x * 2 + 1, yCenter - y, background, foreground, symbol) - buffer.set(xCenter - x * 2 + 1, yCenter + y, background, foreground, symbol) - buffer.set(xCenter - x * 2 + 1, yCenter - y, background, foreground, symbol) - end - - local x = 0 - local y = radius - local delta = 3 - 2 * radius; - while (x < y) do - insertPoints(x, y); - insertPoints(y, x); - if (delta < 0) then - delta = delta + (4 * x + 6) - else - delta = delta + (4 * (x - y) + 10) - y = y - 1 - end - x = x + 1 - end - - if x == y then insertPoints(x, y) end -end - ---Скопировать область изображения и вернуть ее в виде массива -function buffer.copy(x, y, width, height) - local copyArray = { - ["width"] = width, - ["height"] = height, - } - - if x < 1 or y < 1 or x + width - 1 > buffer.screen.width or y + height - 1 > buffer.screen.height then - errror("Область копирования выходит за пределы экрана.") - end - - local index - for j = y, (y + height - 1) do - for i = x, (x + width - 1) do - index = convertCoordsToIndex(i, j) - table.insert(copyArray, buffer.screen.new[index]) - table.insert(copyArray, buffer.screen.new[index + 1]) - table.insert(copyArray, buffer.screen.new[index + 2]) - end - end - - return copyArray -end - ---Вставить скопированную ранее область изображения -function buffer.paste(x, y, copyArray) - local index, arrayIndex - if not copyArray or #copyArray == 0 then error("Массив области экрана пуст.") end - - for j = y, (y + copyArray.height - 1) do - for i = x, (x + copyArray.width - 1) do - if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then - --Рассчитываем индекс массива основного изображения - index = convertCoordsToIndex(i, j) - --Копипаст формулы, аккуратнее! - --Рассчитываем индекс массива вставочного изображения - arrayIndex = (copyArray.width * ((j - y + 1) - 1) + (i - x + 1)) * sizeOfPixelData - sizeOfPixelData + 1 - --Вставляем данные - buffer.screen.new[index] = copyArray[arrayIndex] - buffer.screen.new[index + 1] = copyArray[arrayIndex + 1] - buffer.screen.new[index + 2] = copyArray[arrayIndex + 2] - end - end - end -end - ---Нарисовать линию, алгоритм спизжен с вики -function buffer.line(x1, y1, x2, y2, background, foreground, symbol) - local deltaX = math.abs(x2 - x1) - local deltaY = math.abs(y2 - y1) - local signX = (x1 < x2) and 1 or -1 - local signY = (y1 < y2) and 1 or -1 - - local errorCyka = deltaX - deltaY - local errorCyka2 - - buffer.set(x2, y2, background, foreground, symbol) - - while(x1 ~= x2 or y1 ~= y2) do - buffer.set(x1, y1, background, foreground, symbol) - - errorCyka2 = errorCyka * 2 - - if (errorCyka2 > -deltaY) then - errorCyka = errorCyka - deltaY - x1 = x1 + signX - end - - if (errorCyka2 < deltaX) then - errorCyka = errorCyka + deltaX - y1 = y1 + signY - end - end -end - --- Отрисовка текста, подстраивающегося под текущий фон -function buffer.text(x, y, color, text, transparency) - local index - if transparency then transparency = transparency * 2.55 end - local sText = unicode.len(text) - for i = 1, sText do - if (x + i - 1) >= buffer.drawLimit.x1 and y >= buffer.drawLimit.y1 and (x + i - 1) <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then - index = convertCoordsToIndex(x + i - 1, y) - buffer.screen.new[index + 1] = not transparency and color or colorlib.alphaBlend(buffer.screen.new[index], color, transparency) - buffer.screen.new[index + 2] = unicode.sub(text, i, i) - end - end -end - --- Отрисовка изображения -function buffer.image(x, y, picture) - if not image then image = require("image") end - local index, imageIndex - for j = y, (y + picture.height - 1) do - for i = x, (x + picture.width - 1) do - if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then - index = convertCoordsToIndex(i, j) - --Копипаст формулы! - imageIndex = (picture.width * ((j - y + 1) - 1) + (i - x + 1)) * 4 - 4 + 1 - - if picture[imageIndex + 2] ~= 0x00 then - buffer.screen.new[index] = colorlib.alphaBlend(buffer.screen.new[index], picture[imageIndex], picture[imageIndex + 2]) - else - buffer.screen.new[index] = picture[imageIndex] - end - buffer.screen.new[index + 1] = picture[imageIndex + 1] - buffer.screen.new[index + 2] = picture[imageIndex + 3] - end - end - end -end - --- Кнопка фиксированных размеров -function buffer.button(x, y, width, height, background, foreground, text) - local textPosX = math.floor(x + width / 2 - unicode.len(text) / 2) - local textPosY = math.floor(y + height / 2) - buffer.square(x, y, width, height, background, 0xFFFFFF, " ") - buffer.text(textPosX, textPosY, foreground, text) - - return x, y, (x + width - 1), (y + height - 1) -end - --- Кнопка, подстраивающаяся под длину текста -function buffer.adaptiveButton(x, y, xOffset, yOffset, background, foreground, text) - local width = xOffset * 2 + unicode.len(text) - local height = yOffset * 2 + 1 - - buffer.square(x, y, width, height, background, 0xFFFFFF, " ") - buffer.text(x + xOffset, y + yOffset, foreground, text) - - return x, y, (x + width - 1), (y + height - 1) -end - --- Вертикальный скролл-бар -function buffer.scrollBar(x, y, width, height, countOfAllElements, currentElement, backColor, frontColor) - local sizeOfScrollBar = math.ceil(1 / countOfAllElements * height) - local displayBarFrom = math.floor(y + height * ((currentElement - 1) / countOfAllElements)) - - buffer.square(x, y, width, height, backColor, 0xFFFFFF, " ") - buffer.square(x, displayBarFrom, width, sizeOfScrollBar, frontColor, 0xFFFFFF, " ") - - sizeOfScrollBar, displayBarFrom = nil, nil -end - --- Отрисовка любого изображения в виде трехмерного массива. Неоптимизированно, зато просто. -function buffer.customImage(x, y, pixels) - x = x - 1 - y = y - 1 - - for i=1, #pixels do - for j=1, #pixels[1] do - if pixels[i][j][3] ~= "#" then - buffer.set(x + j, y + i, pixels[i][j][1], pixels[i][j][2], pixels[i][j][3]) - end - end - end - - return (x + 1), (y + 1), (x + #pixels[1]), (y + #pixels) -end - ---Нарисовать топ-меню, горизонтальная полоска такая с текстами -function buffer.menu(x, y, width, color, selectedObject, ...) - local objects = { ... } - local objectsToReturn = {} - local xPos = x + 2 - local spaceBetween = 2 - buffer.square(x, y, width, 1, color, 0xFFFFFF, " ") - for i = 1, #objects do - if i == selectedObject then - buffer.square(xPos - 1, y, unicode.len(objects[i][1]) + spaceBetween, 1, 0x3366CC, 0xFFFFFF, " ") - buffer.text(xPos, y, 0xFFFFFF, objects[i][1]) - else - buffer.text(xPos, y, objects[i][2], objects[i][1]) - end - objectsToReturn[objects[i][1]] = { xPos, y, xPos + unicode.len(objects[i][1]) - 1, y, i } - xPos = xPos + unicode.len(objects[i][1]) + spaceBetween - end - return objectsToReturn -end - --- Прамоугольная рамочка -function buffer.frame(x, y, width, height, color) - local stringUp = "┌" .. string.rep("─", width - 2) .. "┐" - local stringDown = "└" .. string.rep("─", width - 2) .. "┘" - - buffer.text(x, y, color, stringUp) - buffer.text(x, y + height - 1, color, stringDown) - - local yPos = 1 - for i = 1, (height - 2) do - buffer.text(x, y + yPos, color, "│") - buffer.text(x + width - 1, y + yPos, color, "│") - yPos = yPos + 1 - end -end - --- Кнопка в виде текста в рамке -function buffer.framedButton(x, y, width, height, backColor, buttonColor, text) - buffer.square(x, y, width, height, backColor, buttonColor, " ") - buffer.frame(x, y, width, height, buttonColor) - - x = x + math.floor(width / 2 - unicode.len(text) / 2) - y = y + math.floor(width / 2 - 1) - - buffer.text(x, y, buttonColor, text) -end - -------------------------------------------- Просчет изменений и отрисовка ------------------------------------------------------------------------ - ---Функция рассчитывает изменения и применяет их, возвращая то, что было изменено -function buffer.calculateDifference(index) - local somethingIsChanged = false - - --Если цвет фона на новом экране отличается от цвета фона на текущем, то - if buffer.screen.new[index] ~= buffer.screen.current[index] then - --Присваиваем цвету фона на текущем экране значение цвета фона на новом экране - buffer.screen.current[index] = buffer.screen.new[index] - --Говорим системе, что что-то изменилось - somethingIsChanged = true - end - - index = index + 1 - - --Аналогично для цвета текста - if buffer.screen.new[index] ~= buffer.screen.current[index] then - buffer.screen.current[index] = buffer.screen.new[index] - somethingIsChanged = true - end - - index = index + 1 - - --И для символа - if buffer.screen.new[index] ~= buffer.screen.current[index] then - buffer.screen.current[index] = buffer.screen.new[index] - somethingIsChanged = true - end - - return somethingIsChanged -end - ---Функция группировки изменений и их отрисовки на экран -function buffer.draw(force) - --Необходимые переменные, дабы не создавать их в цикле и не генерировать конструкторы - local somethingIsChanged, index, indexPlus1, indexPlus2, massiv, x, y - --Массив третьего буфера, содержащий в себе измененные пиксели - -- buffer.screen.changes = {} - - --Перебираем содержимое нашего буфера по X и Y - for y = 1, buffer.screen.height do - x = 1 - while x <= buffer.screen.width do - --Получаем индекс массива из координат, уменьшая нагрузку на CPU - index = convertCoordsToIndex(x, y) - indexPlus1 = index + 1 - indexPlus2 = index + 2 - --Получаем изменения и применяем их - somethingIsChanged = buffer.calculateDifference(index) - - --Если хоть что-то изменилось, то начинаем работу - if somethingIsChanged or force then - - gpu.setBackground(buffer.screen.current[index]) - gpu.setForeground(buffer.screen.current[indexPlus1]) - gpu.set(x, y, buffer.screen.current[indexPlus2]) - - --Оптимизация by Krutoy, создаем массив, в который заносим чарсы. Работает быстрее, чем конкатенейт строк - -- massiv = { buffer.screen.current[indexPlus2] } - -- --Загоняем в наш чарс-массив одинаковые пиксели справа, если таковые имеются - -- local iIndex - -- local i = x + 1 - -- while i <= buffer.screen.width do - -- iIndex = convertCoordsToIndex(i, y) - -- if - -- buffer.screen.current[index] == buffer.screen.new[iIndex] and - -- ( - -- buffer.screen.new[iIndex + 2] == " " - -- or - -- buffer.screen.current[indexPlus1] == buffer.screen.new[iIndex + 1] - -- ) - -- then - -- buffer.calculateDifference(iIndex) - -- table.insert(massiv, buffer.screen.current[iIndex + 2]) - -- else - -- break - -- end - - -- i = i + 1 - -- end - - -- --Заполняем третий буфер полученными данными - -- buffer.screen.changes[buffer.screen.current[indexPlus1]] = buffer.screen.changes[buffer.screen.current[indexPlus1]] or {} - -- buffer.screen.changes[buffer.screen.current[indexPlus1]][buffer.screen.current[index]] = buffer.screen.changes[buffer.screen.current[indexPlus1]][buffer.screen.current[index]] or {} - - -- table.insert(buffer.screen.changes[buffer.screen.current[indexPlus1]][buffer.screen.current[index]], index) - -- table.insert(buffer.screen.changes[buffer.screen.current[indexPlus1]][buffer.screen.current[index]], table.concat(massiv)) - - --Смещаемся по иксу вправо - -- x = x + #massiv - 1 - end - - x = x + 1 - end - end - - --Сбрасываем переменные на невозможное значение цвета, чтобы не багнуло - -- index, indexPlus1 = -math.huge, -math.huge - - --Перебираем все цвета текста и фона, выполняя гпу-операции - -- for foreground in pairs(buffer.screen.changes) do - -- if indexPlus1 ~= foreground then gpu.setForeground(foreground); indexPlus1 = foreground end - -- for background in pairs(buffer.screen.changes[foreground]) do - -- if index ~= background then gpu.setBackground(background); index = background end - - -- for i = 1, #buffer.screen.changes[foreground][background], 2 do - -- --Конвертируем указанный индекс в координаты - -- x, y = convertIndexToCoords(buffer.screen.changes[foreground][background][i]) - -- --Выставляем ту самую собранную строку из одинаковых цветов - -- gpu.set(x, y, buffer.screen.changes[foreground][background][i + 1]) - -- end - -- end - -- end - - --Очищаем память, ибо незачем нам хранить третий буфер - -- buffer.screen.changes = {} - -- buffer.screen.changes = nil -end - ------------------------------------------------------------------------------------------------------- - -buffer.start() - ------------------------------------------------------------------------------------------------------- - -return buffer - - - - - - - - - - - - - diff --git a/Beta/calendar.lua b/Beta/calendar.lua deleted file mode 100644 index e87d194d..00000000 --- a/Beta/calendar.lua +++ /dev/null @@ -1,205 +0,0 @@ -local gpu = component.gpu - ---Количество дней в месяцах -local countOfDays = { - 31, - 28, - 31, - 30, - 31, - 30, - 31, - 31, - 30, - 31, - 30, - 31, -} - -local months = { - "Январь", - "Февраль", - "Март", - "Апрель", - "Май", - "Июнь", - "Июль", - "Август", - "Сентябрь", - "Октябрь", - "Ноябрь", - "Декабрь", -} - -local monthDateMove = { - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 3, - 2, - 3, - 2, - 3, -} - -local constants = { - xSpaceBetweenNumbers = 2, - ySpaceBetweenNumbers = 1, - xSpaceBetweenMonths = 4, - ySpaceBetweenMonths = 1, - currentYear = 2015, - currentMonth = 9, - currentDay = 26, - programYear = 2001, - programMonth = 1, - proramDay = 1, - usualDayColor = 0x262626, - weekendColor = 0x880000, - backgroundColor = 0xEEEEEE, - dayNamesColor = 0x888888, - monthsColor = 0xCC0000, - currentDayColor = 0xFFFFFF, -} - -local function visokosniy(year) - if year % 4 == 0 or year % 400 == 0 then return true else return false end -end - -local function drawMonth(x, y, firstDay, countOfDays, year, month) - local xPos, yPos = x, y + 4 - local counter = 1 - local startDrawing = false - local separator = string.rep(" ", 2) - ecs.colorText(x, y, constants.monthsColor, months[month]) - ecs.colorText(x, y + 2, constants.dayNamesColor,"Пн"..separator.."Вт"..separator.."Ср"..separator.."Чт"..separator.."Пт"..separator.."Сб"..separator.."Вс") - for j = 1, 6 do - xPos = x - for i = 1, 7 do - if i < 6 then gpu.setForeground(constants.usualDayColor) else gpu.setForeground(constants.weekendColor) end - if counter == constants.currentDay and year == constants.currentYear and month == constants.currentMonth then ecs.square(xPos-1, yPos, 4, 1, constants.weekendColor); gpu.setForeground(constants.currentDayColor) else gpu.setBackground(constants.backgroundColor) end - if counter > countOfDays then break end - if i >= firstDay then startDrawing = true end - if startDrawing then gpu.set(xPos, yPos, tostring(counter)); counter = counter + 1 end - xPos = xPos + constants.xSpaceBetweenNumbers + 2 - end - yPos = yPos + constants.ySpaceBetweenNumbers + 1 - end -end - -local function getNextDay(day) - if day < 7 then - return (day + 1) - else - return 1 - end -end - ---2001 2007 2018 2029 ---6 11 11 - - -local function calculateYear(year, dayOf1Jan) - local massivGoda = {} - local visokosniy = visokosniy(year) - - local firstDayPosition = dayOf1Jan - - --Получаем количество дней в каждом месяце - for month = 1, 12 do - --Создаем подмассив месяца в массиве года - massivGoda[month] = {} - --Если это февраль - if month == 2 then - --Если год високосный - if visokosniy then - massivGoda[month].countOfDays = 29 - massivGoda[month].firstDayPosition = firstDayPosition - firstDayPosition = getNextDay(firstDayPosition) - --Если не високосный - else - massivGoda[month].countOfDays = 28 - massivGoda[month].firstDayPosition = firstDayPosition - end - --Если не февраль - else - massivGoda[month].countOfDays = countOfDays[month] - massivGoda[month].firstDayPosition = firstDayPosition - for i = 1, monthDateMove[month] do - firstDayPosition = getNextDay(firstDayPosition) - end - end - end - - return massivGoda -end - -local function polu4itDenNedeliPervogoJanvarja(year, debug) - local den = 0 - - local difference = math.abs(year - 1010) - local koli4estvoVisokosnih - - if difference % 4 == 0 then - koli4estvoVisokosnih = difference / 4 - elseif difference % 4 == 1 then - koli4estvoVisokosnih = math.floor(difference / 4) - elseif difference % 4 == 2 then - koli4estvoVisokosnih = math.floor(difference / 4) - elseif difference % 4 == 3 then - koli4estvoVisokosnih = math.floor(difference / 4) + 1 - end - - local sdvig = difference + koli4estvoVisokosnih - - if sdvig % 7 == 0 then - den = 1 - else - den = sdvig % 7 + 1 - end - - if debug then - print("Год: "..year) - print("Разница в годах: "..difference) - print("Кол-во високосных: "..koli4estvoVisokosnih) - print("Сдвиг по дням: "..sdvig) - print("День недели: "..den) - print(" ") - end - - return den -end - -local function drawCalendar(xPos, yPos, year) - --Очищаем экран - ecs.prepareToExit(constants.backgroundColor) - - local janFirst = polu4itDenNedeliPervogoJanvarja(year) - --Получаем массив года - local massivGoda = calculateYear(year, janFirst) - - --Перебираем массив года - for i = 1, #massivGoda do - --Рисуем месяц - drawMonth(xPos, yPos, massivGoda[i].firstDayPosition, massivGoda[i].countOfDays, year, i) - --Корректируем коорды - xPos = xPos + constants.xSpaceBetweenMonths + 27 - if i % 4 == 0 then xPos = 2; yPos = yPos + constants.ySpaceBetweenMonths + 15 end - end -end - - --------------------------------------------------------------------------------------------------------------------- - -ecs.prepareToExit() -drawCalendar(2, 2, 2015) - - - - - - - diff --git a/Beta/colorPaletteCompressed.lua b/Beta/colorPaletteCompressed.lua deleted file mode 100644 index bd88276f..00000000 --- a/Beta/colorPaletteCompressed.lua +++ /dev/null @@ -1,256 +0,0 @@ -[0x00] = 0x000000, -[0x01] = 0x000040, -[0x02] = 0x000080, -[0x03] = 0x0000C0, -[0x04] = 0x002000, -[0x05] = 0x002040, -[0x06] = 0x002080, -[0x07] = 0x0020C0, -[0x08] = 0x004000, -[0x09] = 0x004040, -[0x0A] = 0x004080, -[0x0B] = 0x0040C0, -[0x0C] = 0x006000, -[0x0D] = 0x006040, -[0x0E] = 0x006080, -[0x0F] = 0x0060C0, -[0x10] = 0x008000, -[0x11] = 0x008040, -[0x12] = 0x008080, -[0x13] = 0x0080C0, -[0x14] = 0x00A000, -[0x15] = 0x00A040, -[0x16] = 0x00A080, -[0x17] = 0x00A0C0, -[0x18] = 0x00C000, -[0x19] = 0x00C040, -[0x1A] = 0x00C080, -[0x1B] = 0x00C0C0, -[0x1C] = 0x00E000, -[0x1D] = 0x00E040, -[0x1E] = 0x00E080, -[0x1F] = 0x00E0C0, -[0x20] = 0x200000, -[0x21] = 0x200040, -[0x22] = 0x200080, -[0x23] = 0x2000C0, -[0x24] = 0x202000, -[0x25] = 0x202040, -[0x26] = 0x202080, -[0x27] = 0x2020C0, -[0x28] = 0x204000, -[0x29] = 0x204040, -[0x2A] = 0x204080, -[0x2B] = 0x2040C0, -[0x2C] = 0x206000, -[0x2D] = 0x206040, -[0x2E] = 0x206080, -[0x2F] = 0x2060C0, -[0x30] = 0x208000, -[0x31] = 0x208040, -[0x32] = 0x208080, -[0x33] = 0x2080C0, -[0x34] = 0x20A000, -[0x35] = 0x20A040, -[0x36] = 0x20A080, -[0x37] = 0x20A0C0, -[0x38] = 0x20C000, -[0x39] = 0x20C040, -[0x3A] = 0x20C080, -[0x3B] = 0x20C0C0, -[0x3C] = 0x20E000, -[0x3D] = 0x20E040, -[0x3E] = 0x20E080, -[0x3F] = 0x20E0C0, -[0x40] = 0x400000, -[0x41] = 0x400040, -[0x42] = 0x400080, -[0x43] = 0x4000C0, -[0x44] = 0x402000, -[0x45] = 0x402040, -[0x46] = 0x402080, -[0x47] = 0x4020C0, -[0x48] = 0x404000, -[0x49] = 0x404040, -[0x4A] = 0x404080, -[0x4B] = 0x4040C0, -[0x4C] = 0x406000, -[0x4D] = 0x406040, -[0x4E] = 0x406080, -[0x4F] = 0x4060C0, -[0x50] = 0x408000, -[0x51] = 0x408040, -[0x52] = 0x408080, -[0x53] = 0x4080C0, -[0x54] = 0x40A000, -[0x55] = 0x40A040, -[0x56] = 0x40A080, -[0x57] = 0x40A0C0, -[0x58] = 0x40C000, -[0x59] = 0x40C040, -[0x5A] = 0x40C080, -[0x5B] = 0x40C0C0, -[0x5C] = 0x40E000, -[0x5D] = 0x40E040, -[0x5E] = 0x40E080, -[0x5F] = 0x40E0C0, -[0x60] = 0x600000, -[0x61] = 0x600040, -[0x62] = 0x600080, -[0x63] = 0x6000C0, -[0x64] = 0x602000, -[0x65] = 0x602040, -[0x66] = 0x602080, -[0x67] = 0x6020C0, -[0x68] = 0x604000, -[0x69] = 0x604040, -[0x6A] = 0x604080, -[0x6B] = 0x6040C0, -[0x6C] = 0x606000, -[0x6D] = 0x606040, -[0x6E] = 0x606080, -[0x6F] = 0x6060C0, -[0x70] = 0x608000, -[0x71] = 0x608040, -[0x72] = 0x608080, -[0x73] = 0x6080C0, -[0x74] = 0x60A000, -[0x75] = 0x60A040, -[0x76] = 0x60A080, -[0x77] = 0x60A0C0, -[0x78] = 0x60C000, -[0x79] = 0x60C040, -[0x7A] = 0x60C080, -[0x7B] = 0x60C0C0, -[0x7C] = 0x60E000, -[0x7D] = 0x60E040, -[0x7E] = 0x60E080, -[0x7F] = 0x60E0C0, -[0x80] = 0x800000, -[0x81] = 0x800040, -[0x82] = 0x800080, -[0x83] = 0x8000C0, -[0x84] = 0x802000, -[0x85] = 0x802040, -[0x86] = 0x802080, -[0x87] = 0x8020C0, -[0x88] = 0x804000, -[0x89] = 0x804040, -[0x8A] = 0x804080, -[0x8B] = 0x8040C0, -[0x8C] = 0x806000, -[0x8D] = 0x806040, -[0x8E] = 0x806080, -[0x8F] = 0x8060C0, -[0x90] = 0x808000, -[0x91] = 0x808040, -[0x92] = 0x808080, -[0x93] = 0x8080C0, -[0x94] = 0x80A000, -[0x95] = 0x80A040, -[0x96] = 0x80A080, -[0x97] = 0x80A0C0, -[0x98] = 0x80C000, -[0x99] = 0x80C040, -[0x9A] = 0x80C080, -[0x9B] = 0x80C0C0, -[0x9C] = 0x80E000, -[0x9D] = 0x80E040, -[0x9E] = 0x80E080, -[0x9F] = 0x80E0C0, -[0xA0] = 0xA00000, -[0xA1] = 0xA00040, -[0xA2] = 0xA00080, -[0xA3] = 0xA000C0, -[0xA4] = 0xA02000, -[0xA5] = 0xA02040, -[0xA6] = 0xA02080, -[0xA7] = 0xA020C0, -[0xA8] = 0xA04000, -[0xA9] = 0xA04040, -[0xAA] = 0xA04080, -[0xAB] = 0xA040C0, -[0xAC] = 0xA06000, -[0xAD] = 0xA06040, -[0xAE] = 0xA06080, -[0xAF] = 0xA060C0, -[0xB0] = 0xA08000, -[0xB1] = 0xA08040, -[0xB2] = 0xA08080, -[0xB3] = 0xA080C0, -[0xB4] = 0xA0A000, -[0xB5] = 0xA0A040, -[0xB6] = 0xA0A080, -[0xB7] = 0xA0A0C0, -[0xB8] = 0xA0C000, -[0xB9] = 0xA0C040, -[0xBA] = 0xA0C080, -[0xBB] = 0xA0C0C0, -[0xBC] = 0xA0E000, -[0xBD] = 0xA0E040, -[0xBE] = 0xA0E080, -[0xBF] = 0xA0E0C0, -[0xC0] = 0xC00000, -[0xC1] = 0xC00040, -[0xC2] = 0xC00080, -[0xC3] = 0xC000C0, -[0xC4] = 0xC02000, -[0xC5] = 0xC02040, -[0xC6] = 0xC02080, -[0xC7] = 0xC020C0, -[0xC8] = 0xC04000, -[0xC9] = 0xC04040, -[0xCA] = 0xC04080, -[0xCB] = 0xC040C0, -[0xCC] = 0xC06000, -[0xCD] = 0xC06040, -[0xCE] = 0xC06080, -[0xCF] = 0xC060C0, -[0xD0] = 0xC08000, -[0xD1] = 0xC08040, -[0xD2] = 0xC08080, -[0xD3] = 0xC080C0, -[0xD4] = 0xC0A000, -[0xD5] = 0xC0A040, -[0xD6] = 0xC0A080, -[0xD7] = 0xC0A0C0, -[0xD8] = 0xC0C000, -[0xD9] = 0xC0C040, -[0xDA] = 0xC0C080, -[0xDB] = 0xC0C0C0, -[0xDC] = 0xC0E000, -[0xDD] = 0xC0E040, -[0xDE] = 0xC0E080, -[0xDF] = 0xC0E0C0, -[0xE0] = 0xE00000, -[0xE1] = 0xE00040, -[0xE2] = 0xE00080, -[0xE3] = 0xE000C0, -[0xE4] = 0xE02000, -[0xE5] = 0xE02040, -[0xE6] = 0xE02080, -[0xE7] = 0xE020C0, -[0xE8] = 0xE04000, -[0xE9] = 0xE04040, -[0xEA] = 0xE04080, -[0xEB] = 0xE040C0, -[0xEC] = 0xE06000, -[0xED] = 0xE06040, -[0xEE] = 0xE06080, -[0xEF] = 0xE060C0, -[0xF0] = 0xE08000, -[0xF1] = 0xE08040, -[0xF2] = 0xE08080, -[0xF3] = 0xE080C0, -[0xF4] = 0xE0A000, -[0xF5] = 0xE0A040, -[0xF6] = 0xE0A080, -[0xF7] = 0xE0A0C0, -[0xF8] = 0xE0C000, -[0xF9] = 0xE0C040, -[0xFA] = 0xE0C080, -[0xFB] = 0xE0C0C0, -[0xFC] = 0xE0E000, -[0xFD] = 0xE0E040, -[0xFE] = 0xE0E080, -[0xFF] = 0xE0E0C0, diff --git a/Beta/debugImageApi.lua b/Beta/debugImageApi.lua deleted file mode 100644 index aefb4deb..00000000 --- a/Beta/debugImageApi.lua +++ /dev/null @@ -1,646 +0,0 @@ - --------------------------------------------- OCIF Image Format ----------------------------------------------------------- - -local copyright = [[ - - Автор: Pirnogion - VK: https://vk.com/id88323331 - Соавтор: IT - VK: https://vk.com/id7799889 - -]] - ---------------------------------------- Подгрузка библиотек -------------------------------------------------------------- - -local component = require("component") -local unicode = require("unicode") -local fs = require("filesystem") -local gpu = component.gpu - -local image = {} - --------------------------------------------- Переменные ------------------------------------------------------------------- - ---Cигнатура OCIF-файла -local ocif_signature1 = 0x896F6369 -local ocif_signature2 = 0x00661A0A --7 bytes: 89 6F 63 69 66 1A 0A -local ocif_signature_expand = { string.char(0x89), string.char(0x6F), string.char(0x63), string.char(0x69), string.char(0x66), string.char(0x1A), string.char(0x0A) } - ---Константы программы -local constants = { - elementCount = 4, - byteSize = 8, - nullChar = 0, - rawImageLoadStep = 19, - fileOpenError = "Can't open file", - compressedFileFormat = ".pic", - rawFileFormat = ".rawpic", -} - ----------------------------------------- Локальные функции ------------------------------------------------------------------- - ---Выделить бит-терминатор в первом байте UTF-8 символа: 1100 0010 --> 0010 0000 -local function selectTerminateBit_l() - local prevByte = nil - local prevTerminateBit = nil - - return function( byte ) - local x, terminateBit = nil - if ( prevByte == byte ) then - return prevTerminateBit - end - - x = bit32.band( bit32.bnot(byte), 0x000000FF ) - x = bit32.bor( x, bit32.rshift(x, 1) ) - x = bit32.bor( x, bit32.rshift(x, 2) ) - x = bit32.bor( x, bit32.rshift(x, 4) ) - x = bit32.bor( x, bit32.rshift(x, 8) ) - x = bit32.bor( x, bit32.rshift(x, 16) ) - - terminateBit = x - bit32.rshift(x, 1) - - prevByte = byte - prevTerminateBit = terminateBit - - return terminateBit - end -end -local selectTerminateBit = selectTerminateBit_l() - ---Прочитать n байтов из файла, возвращает прочитанные байты как число, если не удалось прочитать, то возвращает 0 -local function readBytes(file, bytes) - local readedByte = 0 - local readedNumber = 0 - for i = bytes, 1, -1 do - readedByte = string.byte( file:read(1) or constants.nullChar ) - readedNumber = readedNumber + bit32.lshift(readedByte, i * constants.byteSize - constants.byteSize) - end - - return readedNumber -end - ---Преобразует цвет из HEX-записи в RGB-запись -local function HEXtoRGB(color) - return bit32.rshift( color, 16 ), bit32.rshift( bit32.band(color, 0x00ff00), 8 ), bit32.band(color, 0x0000ff) -end - ---Аналогично, но из RGB в HEX -local function RGBtoHEX(rr, gg, bb) - return bit32.lshift(rr, 16) + bit32.lshift(gg, 8) + bb -end - ---Смешивание двух цветов на основе альфа-канала второго -local function alphaBlend(back_color, front_color, alpha_channel) - local INVERTED_ALPHA_CHANNEL = 255 - alpha_channel - - local back_color_rr, back_color_gg, back_color_bb = HEXtoRGB(back_color) - local front_color_rr, front_color_gg, front_color_bb = HEXtoRGB(front_color) - - local blended_rr = front_color_rr * INVERTED_ALPHA_CHANNEL / 255 + back_color_rr * alpha_channel / 255 - local blended_gg = front_color_gg * INVERTED_ALPHA_CHANNEL / 255 + back_color_gg * alpha_channel / 255 - local blended_bb = front_color_bb * INVERTED_ALPHA_CHANNEL / 255 + back_color_bb * alpha_channel / 255 - - return RGBtoHEX( blended_rr, blended_gg, blended_bb ) -end - ---Подготавливает цвета и символ для записи в файл сжатого формата -local function encodePixel(background, foreground, alpha, char) - --Расхерачиваем жирные цвета в компактные цвета - local ascii_background1, ascii_background2, ascii_background3 = HEXtoRGB(background) - local ascii_foreground1, ascii_foreground2, ascii_foreground3 = HEXtoRGB(foreground) - --Расхерачиваем жирный код юникод-символа в несколько миленьких ascii-кодов - local ascii_char1, ascii_char2, ascii_char3, ascii_char4, ascii_char5, ascii_char6 = string.byte( char, 1, 6 ) - ascii_char1 = ascii_char1 or constants.nullChar - --Возвращаем все расхераченное - return ascii_background1, ascii_background2, ascii_background3, ascii_foreground1, ascii_foreground2, ascii_foreground3, alpha, ascii_char1, ascii_char2, ascii_char3, ascii_char4, ascii_char5, ascii_char6 -end - ---Декодирование UTF-8 символа -local function decodeChar(file) - local first_byte = readBytes(file, 1) - local charcode_array = {first_byte} - local len = 1 - - local middle = selectTerminateBit(first_byte) - if ( middle == 32 ) then - len = 2 - elseif ( middle == 16 ) then - len = 3 - elseif ( middle == 8 ) then - len = 4 - elseif ( middle == 4 ) then - len = 5 - elseif ( middle == 2 ) then - len = 6 - end - - for i = 1, len-1 do - table.insert( charcode_array, readBytes(file, 1) ) - end - - return string.char( table.unpack( charcode_array ) ) -end - ---Правильное конвертирование HEX-переменной в строковую -local function HEXtoSTRING(color, bitCount, withNull) - local stro4ka = string.format("%X",color) - local sStro4ka = unicode.len(stro4ka) - - if sStro4ka < bitCount then - stro4ka = string.rep("0", bitCount - sStro4ka) .. stro4ka - end - - sStro4ka = nil - - if withNull then return "0x"..stro4ka else return stro4ka end -end - ---Получение формата файла -local function getFileFormat(path) - local name = fs.name(path) - local starting, ending = string.find(name, "(.)%.[%d%w]*$") - if starting == nil then - return nil - else - return unicode.sub(name,starting + 1, -1) - end - name, starting, ending = nil, nil, nil -end - ------------------------------- Все, что касается сжатого формата ------------------------------------------------------------ - --- Запись в файл сжатого OCIF-формата изображения -function image.saveCompressed(path, picture) - local encodedPixel - local file = assert( io.open(path, "w"), constants.fileOpenError ) - - file:write( table.unpack( ocif_signature_expand ) ) - file:write( string.char( picture.width ) ) - file:write( string.char( picture.height ) ) - - for i = 1, picture.width * picture.height * constants.elementCount, constants.elementCount do - encodedPixel = - { - encodePixel(picture[i], picture[i + 1], picture[i + 2], picture[i + 3]) - } - for j = 1, #encodedPixel do - file:write( string.char( encodedPixel[j] ) ) - end - end - - file:close() -end - ---Чтение из файла сжатого OCIF-формата изображения, возвращает массив типа 2 (подробнее о типах см. конец файла) -function image.loadCompressed(path) - local picture = {} - local file = assert( io.open(path, "rb"), constants.fileOpenError ) - - --Проверка файла на соответствие сигнатуры - local signature1, signature2 = readBytes(file, 4), readBytes(file, 3) - if ( signature1 ~= ocif_signature1 or signature2 ~= ocif_signature2 ) then - file:close() - return nil - end - - --Читаем ширину и высоту файла - picture.width = readBytes(file, 1) - picture.height = readBytes(file, 1) - - for i = 1, picture.width * picture.height do - --Читаем бекграунд - table.insert(picture, readBytes(file, 3)) - --Читаем форграунд - table.insert(picture, readBytes(file, 3)) - --Читаем альфу - table.insert(picture, readBytes(file, 1)) - --Читаем символ - table.insert(picture, decodeChar( file )) - end - - file:close() - - return picture -end - ------------------------------- Все, что касается сырого формата ------------------------------------------------------------ - ---Сохранение в файл сырого формата изображения типа 2 (подробнее о типах см. конец файла) -function image.saveRaw(path, picture) - local file = assert( io.open(path, "w"), constants.fileOpenError ) - - local xPos, yPos = 1, 1 - for i = 1, picture.width * picture.height * constants.elementCount, constants.elementCount do - file:write( HEXtoSTRING(picture[i], 6), " ", HEXtoSTRING(picture[i + 1], 6), " ", HEXtoSTRING(picture[i + 2], 2), " ", picture[i + 3], " ") - - xPos = xPos + 1 - if xPos > picture.width then - xPos = 1 - yPos = yPos + 1 - file:write("\n") - end - end - - file:close() -end - ---Загрузка из файла сырого формата изображения типа 2 (подробнее о типах см. конец файла) -function image.loadRaw(path) - local file = assert( io.open(path, "r"), constants.fileOpenError ) - local picture = {} - - local background, foreground, alpha, symbol, sLine - local lineCounter = 0 - for line in file:lines() do - sLine = unicode.len(line) - for i = 1, sLine, constants.rawImageLoadStep do - background = "0x" .. unicode.sub(line, i, i + 5) - foreground = "0x" .. unicode.sub(line, i + 7, i + 12) - alpha = "0x" .. unicode.sub(line, i + 14, i + 15) - symbol = unicode.sub(line, i + 17, i + 17) - - table.insert(picture, tonumber(background)) - table.insert(picture, tonumber(foreground)) - table.insert(picture, tonumber(alpha)) - table.insert(picture, symbol) - end - lineCounter = lineCounter + 1 - end - - picture.width = sLine / constants.rawImageLoadStep - picture.height = lineCounter - - file:close() - - return picture -end - ------------------------------------ Вспомогательные функции программы ------------------------------------------------------------ - ---Оптимизировать и сгруппировать по цветам картинку типа 2 (подробнее о типах см. конец файла) -function image.convertToGroupedImage(picture) - --Создаем массив оптимизированной картинки - local optimizedPicture = {} - --Задаем константы - local xPos, yPos, background, foreground, alpha, symbol = 1, 1, nil, nil, nil, nil - --Перебираем все элементы массива - for i = 1, picture.width * picture.height * constants.elementCount, constants.elementCount do - --Получаем символ из неоптимизированного массива - background, foreground, alpha, symbol = picture[i], picture[i + 1], picture[i + 2], picture[i + 3] - --Группируем картинку по цветам - optimizedPicture[background] = optimizedPicture[background] or {} - optimizedPicture[background][foreground] = optimizedPicture[background][foreground] or {} - table.insert(optimizedPicture[background][foreground], xPos) - table.insert(optimizedPicture[background][foreground], yPos) - table.insert(optimizedPicture[background][foreground], alpha) - table.insert(optimizedPicture[background][foreground], symbol) - --Если xPos достигает width изображения, то сбросить на 1, иначе xPos++ - xPos = (xPos == picture.width) and 1 or xPos + 1 - --Если xPos равняется 1, то yPos++, а если нет, то похуй - yPos = (xPos == 1) and yPos + 1 or yPos - end - --Возвращаем оптимизированный массив - return optimizedPicture -end - ---Нарисовать по указанным координатам картинку указанной ширины и высоты для теста -function image.drawRandomImage(x, y, width, height) - local picture = {} - local symbolArray = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "Й", "К", "Л", "И", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "Ь", "Э", "Ю", "Я"} - picture.width = width - picture.height = height - local background, foreground, symbol - for j = 1, height do - for i = 1, width do - background = math.random(0x000000, 0xffffff) - foreground = math.random(0x000000, 0xffffff) - symbol = symbolArray[math.random(1, #symbolArray)] - - table.insert(picture, background) - table.insert(picture, foreground) - table.insert(picture, 0x00) - table.insert(picture, symbol) - end - end - image.draw(x, y, picture) - return picture -end - ------------------------------------------ Основные функции программы ------------------------------------------------------------------- - ---Сохранить изображение любого поддерживаемого формата -function image.save(path, picture) - --Создать папку под файл, если ее нет - fs.makeDirectory(fs.path(path)) - --Получаем формат указанного файла - local fileFormat = getFileFormat(path) - --Проверяем соответствие формата файла - if fileFormat == constants.compressedFileFormat then - image.saveCompressed(path, picture) - elseif fileFormat == constants.rawFileFormat then - image.saveRaw(path, picture) - else - error("Unsupported file format.\n") - end -end - ---Загрузить изображение любого поддерживаемого формата -function image.load(path) - --Кинуть ошибку, если такого файла не существует - if not fs.exists(path) then error("File \""..path.."\" does not exists.\n") end - --Получаем формат указанного файла - local fileFormat = getFileFormat(path) - --Проверяем соответствие формата файла - if fileFormat == constants.compressedFileFormat then - return image.loadCompressed(path) - elseif fileFormat == constants.rawFileFormat then - return image.loadRaw(path) - else - error("Unsupported file format.\n") - end -end - ---Отрисовка изображения типа 3 (подробнее о типах см. конец файла) -function image.draw(x, y, rawPicture) - --Конвертируем в групповое изображение - local picture = image.convertToGroupedImage(rawPicture) - --Все как обычно - x, y = x - 1, y - 1 - --Переменные, чтобы в цикле эту парашу не создавать - local currentBackground, xPos, yPos, alpha, symbol - local _, _ - --Перебираем все цвета фона - for background in pairs(picture) do - --Заранее ставим корректный цвет фона - gpu.setBackground(background) - --Перебираем все цвета текста - for foreground in pairs(picture[background]) do - --Ставим сразу и корректный цвет текста - gpu.setForeground(foreground) - --Перебираем все пиксели - for i = 1, #picture[background][foreground], 4 do - --Получаем временную репрезентацию - xPos, yPos, alpha, symbol = picture[background][foreground][i], picture[background][foreground][i + 1], picture[background][foreground][i + 2], picture[background][foreground][i + 3] - --Если альфа имеется, но она не совсем прозрачна - if alpha > 0x00 and alpha < 0xFF then - _, _, currentBackground = gpu.get(x + xPos, y + yPos) - currentBackground = alphaBlend(currentBackground, background, alpha) - gpu.setBackground(currentBackground) - --Рисуем символ на экране - gpu.set(x + xPos, y + yPos, symbol) - --Если альфа отсутствует - elseif alpha == 0x00 then - if currentBackground ~= background then - currentBackground = background - gpu.setBackground(currentBackground) - end - --Рисуем символ на экране - gpu.set(x + xPos, y + yPos, symbol) - end - - --Выгружаем сгруппированное изображение из памяти - picture[background][foreground][i], picture[background][foreground][i + 1], picture[background][foreground][i + 2], picture[background][foreground][i + 3] = nil, nil, nil, nil - end - --Выгружаем данные о текущем цвете текста из памяти - picture[background][foreground] = nil - end - --Выгружаем данные о текущем фоне из памяти - picture[background] = nil - end -end - -local function loadOldPng(path) - local massiv = {} - local file = io.open(path, "r") - local lineCounter = 0 - local sLine = 0 - for line in file:lines() do - sLine = unicode.len(line) - - for i = 1, sLine, 16 do - table.insert(massiv, tonumber("0x" .. unicode.sub(line, i, i + 5))) - table.insert(massiv, tonumber("0x" .. unicode.sub(line, i + 7, i + 12))) - table.insert(massiv, 0x00) - table.insert(massiv, tonumber("0x" .. unicode.sub(line, i + 14, i + 14))) - end - - lineCounter = lineCounter + 1 - end - - massiv.width = sLine / 16 - massiv.height = lineCounter - - return massiv -end - -local function convertAllPngToPic() - local counter = 0 - local function doConvert(path) - local fileList = ecs.getFileList(path) - for file = 1, #fileList do - if fs.isDirectory(path..file) then - doConvert(path..file) - else - local fileFormat = ecs.getFileFormat(path..file) - if fileFormat == ".png" then - print("Найден .png в "..path..file) - print("Загружаю старый формат...") - local picture = loadOldPng() - print("Сохраняю в новом формате...") - image.saveCompressed(path..ecs.hideFileFormat(file)..".pic", picture) - picture = nil - print("Успешно!") - print(" ") - counter = counter + 1 - end - end - end - end - - print(" ") - doConvert("/") - print("Всего сконвертировано "..counter.." файлов.") - print(" ") -end - -convertAllPngToPic() - ------------------------------------------- Примеры работы с библиотекой ------------------------------------------------ - --- ecs.prepareToExit() --- ecs.error("Создаю и рисую картинку!") --- local generatedPic = image.drawRandomImage(1, 1, 160, 50) --- ecs.error("Сохраняю созданную картинку в формате .pic!") --- ecs.prepareToExit() --- image.save("1.pic", generatedPic) --- ecs.error("Сохраняю созданную картинку в формате .rawpic!") --- ecs.prepareToExit() --- image.save("1.rawpic", generatedPic) --- ecs.error("Загружаю сохраненную картинку в формате .pic!") --- ecs.prepareToExit() --- local loadedPic = image.load("1.pic") --- image.draw(1, 1, loadedPic) --- ecs.error("Загружаю сохраненную картинку в формате .rawpic!") --- ecs.prepareToExit() --- local loadedPic = image.load("1.rawpic") --- image.draw(1, 1, loadedPic) - ------------------------------------------- Типы массивов изображений --------------------------------------------------- - - ---[[ - - Тип 1: - - Основной формат изображения, линейная запись данных о пикселях, - сжатие двух цветов и альфа-канала в одно число. Минимальный расход - оперативной памяти, однако для изменения цвета требует декомпрессию. - - Структура: - - local picture = { - width = ширина изображения, - height = высота изображения, - Сжатые цвета и альфа-канал, - Символ, - Сжатые цвета и альфа-канал, - Символ, - ... - } - - Пример: - - local picture = { - width = 2, - height = 2, - 0xff00aa, - "Q", - 0x88aacc, - "W", - 0xff00aa, - "E", - 0x88aacc, - "R" - } - - Тип 2 конвертируется только в тип 3 и только для отрисовки на экране: - Изображение типа 3 = image.convertToGroupedImage( Сюда кидаем массив изображения типа 2 ) - - Тип 2 (сгруппированный по цветам формат, ипользуется только для отрисовки изображения): - - Структура: - local picture = { - Цвет фона 1 = { - Цвет текста 1 = { - Координата по X, - Координата по Y, - Альфа-канал, - Символ, - Координата по X, - Координата по Y, - Альфа-канал, - Символ, - ... - }, - Цвет текста 2 = { - Координата по X, - Координата по Y, - Альфа-канал, - Символ, - Координата по X, - Координата по Y, - Альфа-канал, - Символ, - ... - }, - ... - }, - Цвет фона 2 = { - Цвет текста 1 = { - Координата по X, - Координата по Y, - Альфа-канал, - Символ, - Координата по X, - Координата по Y, - Альфа-канал, - Символ, - ... - }, - Цвет текста 2 = { - Координата по X, - Координата по Y, - Альфа-канал, - Символ, - Координата по X, - Координата по Y, - Альфа-канал, - Символ, - ... - }, - ... - }, - } - - Пример: - local picture = { - 0xffffff = { - 0xaabbcc = { - 1, - 1, - 0x00, - "Q", - 12, - 12, - 0xaa, - "W" - }, - 0x88aa44 = { - 5, - 5, - 0xcc, - "E", - 12, - 12, - 0x00, - "R" - } - }, - 0x444444 = { - 0x112233 = { - 40, - 20, - 0x00, - "T", - 12, - 12, - 0xaa, - "Y" - }, - 0x88aa44 = { - 5, - 5, - 0xcc, - "U", - 12, - 12, - 0x00, - "I" - } - } - } - -]] - ------------------------------------------------------------------------------------------------------------------------- - -return image - - - - - - - - - diff --git a/PoleznayaHuynaPoMaynu/Фирменный компьютер ECS.json b/PoleznayaHuynaPoMaynu/Фирменный компьютер ECS.json index 807a1e26..ac3a08dd 100644 --- a/PoleznayaHuynaPoMaynu/Фирменный компьютер ECS.json +++ b/PoleznayaHuynaPoMaynu/Фирменный компьютер ECS.json @@ -22,12 +22,13 @@ /minecraft:give @a[r=5,name=ECS] OpenComputers:item 1 103 { display:{ - Name:"Фирменный процессор от ECS", + Name:"Buttex® XTreme® Processor X1000, 30 Hz", Lore:[ " ", - " Сверхбыстрый процессор, созданный лучшими ", - " инженерами нашей компании. Имеет встроенную ", - " видеокарту 3 уровня с водяным охлаждением. ", + " Мощный процессор, созданный лучшими инженерами ", + " нашей компании для особых задач. Имеет ", + " интегрированный видеомодуль 3 уровня ", + " для экономии свободного пространства ПК. ", " ", ] } diff --git a/lib/ECSAPI.lua b/lib/ECSAPI.lua index f8524983..6332b866 100755 --- a/lib/ECSAPI.lua +++ b/lib/ECSAPI.lua @@ -1885,7 +1885,7 @@ function ecs.universalWindow(x, y, width, background, closeWindowAfter, ...) elseif objectType == "color" then local xPos, yPos = x + 1, objects[number].y - local blendedColor = require("colorlib").alphaBlend(objects[number][3], 0xFFFFFF, 180) + local blendedColor = require("colorlib").alphaBlend(objects[number][3], 0xFFFFFF, 0.705882) local w = width - 2 ecs.colorTextWithBack(xPos, yPos + 2, blendedColor, background, string.rep("▀", w)) diff --git a/lib/GUI.lua b/lib/GUI.lua index ad7ab6b4..9475c4a2 100755 --- a/lib/GUI.lua +++ b/lib/GUI.lua @@ -1760,35 +1760,43 @@ local function drawChart(object) local dx, dy = xMax - xMin, yMax - yMin -- y axis values and helpers - local value, chartHeight, yAxisValues, yAxisValueMaxWidth = yMin, object.height - 2, {}, -math.huge + local value, chartHeight, yAxisValueMaxWidth, yAxisValues = yMin, object.height - 1 - (object.showXAxisValues and 1 or 0), 0, {} for y = object.y + object.height - 3, object.y + 1, -chartHeight * object.yAxisValueInterval do local stringValue = getAxisValue(value, object.yAxisPostfix, object.roundValues) yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.len(stringValue)) table.insert(yAxisValues, {y = math.ceil(y), value = stringValue}) value = value + dy * object.yAxisValueInterval end - table.insert(yAxisValues, {y = object.y, value = getAxisValue(yMax, object.yAxisPostfix, object.roundValues)}) - local x, chartWidth, chartX = object.x + yAxisValueMaxWidth + 2, object.width - yAxisValueMaxWidth - 2, object.x + yAxisValueMaxWidth + 2 + local stringValue = getAxisValue(yMax, object.yAxisPostfix, object.roundValues) + table.insert(yAxisValues, {y = object.y, value = stringValue}) + yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.len(stringValue)) + + local chartWidth = object.width - (object.showYAxisValues and yAxisValueMaxWidth + 2 or 0) + local chartX = object.x + object.width - chartWidth for i = 1, #yAxisValues do - buffer.text(x - unicode.len(yAxisValues[i].value) - 2, yAxisValues[i].y, object.colors.axisValue, yAxisValues[i].value) - buffer.text(x, yAxisValues[i].y, object.colors.helpers, string.rep("─", chartWidth)) + if object.showYAxisValues then + buffer.text(chartX - unicode.len(yAxisValues[i].value) - 2, yAxisValues[i].y, object.colors.axisValue, yAxisValues[i].value) + end + buffer.text(chartX, yAxisValues[i].y, object.colors.helpers, string.rep("─", chartWidth)) end -- x axis values - local value = xMin - for x = x, x + chartWidth - 2, chartWidth * object.xAxisValueInterval do - local stringValue = getAxisValue(value, object.xAxisPostfix, object.roundValues) - buffer.text(math.floor(x - unicode.len(stringValue) / 2), object.y + object.height - 1, object.colors.axisValue, stringValue) - value = value + dx * object.xAxisValueInterval + if object.showXAxisValues then + value = xMin + for x = chartX, chartX + chartWidth - 2, chartWidth * object.xAxisValueInterval do + local stringValue = getAxisValue(value, object.xAxisPostfix, object.roundValues) + buffer.text(math.floor(x - unicode.len(stringValue) / 2), object.y + object.height - 1, object.colors.axisValue, stringValue) + value = value + dx * object.xAxisValueInterval + end + local value = getAxisValue(xMax, object.xAxisPostfix, object.roundValues) + buffer.text(object.x + object.width - unicode.len(value), object.y + object.height - 1, object.colors.axisValue, value) end - local value = getAxisValue(xMax, object.xAxisPostfix, object.roundValues) - buffer.text(object.x + object.width - unicode.len(value), object.y + object.height - 1, object.colors.axisValue, value) -- Axis lines for y = object.y, object.y + chartHeight - 1 do buffer.text(chartX - 1, y, object.colors.axis, "┨") end - buffer.text(chartX - 1, object.y + object.height - 2, object.colors.axis, "┗" .. string.rep("┯━", chartWidth / 2)) + buffer.text(chartX - 1, object.y + chartHeight, object.colors.axis, "┗" .. string.rep("┯━", chartWidth / 2)) local function fillVerticalPart(x1, y1, x2, y2) local dx, dy = x2 - x1, y2 - y1 @@ -1813,9 +1821,9 @@ local function drawChart(object) -- chart for i = 1, #valuesCopy - 1 do local x = math.floor(chartX + (valuesCopy[i][1] - xMin) / dx * (chartWidth - 1)) - local y = math.floor(object.y + object.height - 3 - (valuesCopy[i][2] - yMin) / dy * (chartHeight - 1)) * 2 + local y = math.floor(object.y + chartHeight - 1 - (valuesCopy[i][2] - yMin) / dy * (chartHeight - 1)) * 2 local xNext = math.floor(chartX + (valuesCopy[i + 1][1] - xMin) / dx * (chartWidth - 1)) - local yNext = math.floor(object.y + object.height - 3 - (valuesCopy[i + 1][2] - yMin) / dy * (chartHeight - 1)) * 2 + local yNext = math.floor(object.y + chartHeight - 1 - (valuesCopy[i + 1][2] - yMin) / dy * (chartHeight - 1)) * 2 if object.fillChartArea then fillVerticalPart(x, y, xNext, yNext) else @@ -1837,6 +1845,8 @@ function GUI.chart(x, y, width, height, axisColor, axisValueColor, axisHelpersCo object.xAxisValueInterval = xAxisValueInterval object.yAxisValueInterval = yAxisValueInterval object.fillChartArea = fillChartArea + object.showYAxisValues = true + object.showXAxisValues = true return object end @@ -1844,8 +1854,10 @@ end -------------------------------------------------------------------------------------------------------------------------------- -- buffer.start() --- local x, y, width, height = 2, 2, 150, 40 +-- local x, y, width, height = 10, 10, 32, 16 -- local chart = GUI.chart(x, y, width, height, 0xFFFFFF, 0xBBBBBB, 0x777777, 0xFF4444, 0.1, 0.15, "%", " RF/t", true, {}) +-- chart.showXAxisValues = false +-- chart.showYAxisValues = false -- -- buffer.clear(0x262626) -- -- buffer.square(x, y, width, height, 0x1D1D1D) diff --git a/lib/OpenComputersGL/Main.lua b/lib/OpenComputersGL/Main.lua index defb6124..fab89935 100644 --- a/lib/OpenComputersGL/Main.lua +++ b/lib/OpenComputersGL/Main.lua @@ -212,7 +212,7 @@ function OCGL.render() renderer.renderFilledTriangle({ vertex1, vertex2, vertex3 }, material.color) elseif OCGL.renderMode == OCGL.renderModes.flatShading then local finalColor = 0x0 - finalColor = colorlib.alphaBlend(material.color, 0x0, OCGL.triangles[triangleIndex][5] * 255) + finalColor = colorlib.alphaBlend(material.color, 0x0, OCGL.triangles[triangleIndex][5]) OCGL.triangles[triangleIndex][5] = nil renderer.renderFilledTriangle({ vertex1, vertex2, vertex3 }, finalColor) end diff --git a/lib/colorlib.lua b/lib/colorlib.lua index f299a2eb..caf7c2c6 100755 --- a/lib/colorlib.lua +++ b/lib/colorlib.lua @@ -76,10 +76,8 @@ end --Смешивание двух цветов на основе альфа-канала второго function colorlib.alphaBlend(firstColor, secondColor, alphaChannel) - alphaChannel = alphaChannel / 255 local invertedAlphaChannel = 1 - alphaChannel - local firstColorRed, firstColorGreen, firstColorBlue = colorlib.HEXtoRGB(firstColor) local secondColorRed, secondColorGreen, secondColorBlue = colorlib.HEXtoRGB(secondColor) diff --git a/lib/doubleBuffering.lua b/lib/doubleBuffering.lua index 29f4c320..8bc166a6 100755 --- a/lib/doubleBuffering.lua +++ b/lib/doubleBuffering.lua @@ -114,7 +114,7 @@ function buffer.square(x, y, width, height, background, foreground, symbol, tran if transparency == 0 then transparency = nil else - transparency = transparency * 2.55 + transparency = transparency / 100 end end if not foreground then foreground = 0x000000 end @@ -227,7 +227,7 @@ function buffer.text(x, y, color, text, transparency) if transparency == 0 then transparency = nil else - transparency = transparency * 2.55 + transparency = transparency / 100 end end diff --git a/lib/image.lua b/lib/image.lua index c8d30121..e19ba8bd 100755 --- a/lib/image.lua +++ b/lib/image.lua @@ -344,7 +344,7 @@ local function loadOCIF1(file) --Читаем форграунд table.insert(picture, readBytes(file, 3)) --Читаем альфу - table.insert(picture, readBytes(file, 1)) + table.insert(picture, readBytes(file, 1) / 0xFF) --Читаем символ table.insert(picture, decodeChar( file )) end @@ -463,7 +463,7 @@ local function loadOCIF2(file, decompressColors, useOCIF4) if header == "A" then local countOfBytesForArraySize = string.byte(file:read(1)) alphaSize = string.byte(file:read(countOfBytesForArraySize)) - alpha = string.byte(file:read(1)) + alpha = string.byte(file:read(1)) / 0xFF -- print("Количество байт под размер массива символов: " .. countOfBytesForArraySize) -- print("Размер массива символов: " .. alphaSize) -- print("Альфа: " .. alpha) @@ -584,7 +584,7 @@ local function loadRaw(file) table.insert(picture, tonumber(background)) table.insert(picture, tonumber(foreground)) - table.insert(picture, tonumber(alpha)) + table.insert(picture, tonumber(alpha) / 0xFF) table.insert(picture, symbol) end lineCounter = lineCounter + 1 diff --git a/lib/rayEngine.lua b/lib/rayEngine.lua index b2e2eed0..47f654c8 100755 --- a/lib/rayEngine.lua +++ b/lib/rayEngine.lua @@ -83,8 +83,8 @@ end local function getTileColor(basecolor, distance) local limitedDistance = math.floor(distance * rayEngine.properties.shadingCascades / rayEngine.properties.shadingDistance) - local transparency = rayEngine.currentShadingTransparencyMapValue - math.floor(limitedDistance * 255 / rayEngine.properties.shadingCascades) - transparency = (transparency >= rayEngine.properties.shadingTransparencyMap[1] and transparency <= 255) and transparency or rayEngine.properties.shadingTransparencyMap[1] + local transparency = rayEngine.currentShadingTransparencyMapValue - limitedDistance / rayEngine.properties.shadingCascades + transparency = (transparency >= rayEngine.properties.shadingTransparencyMap[1] and transparency <= 1) and transparency or rayEngine.properties.shadingTransparencyMap[1] return colorlib.alphaBlend(basecolor, 0x000000, transparency) end diff --git a/lib/rayEngineBackup.lua b/lib/rayEngineBackup.lua deleted file mode 100644 index 4d895c45..00000000 --- a/lib/rayEngineBackup.lua +++ /dev/null @@ -1,472 +0,0 @@ -local libraries = { - colorlib = "colorlib", - image = "image", - buffer = "doubleBuffering", - doubleHeight = "doubleHeight", - GUI = "GUI", - files = "files", - computer = "computer", - event = "event", -} - -for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end; libraries = nil -local rayEngine = {} - ----------------------------------------------------- Константы ------------------------------------------------------------------ - -rayEngine.tileWidth = 32 -rayEngine.wallsPosition = 0 -rayEngine.horizonPosition = math.floor(buffer.screen.height / 2) -rayEngine.minimapEnabled = true -rayEngine.compassEnabled = false -rayEngine.watchEnabled = false -rayEngine.drawFieldOfViewOnMinimap = false -rayEngine.chatShowTime = 4 -rayEngine.chatHistory = {} -rayEngine.chatPanelWidth, rayEngine.chatPanelHeight = math.floor(buffer.screen.width * 0.4), math.floor(buffer.screen.height * 0.4) -rayEngine.chatHistoryLimit = rayEngine.chatPanelHeight - ----------------------------------------------- Вспомогательные функции ------------------------------------------------------------------ - -local function round(num) - if num >= 0 then - return math.floor(num + 0.5) - else - return math.ceil(num - 0.5) - end -end - -local function convertRadiansToDegrees(rad) - return rad * (180 / 3.14) -end - -local function convertDegreesToRadians(ang) - return ang * (3.14 / 180) -end - -local function constrainAngle(value) - if ( value < 0 ) then - value = value + 360 - elseif ( value > 360 ) then - value = value - 360 - end - return value -end - -local function getSkyColorByTime() - return rayEngine.world.colors.sky[rayEngine.world.dayNightCycle.currentTime > 0 and math.ceil(rayEngine.world.dayNightCycle.currentTime / rayEngine.world.dayNightCycle.length * #rayEngine.world.colors.sky) or 1] -end - -local function getBrightnessByTime() - return rayEngine.world.colors.brightnessMultiplyer[rayEngine.world.dayNightCycle.currentTime > 0 and math.ceil(rayEngine.world.dayNightCycle.currentTime / rayEngine.world.dayNightCycle.length * #rayEngine.world.colors.brightnessMultiplyer) or 1] -end - -local function getTimeDependentColors() - rayEngine.world.colors.sky.current = getSkyColorByTime() - rayEngine.world.colors.brightnessMultiplyer.current = math.floor(getBrightnessByTime() * 2.55) - rayEngine.world.colors.groundByTime = colorlib.alphaBlend(rayEngine.world.colors.ground, 0x000000, rayEngine.world.colors.brightnessMultiplyer.current) - - rayEngine.world.colors.tile.byTime = {} - for i = 1, #rayEngine.world.colors.tile do - rayEngine.world.colors.tile.byTime[i] = colorlib.alphaBlend(rayEngine.world.colors.tile[i], 0x000000, rayEngine.world.colors.brightnessMultiplyer.current) - end -end - -local function doDayNightCycle() - if rayEngine.world.dayNightCycle.enabled then - local computerUptime = computer.uptime() - if (computerUptime - rayEngine.world.dayNightCycle.lastComputerUptime) >= rayEngine.world.dayNightCycle.speed then - rayEngine.world.dayNightCycle.currentTime = rayEngine.world.dayNightCycle.currentTime + rayEngine.world.dayNightCycle.speed - if rayEngine.world.dayNightCycle.currentTime > rayEngine.world.dayNightCycle.length then rayEngine.world.dayNightCycle.currentTime = 0 end - rayEngine.world.dayNightCycle.lastComputerUptime = computerUptime - - getTimeDependentColors() - end - end -end - -local function correctDouble(number) - return string.format("%.1f", number) -end - -local function convertWorldCoordsToMapCoords(x, y) - return round(x / rayEngine.tileWidth), round(y / rayEngine.tileWidth) -end - -local function getBlockCoordsByLook(distance) - local radRotation = math.rad(rayEngine.player.rotation + 90) - return convertWorldCoordsToMapCoords(rayEngine.player.position.x + distance * math.sin(radRotation) * rayEngine.tileWidth, rayEngine.player.position.y + distance * math.cos(radRotation) * rayEngine.tileWidth) -end - ----------------------------------------------------- Работа с файлами ------------------------------------------------------------------ - -function rayEngine.loadWorld(pathToWorldFolder) - --Загружаем все конфиг-файлы мира - rayEngine.world = files.loadTableFromFile(pathToWorldFolder .. "/World.cfg") - rayEngine.map = files.loadTableFromFile(pathToWorldFolder .. "/Map.cfg") - rayEngine.player = files.loadTableFromFile(pathToWorldFolder .. "/Player.cfg") - --Дополняем карту ее размерами - rayEngine.map.width = #rayEngine.map[1] - rayEngine.map.height = #rayEngine.map - --Ебашим правильную позицию игрока, основанную на этой ХУЙНЕ, которую ГЛЕБ так ЛЮБИТ - rayEngine.player.position.x = rayEngine.tileWidth * rayEngine.player.position.x - rayEngine.tileWidth / 2 - rayEngine.player.position.y = rayEngine.tileWidth * rayEngine.player.position.y - rayEngine.tileWidth / 2 - --Рассчитываем стартовые цвета, зависимые от времени - небо, землю, стены - getTimeDependentColors() - --Обнуляем текущее время, если превышен лимит - rayEngine.world.dayNightCycle.currentTime = rayEngine.world.dayNightCycle.currentTime > rayEngine.world.dayNightCycle.length and 0 or rayEngine.world.dayNightCycle.currentTime - --Осуществляем базовое получение аптайма пекарни - rayEngine.world.dayNightCycle.lastComputerUptime = computer.uptime() - rayEngine.distanceToProjectionPlane = (buffer.screen.width / 2) / math.tan(convertDegreesToRadians(rayEngine.player.fieldOfView / 2)) -end - ----------------------------------------------------- Функции, связанные с игроком ------------------------------------------------------------------ - -function rayEngine.move(distanceForward, distanceRight) - local forwardRotation = math.rad(rayEngine.player.rotation + 90) - local rightRotation = math.rad(rayEngine.player.rotation + 180) - local xNew = rayEngine.player.position.x + distanceForward * math.sin(forwardRotation) + distanceRight * math.sin(rightRotation) - local yNew = rayEngine.player.position.y + distanceForward * math.cos(forwardRotation) + distanceRight * math.cos(rightRotation) - - local xWorld, yWorld = convertWorldCoordsToMapCoords(xNew, yNew) - if rayEngine.map[yWorld][xWorld] == nil then - rayEngine.player.position.x, rayEngine.player.position.y = xNew, yNew - end -end - -function rayEngine.rotate(angle) - rayEngine.player.rotation = constrainAngle(rayEngine.player.rotation + angle) -end - -function rayEngine.turnRight() - rayEngine.rotate(rayEngine.player.rotationSpeed) -end - -function rayEngine.turnLeft() - rayEngine.rotate(-rayEngine.player.rotationSpeed) -end - -function rayEngine.moveForward() - rayEngine.move(rayEngine.player.moveSpeed, 0) -end - -function rayEngine.moveBackward() - rayEngine.move(-rayEngine.player.moveSpeed, 0) -end - -function rayEngine.moveLeft() - rayEngine.move(0, -rayEngine.player.moveSpeed) -end - -function rayEngine.moveRight() - rayEngine.move(0, rayEngine.player.moveSpeed) -end - -function rayEngine.jump() - if not rayEngine.player.jumpTimer then - local function onJumpFinished() - rayEngine.horizonPosition = rayEngine.horizonPosition - rayEngine.player.jumpHeight; - rayEngine.wallsPosition = rayEngine.wallsPosition - rayEngine.player.jumpHeight; - rayEngine.player.jumpTimer = nil - end - - rayEngine.player.jumpTimer = event.timer(1, onJumpFinished) - rayEngine.wallsPosition = rayEngine.wallsPosition + rayEngine.player.jumpHeight - rayEngine.horizonPosition = rayEngine.horizonPosition + rayEngine.player.jumpHeight - end -end - -function rayEngine.crouch() - rayEngine.player.isCrouched = not rayEngine.player.isCrouched - local heightAdder = rayEngine.player.isCrouched and -rayEngine.player.crouchHeight or rayEngine.player.crouchHeight - rayEngine.wallsPosition = rayEngine.wallsPosition + heightAdder - rayEngine.horizonPosition = rayEngine.horizonPosition + heightAdder -end - -function rayEngine.destroy(distance) - local xBlock, yBlock = getBlockCoordsByLook(distance) - rayEngine.map[yBlock][xBlock] = nil -end - -function rayEngine.place(distance, blockColor) - local xBlock, yBlock = getBlockCoordsByLook(distance) - rayEngine.map[yBlock][xBlock] = blockColor or 0x0 -end - ----------------------------------------------------- Функции интерфейса ------------------------------------------------------------------ - -local function drawFieldOfViewAngle(x, y, distance, color) - local fieldOfViewHalf = rayEngine.player.fieldOfView / 2 - local firstAngle, secondAngle = math.rad(-(rayEngine.player.rotation - fieldOfViewHalf + 90)), math.rad(-(rayEngine.player.rotation + fieldOfViewHalf + 90)) - local xFirst, yFirst = math.floor(x + math.sin(firstAngle) * distance), math.floor(y + math.cos(firstAngle) * distance) - local xSecond, ySecond = math.floor(x + math.sin(secondAngle) * distance), math.floor(y + math.cos(secondAngle) * distance) - doubleHeight.line(x, y, xFirst, yFirst, color) - doubleHeight.line(x, y, xSecond, ySecond, color) -end - -function rayEngine.drawMap(x, y, width, height, transparency) - buffer.square(x, y, width, height, 0x000000, 0x000000, " ", transparency) - local xHalf, yHalf = math.floor(width / 2), math.floor(height / 2) - local xMap, yMap = convertWorldCoordsToMapCoords(rayEngine.player.position.x, rayEngine.player.position.y) - - local xPos, yPos = x, y - for i = yMap - yHalf + 1, yMap + yHalf + 1 do - for j = xMap + xHalf + 1, xMap - xHalf + 1, -1 do - if rayEngine.map[i] and rayEngine.map[i][j] then - buffer.square(xPos, yPos, 1, 1, 0xEEEEEE) - end - xPos = xPos + 1 - end - xPos = x; yPos = yPos + 1 - end - - local xPlayer, yPlayer = x + xHalf, (y + yHalf) * 2 - --Поле зрения - if rayEngine.drawFieldOfViewOnMinimap then drawFieldOfViewAngle(xPlayer, yPlayer, 5, 0xCCFFBF) end - --Игрок - doubleHeight.set(xPlayer, yPlayer, 0x66FF40) - --Инфа - y = y + height - buffer.square(x, y, width, 1, 0x000000, 0x000000, " ", transparency + 10) - x = x + 1 - buffer.text(x, y, 0xFFFFFF, "POS: " .. correctDouble(rayEngine.player.position.x) .. " x " .. correctDouble(rayEngine.player.position.y)) -end - -function rayEngine.intro() - local logo = image.fromString("17060000FF 0000FF 0000FF 0000FF 007EFF▄007EFF▄007EFF▄007EFF▀007EFF▀007EFF▀007EFF▀007EFF▀007EFF▀007EFF▀007EFF▄007EFF▄007EFF▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 007EFF▄007EFF▀007EFF▀0000FF 0000FF 0000FF 0000FF 0053FF▄0053FF▀0053FF▀0053FF▀0053FF▄0000FF 0000FF 0000FF 0000FF 007EFF▀007EFF▀007EFF▄0000FF 0000FF 0000FF 007EFF▀007EFF▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 530000 0000FF 0078FF▀0000FF 537800▀0078FF▀0078FF▀0078FF▀0078FF▀0078FF▀0078FF▀7E7800▀0078FF▀0000FF 0078FF▀0000FF 0000FF 007EFF▀007EFF▀007EFF▄007EFF▄007EFF▄0000FF 0000FF 0053FF▀0053FF▀0053FF▀0000FF 0000FF 007EFF▄007EFF▄007EFF▄007EFF▀007EFF▀0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 007EFF▀007EFF▀007EFF▀007EFF▀007EFF▀007EFF▀007EFF▀0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 007EFFP007EFFo007EFFw007EFFe007EFFr007EFFe007EFFd0000FF 007EFFb007EFFy0000FF 007EFFR007EFFa007EFFy007EFFE007EFFn007EFFg007EFFi007EFFn007EFFe007EFF™0000FF 0000FF ") - local x, y = math.floor(buffer.screen.width / 2 - logo.width / 2), math.floor(buffer.screen.height / 2 - logo.height / 2) - local function draw(transparency) - buffer.clear(0xF0F0F0); - buffer.image(x, y, logo) - buffer.square(1, 1, buffer.screen.width, buffer.screen.height, 0x000000, 0x000000, " ", transparency) - buffer.draw() - os.sleep(0) - end - for i = 20, 100, 20 do draw(i) end - os.sleep(1.5) - for i = 100, 20, -20 do draw(i) end -end - -function rayEngine.compass(x, y) - if not rayEngine.compassImage then rayEngine.compassImage = image.fromString("1C190000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 553600▄373100▄543600▄373600▄543600▄373100▄540000 375400▄673700▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0055FF▄675400▄553700▄375500▄550000 375500▄540000 375400▄540000 373600▄310000 675500▄677E00▄375300▄365400▄373600▄540000 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 555400▄553700▄540000 543700▄540000 375300▄533100▄310B00▄310000 310000 360000 543100▄375300▄553100▄533600▄543200▄313600▄372A00▄373100▄0054FF▄0054FF▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 540000 543200▄540000 545300▄540600▄063100▄310000 315400▄365400▄373100▄313600▄530000 0000FF 0000FF 535400▄535400▄540000 365300▄533100▄065300▄310000 530600▄0054FF▄0000FF 0000FF 0000FF 0000FF 0000FF 530000 365300▄543600▄310600▄312A00▄2A5300▄365300▄543600▄540000 365300▄315300▄530000 0000FF 0000FF 535400▄540000 540000 313600▄363100▄540000 313600▄315300▄062A00▄543100▄0000FF 0000FF 0000FF 0000FF 315300▄533600▄312A00▄2A3100▄315300▄533600▄315400▄540000 535400▄540000 530000 533100▄0000FF 0000FF 540000 540000 315400▄540000 543100▄530000 543100▄313600▄2A0000 2A2900▄540000 0000FF 0000FF 0000FF 533100▄315400▄530000 062A00▄533100▄315300▄535400▄533100▄540000 315400▄543100▄530000 0000FF 0000FF 540000 535400▄315300▄535400▄363100▄535400▄530000 530000 312A00▄2A5300▄0054FF▀0000FF 0000FF 0000FF 312A00▄530000 553600▄2A5500▄2A0000 312A00▄533600▄545300▄315400▄535400▄540000 540000 0053FF▄0053FF▄540000 530000 535400▄535400▄545300▄530000 363100▄312A00▄313600▄545300▄0000FF 0000FF 0000FF 0000FF 530000 535400▄540000 545300▄555400▄315500▄315400▄533100▄543100▄530000 533100▄530000 535400▄535500▄533100▄535400▄315300▄533100▄533600▄315300▄530000 542A00▄312800▄0029FF▀0000FF 0000FF 0000FF 0000FF 530000 545500▄540000 555300▄535400▄530000 542A00▄545300▄365400▄530000 543600▄2A5400▄547E00▄550000 545300▄533600▄540000 530000 530000 542A00▄2A0000▄0029FF▀0000FF 0000FF 0000FF 0000FF 0000FF 530000 535400▄540000 540000 540000 545300▄530000 540000 2A5500▄545300▄292A00▄290000 292A00▄290000 295400▄292A00▄292A00▄290000 542A00▄543600▄285400▄0054FF▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 530000 533100▄540000 530000 535400▄0053FF▀0053FF▀542800▄542800▄532800▄2A2900▄542900▄532900▄542900▄542900▄532900▄542800▄2A2900▄2A2800▄532900▄552800▄542800▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 2A5300▄530000 535400▄540000 530000 532A00▀2A5300▄2A5500▄0029FF▀0028FF▀0028FF▀0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0028FF▀0028FF▀0028FF▀295300▄535500▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 535400▄545300▄530000 545300▄530000 2A0000 2A5300▄545300▄532A00▄542900▄532900▄2A2900▄2A2900▄2A2800▄2A2800▄2A2800▄2A2900▄2A2900▄532900▄532900▄2A2900▄542A00▄545300▄0054FF▄0054FF▄0000FF 0000FF 0000FF 545300▄530000 530000 545300▄2A5300▄532A00▄542900▄290000 295400▄297F00▄548100▄548100▄558100▄558100▄558100▄558100▄538100▄2A8100▄007E00▄295400▄2A2900▄295400▄2A2900▄290000 542A00▄557E00▄0000FF 0000FF 530000 2A0000 545300▄530000 532900▄285400▄2A8000▄7F8100▄810000 810000 810000 810000 810000 810000 812A00N810000 810000 810000 810000 810000 808100▄548100▄545500▄295300▄282900▄542900▄0000FF 0000FF 2A0000 2A0000 545300▄2A2900▄298000▄810000 810000 815500381550018155005810000 810000 810000 810000 810000 810000 810000 810000 81550048155005810000 810000 810000 558100▄2A5300▄282900▄0029FF▄0000FF 532A00▄2A0000 545300▄547E00▄810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 7F8000▄290000 292800▄0000FF 2A0000 2A0000 2A5300▄7E5300▄810000 812A00W810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 812A00E810000 807E00▄2A2900▄292800▄0000FF 2A0000 2A2900▄2A0000 2A0000 552A00▄810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 810000 815500▄542900▄280000 0028FF▀530000 2A0000 2A0000 290000 2A2900▄545300▄552A00▄815500▄810000 815500281550028155005810000 810000 810000 810000 810000 810000 810000 815500181550038155005817F00▄552900▄292800▄280000 282A00▄0000FF 530000 2A0000 540000 2A5300▄282A00▄290000 532900▄542A00▄542800▄552900▄7F5300▄815500▄817F00▄817F00▄810000 812A00S810000 817F00▄815500▄815500▄555400▄532900▄292800▄280000 282A00▄282A00▄530000 0000FF 532A00▄2A0000 530000 530000 2A5300▄290000 282900▄002900▄280000 280000 280000 290000 292A00▄2A2900▄542900▄532900▄2A0000 295300▄282900▄280000 280000 280000 282900▄295300▄295300▄2A5300▄552A00▄0000FF 530000 295300▄535400▄540000 535400▄540000 535400▄2A5500▄282900▄280000▄280000 280000▄290000▄2A2800▄2A2900▄552A00▄7E0000▄2A0000▄280000▄280000 280000▄280000▄002AFF▀002AFF▀002AFF▀002AFF▀0000FF 0000FF 532900▄532800▄0029FF▀0029FF▀0029FF▀0029FF▀0029FF▀0029FF▀0000FF 2A9800▄285500▄547E00▄7E5400▄7F5300▄7E2900▄7E2900▄552A00▄542A00▄2A5300▄282A00▄2A7E00▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF ") end - buffer.image(x, y, rayEngine.compassImage) - - x, y = x + 15, y + 17 - local distance = 3.4 - local northAngle = -rayEngine.player.rotation - local xScaleFactor = 2.2 - local southPoint, northPoint = {}, {} - local northAngleRad = math.rad(northAngle) - northPoint.x, northPoint.y = round(x + math.sin(northAngleRad) * distance * xScaleFactor), round(y - math.cos(northAngleRad) * distance) - northAngleRad = math.rad(northAngle + 180) - southPoint.x, southPoint.y = round(x + math.sin(northAngleRad) * distance * xScaleFactor), round(y - math.cos(northAngleRad) * distance) - - y = y * 2 - doubleHeight.line(x, y, northPoint.x, northPoint.y * 2, 0xFF5555) - doubleHeight.line(x, y, southPoint.x, southPoint.y * 2, 0xFFFFFF) - doubleHeight.set(x, y, 0x000000) -end - -function rayEngine.watch(x, y) - if not rayEngine.watchImage then rayEngine.watchImage = image.fromString("20190000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0053FF▄552900▄673100▄7E2A00▄7E3100▄7E2A00▄7E3100▄672A00▄7E2A00▄672900▄7F3100▄7E2A00▄0053FF▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 313600▄290000 290600▄062900▄290000 062900▄290000 062900▄290000 290600▄062900▄2A2900▄2A0600▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 313600▄012900▄2A2900▄290000 012900▄290000 290000 012A00▄290000 290000 312900▄293100▄310600▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 310000 292800▄062A00▄290000 290100▄062900▄290000 290000 2C2900▄290600▄293100▄2A2900▄292800▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0054FF▄557F00▄012800▄290000 290000 292800▄290000 012900▄292800▄290600▄290000 292800▄290000 012800▄807E00▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF AB8100▄7F8000▄283100▄280000 015400▄318100▄005300▄065500▄315500▄282A00▄296700▄015500▄290000 002900▄677E00▄81AA00▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 807F00▄7F8000▄677E00▄812900▄672800▄542800▄2A0000▄2A0000▄815400▄ACAA00▄555400▄283100▄2A0000 312900▄672800▄7F5300▄7F0000 7F0000 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 007EFF▄817E00▄7E2900▄2A0000▄805300▄54AA00▄003100▄2A0000 310600▄532900▄312800▄532900▄360100▄552900▄672800▄7E2A00▄315500▄678000▄555300▄540000▄805400▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0081FF▄802900▄280100▄280000 285400▄310600▄532900▄290000 290000 290000 290000 29D700129D7002290000 290000 290000 282900▄062900▄2A2900▄550600▄556700▄285500▄542800▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0080FF▄557E00▄28AA00▄005500▄552900▄290000 290000 290000 29D700129D7001290000 290000 290000 290000 290000 290000 290000 29D7001290000 290000 290000 290000 672900▄318000▄297F00▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 543100▄002800▄553100▄7E2800▄290000 29D700129D7000290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 29D7002290000 290000 7E2900▄7E6700▄282900▄808100▄0000FF 0000FF 0000FF 0000FF 805500▄280000▄290000 310600▄290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 555400▄535400▄533100▄D58000▄0080FF▄0000FF 552900▀550000 54AB00▄558100▄290000 290000 29D7009290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 29D7003290000 315400▄548100▄067E00▄557F00▄806700▄ACAB00▄0055FF▀545500▄AB3100▄815400▄290100▄290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 545300▄AB5500▄815300▄558000▄558000▄0000FF 0000FF 538100▄002800▄290600▄290000 290000 290000 29D7008290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 29D7004290000 290000 530000 000000 286700▄0080FF▀0000FF 0000FF 0000FF 0000FF 292A00▄000100▄530000 285400▄290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 290000 296700▄063100▄280000 818000▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 550000 810000▄532800▄015300▄280000 292800▄290000 29D7007290000 290000 290000 290000 290000 290000 290000 290000 290000 29D7005290000 290100▄292A00▄065300▄7F0000▄802900▄81C900▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 549900▄002900▄292800▄312800▄290600▄283100▄290600▄292800▄290000 290000 290000 29D7006290000 290000 292800▄292800▄290000 285300▄2A0600▄362800▄280000 285500▄0081FF▀0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 7EAA00▄317E00▄005300▄547E00▄7F2900▄290000▄292A00▄063100▄283100▄295500▄286200▄285500▄012A00▄292A00▄310600▄540000▄807E00▄005500▄015500▄530000 0081FF▀0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 7E8100▄7E8000▄557F00▄317E00▄2A3600▄283100▄005400▄2A5300▄817E00▄AA7E00▄545300▄005300▄005400▄283100▄537E00▄548100▄7F0000 7E8000▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 819800▄807F00▄280000 002900▄312900▄7E2800▄292800▄532800▄552900▄280000 550100▄542800▄282900▄000100▄7E0000 AA9800▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 555300▄012800▄290000 062900▄290000 062900▄290000 062900▄290000 290000 290000 290600▄280000 007EFF▀0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 313600▄062900▄312900▄290000 012900▄293100▄290000 062900▄312900▄290600▄312900▄2A0000 2A2900▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 315400▄290600▄310000 062900▄290000 293100▄062900▄290000 293100▄290000 293100▄062900▄312A00▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0054FF▀285500▄285500▄015500▄285500▄285500▄015500▄295500▄015500▄285500▄015500▄285500▄065500▄0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF 0000FF ") end - - buffer.image(x, y, rayEngine.watchImage) - x, y = x + 15, y + 12 - - local realTimeInSeconds = rayEngine.world.dayNightCycle.currentTime * 86400 / rayEngine.world.dayNightCycle.length - local hours = realTimeInSeconds / 3600 - local _, minutes = math.modf(hours) - local hourAngle = math.rad(hours * 360 / 12) - local minuteAngle = math.rad(minutes * 360) - local hourArrowLength, minuteArrowLength = 2.8, 4.5 - local xMinute, yMinute = round(x + math.sin(minuteAngle) * minuteArrowLength * 2), round(y - math.cos(minuteAngle) * minuteArrowLength) - local xHour, yHour = round(x + math.sin(hourAngle) * hourArrowLength * 2), round(y - math.cos(hourAngle) * hourArrowLength) - - y = y * 2 - doubleHeight.line(x, y, xMinute, yMinute * 2, 0xEEEEEE) - doubleHeight.line(x, y, xHour, yHour * 2, 0xEEEEEE) -end - -local function addItemToChatHistory(text, color) - text = GUI.stringWrap({text}, rayEngine.chatPanelWidth - 2) - table.insert(rayEngine.chatHistory, {color = color, text = text}) - if #rayEngine.chatHistory > rayEngine.chatHistoryLimit then table.remove(rayEngine.chatHistory, 1) end -end - -function rayEngine.chat(transparency) - local x, y = 1, buffer.screen.height - rayEngine.chatPanelHeight - 3 - buffer.square(x, y, rayEngine.chatPanelWidth, rayEngine.chatPanelHeight, 0x000000, 0xFFFFFF, " ", transparency or 50) - buffer.setDrawLimit(x, y, rayEngine.chatPanelWidth, rayEngine.chatPanelHeight) - local yMessage = y + rayEngine.chatPanelHeight - 1 - x = x + 1 - - for message = #rayEngine.chatHistory, 1, -1 do - for line = #rayEngine.chatHistory[message].text, 1, -1 do - buffer.text(x, yMessage, rayEngine.chatHistory[message].color or 0xFFFFFF, rayEngine.chatHistory[message].text[line]) - yMessage = yMessage - 1 - if yMessage < y then buffer.resetDrawLimit(); return end - end - end - - buffer.resetDrawLimit() -end - -function rayEngine.commandLine(transparency) - transparency = transparency or 50 - local inputPanelHeight = 3 - local x, y = 1, buffer.screen.height - inputPanelHeight + 1 - --Врубаем чат и рисуем все, включая его - rayEngine.chatEnabled = true - rayEngine.update() - --Рисуем панель ввода - buffer.square(x, y, buffer.screen.width, inputPanelHeight, 0x000000, 0xFFFFFF, " ", transparency) - - --Ввод данных - local text = GUI.input(x + 2, y + 1, buffer.screen.width - 4, 0xFFFFFF, "") - local words = {}; for word in string.gmatch(text, "[^%s]+") do table.insert(words, word) end - if #words > 0 then - if unicode.sub(words[1], 1, 1) == "/" then - words[1] = unicode.sub(words[1], 2, -1) - if words[1] == "time" then - if words[2] == "set" and words[3] and tonumber(words[3]) then - local newTime = tonumber(words[3]) - if newTime < 0 or newTime > rayEngine.world.dayNightCycle.length then - addItemToChatHistory("Время не может быть отрицательным и превышать длину суток (" .. rayEngine.world.dayNightCycle.length .. " секю)", 0xFF8888) - else - rayEngine.world.dayNightCycle.currentTime = math.floor(newTime) - addItemToChatHistory("Время успешно изменено на: " .. newTime, 0xFFDB40) - end - elseif words[2] == "get" then - addItemToChatHistory("Текущее время: " .. rayEngine.world.dayNightCycle.currentTime, 0xFFDB40) - addItemToChatHistory("Длина суток: " .. rayEngine.world.dayNightCycle.length, 0xFFDB40) - end - elseif words[1] == "help" then - addItemToChatHistory("Доступные команды:", 0xFFDB40) - addItemToChatHistory("/time get", 0xFFFFBF) - addItemToChatHistory("/time set ", 0xFFFFBF) - else - addItemToChatHistory("Неизвестная команда. Введите /help для получения списка команд", 0xFF8888) - end - else - addItemToChatHistory("Вы написали: " .. text, 0xFFFFFF) - end - end - - --Активируем таймер - if rayEngine.chatTimer then event.cancel(rayEngine.chatTimer) end - rayEngine.chatEnabled = true - rayEngine.chatTimer = event.timer(rayEngine.chatShowTime, function() rayEngine.chatEnabled = false; rayEngine.chatTimer = nil; update() end) -end - -function rayEngine.toggleMinimap() - rayEngine.minimapEnabled = not rayEngine.minimapEnabled -end - -function rayEngine.toggleCompass() - rayEngine.compassEnabled = not rayEngine.compassEnabled - if not rayEngine.compassEnabled then rayEngine.compassImage = nil end -end - -function rayEngine.toggleWatch() - rayEngine.watchEnabled = not rayEngine.watchEnabled - if not rayEngine.watchEnabled then rayEngine.watchImage = nil end -end - ----------------------------------------------------- Функции отрисовки мира ------------------------------------------------------------------ - -local function hRaycast(player, angle) - local rayInTop = math.sin( angle ) > 0 - - local tanAng = math.tan( angle ) - - local Ay = math.floor(rayEngine.player.position.y / rayEngine.tileWidth) * rayEngine.tileWidth; Ay = Ay + ( (rayInTop) and -1 or rayEngine.tileWidth ) - local Ax = rayEngine.player.position.x + (rayEngine.player.position.y - Ay) / tanAng - - local Ya = (rayInTop) and -rayEngine.tileWidth or rayEngine.tileWidth - local Xa = rayEngine.tileWidth / tanAng; Xa = Xa * ( (rayInTop) and 1 or -1 ) - - local x, y = math.floor(Ax / rayEngine.tileWidth), math.floor(Ay / rayEngine.tileWidth) - - while (rayEngine.map[y + 1] and not rayEngine.map[y + 1][x + 1]) do - Ax = Ax + Xa; Ay = Ay + Ya - - if (Ax < 0 or Ax > rayEngine.tileWidth * rayEngine.map.width or Ay < 0 or Ay > rayEngine.tileWidth * rayEngine.map.height) then - break - end - - x, y = math.floor(Ax / rayEngine.tileWidth), math.floor(Ay / rayEngine.tileWidth) - end - - return math.abs(rayEngine.player.position.x - Ax) / math.abs(math.cos( angle )) -end - -local function vRaycast(player, angle) - local rayInRight = math.cos( angle ) > 0 - - local tanAng = math.tan( angle ) - - local Bx = math.floor(rayEngine.player.position.x / rayEngine.tileWidth) * rayEngine.tileWidth; Bx = Bx + ( (rayInRight) and rayEngine.tileWidth or -1 ) - local By = rayEngine.player.position.y + (rayEngine.player.position.x - Bx) * tanAng - - local Xa = (rayInRight) and rayEngine.tileWidth or -rayEngine.tileWidth - local Ya = rayEngine.tileWidth * tanAng; Ya = Ya * ( (rayInRight) and -1 or 1 ) - - local x, y = math.floor(Bx / rayEngine.tileWidth), math.floor(By / rayEngine.tileWidth) - - while (rayEngine.map[y + 1] and not rayEngine.map[y + 1][x + 1]) do - Bx = Bx + Xa; By = By + Ya - - if (Bx < 0 or Bx > rayEngine.tileWidth * rayEngine.map.width or By < 0 or By > rayEngine.tileWidth * rayEngine.map.height) then - break - end - - x, y = math.floor(Bx / rayEngine.tileWidth), math.floor(By / rayEngine.tileWidth) - end - - return math.abs(rayEngine.player.position.y - By) / math.abs(math.sin( angle )) -end - -function rayEngine.drawWorld() - buffer.clear(rayEngine.world.colors.groundByTime) - buffer.square(1, 1, buffer.screen.width, rayEngine.horizonPosition, rayEngine.world.colors.sky.current) - - local startColumn = rayEngine.player.rotation - (rayEngine.player.fieldOfView / 2) - local endColumn = rayEngine.player.rotation + (rayEngine.player.fieldOfView / 2) - local step = rayEngine.player.fieldOfView / buffer.screen.width - - local startX = 1 - local distanceLimit = buffer.screen.height * 0.85 - local hDist, vDist, dist, height, startY, tileColor - for angle = startColumn, endColumn, step do - hDist = hRaycast(player, convertDegreesToRadians(angle) ) - vDist = vRaycast(player, convertDegreesToRadians(angle) ) - - -- local dist = math.min( hDist, vDist ) * math.cos( convertDegreesToRadians(angle) ) - dist = math.min( hDist, vDist ) - height = rayEngine.tileWidth / dist * rayEngine.distanceToProjectionPlane - startY = buffer.screen.height / 2 - height / 2 + 1 + rayEngine.wallsPosition - - --Рисуем сценку - tileColor = height > distanceLimit and rayEngine.world.colors.tile.byTime[#rayEngine.world.colors.tile.byTime] or rayEngine.world.colors.tile.byTime[math.floor(#rayEngine.world.colors.tile.byTime * height / distanceLimit)] - buffer.square(math.floor(startX), math.floor(startY), 1, height, tileColor, 0x000000, " ") - -- buffer.square(math.floor(startX), math.floor(startY), 1, height, 0x000000, 0x000000, " ") - startX = startX + 1 - end - - doDayNightCycle() -end - -function rayEngine.update() - rayEngine.drawWorld() - if rayEngine.minimapEnabled then rayEngine.drawMap(3, 2, 25, 13, 50) end - local xTools, yTools = 3, buffer.screen.height - 25 - if rayEngine.compassEnabled then rayEngine.compass(xTools, yTools); xTools = xTools + 30 end - if rayEngine.watchEnabled then rayEngine.watch(xTools, yTools) end - --rayEngine.drawWeapon() - if rayEngine.chatEnabled then rayEngine.chat() end - buffer.draw() -end - ----------------------------------------------------------------------------------------------------------------------------------- - -return rayEngine