diff --git a/.DS_Store b/.DS_Store index a7c5fa31..177bb94b 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 496ee2ca..00000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store \ No newline at end of file diff --git a/Applications/.DS_Store b/Applications/.DS_Store index 8214b749..68280067 100644 Binary files a/Applications/.DS_Store and b/Applications/.DS_Store differ diff --git a/Applications/Photoshop/Photoshop.lua b/Applications/Photoshop/Photoshop.lua index 89fbeae3..127fbca5 100755 --- a/Applications/Photoshop/Photoshop.lua +++ b/Applications/Photoshop/Photoshop.lua @@ -186,10 +186,10 @@ local function drawTransparentZone(x, y) local stro4ka1 = "" local stro4ka2 = "" if masterPixels.width % 2 == 0 then - stro4ka1 = string.rep("▒ ", masterPixels.width / 2) + stro4ka1 = string.rep("▒ ", math.floor(masterPixels.width / 2)) stro4ka2 = stro4ka1 else - stro4ka1 = string.rep("▒ ", masterPixels.width / 2) + stro4ka1 = string.rep("▒ ", math.floor(masterPixels.width / 2)) stro4ka2 = stro4ka1 .. "▒" end diff --git a/Applications/RayWalk/.DS_Store b/Applications/RayWalk/.DS_Store index 5c6c8702..45feb27c 100644 Binary files a/Applications/RayWalk/.DS_Store and b/Applications/RayWalk/.DS_Store differ diff --git a/Applications/RayWalk/RayWalk.lua b/Applications/RayWalk/RayWalk.lua index b376e6d1..671d3a92 100755 --- a/Applications/RayWalk/RayWalk.lua +++ b/Applications/RayWalk/RayWalk.lua @@ -19,7 +19,7 @@ for library in pairs(libraries) do if not _G[library] then _G[library] = require local applicationResourcesDirectory = MineOSCore.getCurrentApplicationResourcesDirectory() local localization = MineOSCore.getLocalization(applicationResourcesDirectory .. "Localization/") local worldsPath = applicationResourcesDirectory .. "Worlds/" -local rayWalkVersion = "RayWalk Tech Demo v3.4" +local rayWalkVersion = "RayWalk Tech Demo v3.5" ---------------------------------------------------------------------------------------------------------------------------------- @@ -128,10 +128,10 @@ local function menu() y = y + buttonHeight + 1 end - local lines = localization.controlsHelp + local lines = {}; for i = 1, #localization.controlsHelp do table.insert(lines, localization.controlsHelp[i]) end table.insert(lines, 1, " ") table.insert(lines, 1, {text = localization.controls, color = 0xFFFFFF}) - window:addTextBox(1, y, window.width, #lines, nil, 0xDDDDDD, lines, 1):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top); y = y + #lines + 1 + window:addTextBox(1, y, window.width, #lines, nil, 0xCCCCCC, lines, 1):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top); y = y + #lines + 1 window:draw(); buffer.draw(); window:handleEvents() end diff --git a/Applications/RayWalk/Worlds/ExampleWorld/Player.cfg b/Applications/RayWalk/Worlds/ExampleWorld/Player.cfg index 777a7e19..bc553c39 100755 --- a/Applications/RayWalk/Worlds/ExampleWorld/Player.cfg +++ b/Applications/RayWalk/Worlds/ExampleWorld/Player.cfg @@ -10,8 +10,8 @@ isCrouched = false, jumpHeight = 10, moveSpeed = 16, - rotationSpeed = 5, + rotationSpeed = 0.0872664, crouchHeight = 10, - fieldOfView = 60, + fieldOfView = 1.0471975, rotation = 0, } \ No newline at end of file diff --git a/Applications/RayWalk/Worlds/SundownBeams/Blocks.cfg b/Applications/RayWalk/Worlds/SundownBeams/Blocks.cfg deleted file mode 100755 index edc7dd40..00000000 --- a/Applications/RayWalk/Worlds/SundownBeams/Blocks.cfg +++ /dev/null @@ -1,26 +0,0 @@ -{ - { - color = 0xFFFFFF, - canBeDestroyed = false, - }, - { - color = 0xFFFFFF, - canBeDestroyed = true, - }, - { - color = 0xFF8888, - canBeDestroyed = true, - }, - { - color = 0x88FF88, - canBeDestroyed = true, - }, - { - color = 0xFF88FF, - canBeDestroyed = true, - }, - { - color = 0xFFEE60, - canBeDestroyed = true, - }, -} \ No newline at end of file diff --git a/Applications/RayWalk/Worlds/SundownBeams/Map.cfg b/Applications/RayWalk/Worlds/SundownBeams/Map.cfg deleted file mode 100755 index c4e7c04c..00000000 --- a/Applications/RayWalk/Worlds/SundownBeams/Map.cfg +++ /dev/null @@ -1,28 +0,0 @@ -{ - { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, 0x1, 0x1, 0x1, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1, 0x1, 0x1, 0x1, 0x1, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x1 }, - { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, -} \ No newline at end of file diff --git a/Applications/RayWalk/Worlds/SundownBeams/Player.cfg b/Applications/RayWalk/Worlds/SundownBeams/Player.cfg deleted file mode 100755 index 777a7e19..00000000 --- a/Applications/RayWalk/Worlds/SundownBeams/Player.cfg +++ /dev/null @@ -1,17 +0,0 @@ -{ - position = { - x = 5, - y = 5, - }, - health = { - maximum = 100, - current = 100, - }, - isCrouched = false, - jumpHeight = 10, - moveSpeed = 16, - rotationSpeed = 5, - crouchHeight = 10, - fieldOfView = 60, - rotation = 0, -} \ No newline at end of file diff --git a/Applications/RayWalk/Worlds/SundownBeams/World.cfg b/Applications/RayWalk/Worlds/SundownBeams/World.cfg deleted file mode 100755 index ae6f7c3f..00000000 --- a/Applications/RayWalk/Worlds/SundownBeams/World.cfg +++ /dev/null @@ -1,28 +0,0 @@ -{ - dayNightCycle = { - enabled = true, - currentTime = 100, - speed = 1, - length = 300, - }, - colors = { - ground = 0xEEEEEE, - clouds = 0xFFFFFF, - sky = { - 0x002440, - 0x002480, - 0x3349BF, - 0x6692FF, - 0x99DBFF, - 0x99DBFF, - 0x99DBFF, - 0x66B6FF, - 0x66B6FF, - 0xFFDB80, - 0xFFB640, - 0xCCBD00, - 0x000080, - 0x002440, - }, - }, -} \ No newline at end of file diff --git a/Applications/Robot/GeoMiner.lua b/Applications/Robot/GeoMiner.lua new file mode 100644 index 00000000..4d35d165 --- /dev/null +++ b/Applications/Robot/GeoMiner.lua @@ -0,0 +1,410 @@ + +local computer = require("computer") +local component = require("component") +local robot = require("robot") +local event = require("event") +local sides = require("sides") +local geo = component.geolyzer +local inventoryController = inventoryController + +------------------------------------------------------------------------------------------------------------------- + +local fuels = { + "minecraft:coal", + "minecraft:lava_bucket", + "minecraft:coal_block", +} + +local shittyResources = { + "minecraft:cobblestone", + "minecraft:grass", + "minecraft:dirt", + "minecraft:gravel", + "minecraft:sand", + "minecraft:sandstone", + "minecraft:torch", + "minecraft:planks", + "minecraft:fence", + "minecraft:chest", + "minecraft:monster_egg", + "minecraft:stonebrick", +} + +local oreSearchRadius = 5 +local searchPassesCount = 5 +local minimumOreHardness = 2.5 +local maximumOreHardness = 8 +local replaceToolDurabilityTrigger = 0.05 +local replaceToolRegex = "(minecraft:).+(_pickaxe)" +local rechargeTrigger = 0.1 +local dropShittyResourcesOnEmptySlots = 5 + +------------------------------------------------------------------------------------------------------------------- + +local program = {} +local robotPosition = {x = 0, y = 0, z = 0, rotation = 0} +local energyStatusCheckEnabled = true +local toolStatusCheckEnabled = true +local generatorIsAvailable = component.isAvailable("generator") + +function program.scan(radius, passes, minHardness, maxHardness) + local ores = {} + + -- Заносим все руды в массивыч руд + for pass = 1, passes do + print("Scan pass " .. pass .. " started...") + for x = -radius, radius do + for z = -radius, radius do + local stack = geo.scan(x, z, true) + for y = 1, #stack do + if stack[y] >= minHardness and stack[y] <= maxHardness then + -- Заполняем координатную сетку, если массивов еще не существует + ores[x] = ores[x] or {} + ores[x][y] = ores[x][y] or {} + + -- Если мы уже сканировали этот блок, то получаем среднюю плотность из двух значений + -- Если нет, то банально ставим полученное значение + if ores[x][y][z] then + ores[x][y][z] = (ores[x][y][z] + stack[y]) / 2 + else + ores[x][y][z] = stack[y] + end + + -- print("x=" .. x .. ", y=" .. y .. ", z=" .. z .. ", hardness=" .. stack[y]) + end + end + end + end + end + + -- Переебошиваем массив руд для более удобной работы с ним в линейном формате + -- Не забываем подчищать говнище за собой, а то роботы не резиновые + local newOres = {} + for x in pairs(ores) do + for y in pairs(ores[x]) do + for z in pairs(ores[x][y]) do + table.insert(newOres, {x = robotPosition.x + x, y = robotPosition.y + y - 33, z = robotPosition.z + z}) + ores[x][y][z] = nil + end + ores[x][y] = nil + end + ores[x]= nil + end + + return newOres +end + +local function getHardness(x, z) + local stack = geo.scan(x, z) + for i = 1, #stack do + print("i=" .. i .. ", val=" .. stack[i]) + event.pull("key_down") + end +end + +function program.move(direction) + while true do + local swingSuccess, swingReason = component.robot.swing(direction) + if swingSuccess or swingReason == "air" then + local moveSuccess, moveReason = component.robot.move(direction) + if moveSuccess then + break + end + else + if swingReason == "block" then + print("Unbreakable block detected, going to base") + program.returnToBase() + os.exit() + end + end + end + + if direction == sides.front or direction == sides.back then + local directionOffset = direction == sides.front and 1 or -1 + + if robotPosition.rotation == 0 then + robotPosition.x = robotPosition.x + directionOffset + elseif robotPosition.rotation == 1 then + robotPosition.z = robotPosition.z + directionOffset + elseif robotPosition.rotation == 2 then + robotPosition.x = robotPosition.x - directionOffset + elseif robotPosition.rotation == 3 then + robotPosition.z = robotPosition.z - directionOffset + end + elseif direction == sides.up or direction == sides.down then + local directionOffset = direction == sides.up and 1 or -1 + robotPosition.y = robotPosition.y + directionOffset + end +end + + +function program.returnToBase() + program.gotoPoint(0, robotPosition.y, 0) + program.turnToRequiredRotation(0) + program.gotoPoint(0, -2, 0) + program.tryToDropShittyResources() + program.gotoPoint(0, 0, 0) + program.dropAllResoucesIntoBaseChest() +end + +function program.getSlotWithFuel() + for slot = 1, component.robot.inventorySize() do + local stack = inventoryController.getStackInInternalSlot(slot) + if stack then + for fuel = 1, #fuels do + if stack.name == fuels[fuel] then + return slot + end + end + end + end +end + +function program.tryToRechargeByGenerator() + if generatorIsAvailable then + if component.generator.count() == 0 then + print("Generator is empty, trying to find some fuel in inventory") + local slot = program.getSlotWithFuel() + if slot then + print("Found slot with fuel: " .. slot) + local oldSlot = robot.select(slot) + component.generator.insert() + robot.select(oldSlot) + return + else + print("Slot with fuel not found") + end + end + end +end + +function program.checkEnergyStatus() + if computer.energy() / computer.maxEnergy() < rechargeTrigger then + print("Low energy level detected") + energyStatusCheckEnabled = false + -- Запоминаем старую позицию, шобы суда вернуться + local oldPosition = {x = robotPosition.x, y = robotPosition.y, z = robotPosition.z, rotation = robotPosition.rotation} + -- Пиздуем на базу за зарядкой + program.returnToBase() + -- Заряжаемся, пока энергия не достигнет более-менее максимума + while computer.energy() / computer.maxEnergy() < 0.99 do + print("Charging up: " .. math.floor(computer.energy() / computer.maxEnergy() * 100) .. "%") + os.sleep(1) + end + -- Пиздуем обратно + program.gotoPoint(oldPosition.x, oldPosition.y, oldPosition.z) + program.turnToRequiredRotation(oldPosition.rotation) + energyStatusCheckEnabled = true + end +end + +function program.turn(clockwise) + component.robot.turn(clockwise) + robotPosition.rotation = robotPosition.rotation + (clockwise and 1 or -1) + if robotPosition.rotation > 3 then + robotPosition.rotation = 0 + elseif robotPosition.rotation < 0 then + robotPosition.rotation = 3 + end +end + +function program.turnToRequiredRotation(requiredRotation) + local difference = robotPosition.rotation - requiredRotation + + if difference ~= 0 then + local fastestWay + if difference > 0 then + if difference > 2 then fastestWay = true else fastestWay = false end + else + if -difference > 2 then fastestWay = false else fastestWay = true end + end + + while robotPosition.rotation ~= requiredRotation do + program.turn(fastestWay) + end + end +end + +function program.gotoPoint(xTarget, yTarget, zTarget) + local xDistance = xTarget - robotPosition.x + local yDistance = yTarget - robotPosition.y + local zDistance = zTarget - robotPosition.z + + if yDistance ~= 0 then + local direction = yDistance > 0 and sides.up or sides.down + for i = 1, math.abs(yDistance) do program.move(direction) end + end + + if xDistance ~= 0 then + program.turnToRequiredRotation(xDistance > 0 and 0 or 2) + for i = 1, math.abs(xDistance) do program.move(sides.front) end + end + + if zDistance ~= 0 then + program.turnToRequiredRotation(zDistance > 0 and 1 or 3) + for i = 1, math.abs(zDistance) do program.move(sides.front) end + end + + -- Если количество пустых слотов меньше, чем лимит пустых слотов, + -- то выбрасываем весь дерьмовый шмот, указанный в массиве дерьмового шмота + program.tryToDropShittyResources() + + -- Если включена проверка энергосостояния, то делаем ее и возвращаемся на базу + -- для подзарядки, если требуется + if energyStatusCheckEnabled then program.checkEnergyStatus() end + + -- Проверяем также состояние инструментов + if toolStatusCheckEnabled then program.checkToolStatus() end + + -- А еще заправляем генератор + program.tryToRechargeByGenerator() +end + +function program.findNearestOre(ores) + local nearest + for i = 1, #ores do + local distance = math.sqrt((ores[i].x - robotPosition.x) ^ 2 + (ores[i].y - robotPosition.y) ^ 2 + (ores[i].z - robotPosition.z) ^ 2) + if not nearest or distance < nearest.distance then + nearest = {x = ores[i].x, y = ores[i].y, z = ores[i].z, distance = distance, oreIndex = i} + end + end + return nearest +end + +function program.scanAndDig(radius, passes, minHardness, maxHardness, bedrockLocation) + local ores = program.scan(radius, passes, minHardness, maxHardness) + print("Scanning finished, count of resources to mine: " .. #ores) + while #ores > 0 do + local nearest = program.findNearestOre(ores) + if nearest.y >= bedrockLocation and nearest.y < 0 then + -- print("Found next nearest ore: (" .. nearest.x .. "; " .. nearest.y .. "; " .. nearest.z .. ")") + program.gotoPoint(nearest.x, nearest.y, nearest.z) + end + table.remove(ores, nearest.oreIndex) + end +end + +function program.getBedrockLocation() + while true do + local success, reason = component.robot.swing(sides.down) + if success or reason == "air" then + program.move(sides.down) + else + if reason == "block" then + print("Bedrock location is: " .. robotPosition.y) + return robotPosition.y + end + end + end +end + +function program.getEmptySlotsCount() + local count = 0 + for slot = 1, robot.inventorySize() do + count = count + (robot.count(slot) == 0 and 1 or 0) + end + return count +end + +function program.tryToDropShittyResources() + if program.getEmptySlotsCount() < dropShittyResourcesOnEmptySlots then + print("Trying to drop all shitty resources to free some slots for mining") + for slot = 1, robot.inventorySize() do + local stack = inventoryController.getStackInInternalSlot(slot) + if stack then + for i = 1, #shittyResources do + if stack.name == shittyResources[i] then + robot.select(slot) + robot.drop() + end + end + end + end + + if program.getEmptySlotsCount() < dropShittyResourcesOnEmptySlots - 2 then + local oldPosition = {x = robotPosition.x, y = robotPosition.y, z = robotPosition.z, rotation = robotPosition.rotation} + program.returnToBase() + program.gotoPoint(oldPosition.x, oldPosition.y, oldPosition.z) + program.turnToRequiredRotation(oldPosition.rotation) + end + + robot.select(1) + end +end + +function program.dropAllResoucesIntoBaseChest() + print("Dropping all mined resources to chest on base") + for slot = 1, robot.inventorySize() do + local stack = inventoryController.getStackInInternalSlot(slot) + if stack then + if not string.match(stack.name, replaceToolRegex) then + robot.select(slot) + robot.drop() + end + end + end + robot.select(1) +end + +function program.checkToolStatus() + if robot.durability() < replaceToolDurabilityTrigger then + print("Equipped tool durability lesser then " .. replaceToolDurabilityTrigger) + local success = false + + for slot = 1, robot.inventorySize() do + local stack = inventoryController.getStackInInternalSlot(slot) + if stack then + if string.match(stack.name, replaceToolRegex) and stack.damage / stack.maxDamage < replaceToolDurabilityTrigger then + local oldSlot = robot.select(slot) + inventoryController.equip() + robot.select(oldSlot) + success = true + break + end + end + end + + if not success and toolStatusCheckEnabled then + toolStatusCheckEnabled = false + returnToBase() + print("No one useable tool are found in inventory, going back to base") + os.exit() + else + print("Successfullty switched tool to another from inventory") + end + end +end + +------------------------------------------------------------------------------------------------------------------- + +-- getHardness(1, 0) +-- program.checkToolStatus() +-- program.move(sides.front) + +-- Выбираем сразу первый слотик по умолчанию +robot.select(1) +-- Определяем позицию говна +print("Going deeper to determine bedrock location...") +local bedrockLocation = program.getBedrockLocation() + 4 +-- Ебошим стартовую точку после определения позиции говна, и если она слишком высоко, то робот начнет как раз от нее же +local startPoint = bedrockLocation + 32 +if startPoint > 0 then startPoint = 0 end + +-- Пиздуем на старт и вкалываем до посинения +program.gotoPoint(0, startPoint, 0) +program.scanAndDig(oreSearchRadius, searchPassesCount, minimumOreHardness, maximumOreHardness, bedrockLocation) + +-- В конце возвращаемся на начало и ожидаем, че уж там +program.returnToBase() + + + + + + + + + + + + diff --git a/Applications/Robot/untitled.lua b/Applications/Robot/untitled.lua new file mode 100644 index 00000000..bb481050 --- /dev/null +++ b/Applications/Robot/untitled.lua @@ -0,0 +1,16 @@ + +_G.modem = component.proxy(component.list("modem")()) +_G.inventory_controller = component.proxy(component.list("modem")()) +_G.drone = component.proxy(component.list("drone")()) +_G.port = 512 + +modem.open(port) + +while true do + local e = {computer.pullSignal()} + if e[1] == "modem_message" then + if e[6] == "executeScript" then + modem.send(e[2], port, "executionResult", xpcall(load(e[7]), debug.traceback())) + end + end +end diff --git a/lib/GUI.lua b/lib/GUI.lua index ce7374cc..cc5fc20b 100755 --- a/lib/GUI.lua +++ b/lib/GUI.lua @@ -90,7 +90,7 @@ GUI.objectTypes = enum( -- Universal method to check if object was clicked by following coordinates local function isObjectClicked(object, x, y) - if x >= object.x and y >= object.y and x <= object.x + object.width - 1 and y <= object.y + object.height - 1 and not object.disabled and not object.hidden then return true end + if x >= object.x and y >= object.y and x <= object.x + object.width - 1 and y <= object.y + object.height - 1 and not object.disabled and not object.isHidden then return true end return false end @@ -155,7 +155,7 @@ end function GUI.getClickedObject(container, xEvent, yEvent) local clickedObject, clickedIndex for objectIndex = #container.children, 1, -1 do - if not container.children[objectIndex].hidden then + if not container.children[objectIndex].isHidden then container.children[objectIndex].x, container.children[objectIndex].y = container.children[objectIndex].localPosition.x + container.x - 1, container.children[objectIndex].localPosition.y + container.y - 1 if container.children[objectIndex].children and #container.children[objectIndex].children > 0 then clickedObject, clickedIndex = GUI.getClickedObject(container.children[objectIndex], xEvent, yEvent) @@ -213,6 +213,18 @@ local function containerObjectMoveToBack(object) table.remove(object.parent.children, objectIndex + 1) end +local function containerGetFirstParent(object) + if object.parent then + local currentParent = object.parent + while currentParent.parent do + currentParent = currentParent.parent + end + return currentParent + else + error("Object doesn't have any parents") + end +end + -- Add any object as children to parent container with specified objectType function GUI.addChildToContainer(container, object, objectType) object.type = objectType or GUI.objectTypes.unknown @@ -222,6 +234,7 @@ function GUI.addChildToContainer(container, object, objectType) object.moveToBack = containerObjectMoveToBack object.moveForward = containerObjectMoveForward object.moveBackward = containerObjectMoveBackward + object.getFirstParent = containerGetFirstParent object.localPosition = {x = object.x, y = object.y} table.insert(container.children, object) @@ -319,10 +332,15 @@ local function addComboBoxObjectToContainer(container, ...) return GUI.addChildToContainer(container, GUI.comboBox(...), GUI.objectTypes.comboBox) end +-- Add Menu object to container +local function addMenuObjectToContainer(container, ...) + return GUI.addChildToContainer(container, GUI.menu(...), GUI.objectTypes.menu) +end + -- Recursively draw container's content including all children container's content local function drawContainerContent(container) for objectIndex = 1, #container.children do - if not container.children[objectIndex].hidden then + if not container.children[objectIndex].isHidden then container.children[objectIndex].x, container.children[objectIndex].y = container.children[objectIndex].localPosition.x + container.x - 1, container.children[objectIndex].localPosition.y + container.y - 1 if container.children[objectIndex].children then -- cyka blyad @@ -353,7 +371,7 @@ function GUI.container(x, y, width, height) container.children = {} container.draw = drawContainerContent container.getClickedObject = GUI.getClickedObject - container.deleteObjects = deleteContainersContent + container.deleteChildren = deleteContainersContent container.addChild = GUI.addChildToContainer container.addObject = addEmptyObjectToContainer @@ -374,6 +392,7 @@ function GUI.container(x, y, width, height) container.addProgressBar = addProgressBarObjectToContainer container.addChart = addChartObjectToContainer container.addComboBox = addComboBoxObjectToContainer + container.addMenu = addMenuObjectToContainer return container end @@ -634,6 +653,7 @@ local function showDropDownMenu(object) drawDropDownMenuElement(object, itemIndex, true) buffer.draw() os.sleep(0.2) + if object.items[itemIndex].onItemSelected then object.items[itemIndex].onItemSelected() end quit() return object.items[itemIndex].text, itemIndex end diff --git a/lib/MineOSCore.lua b/lib/MineOSCore.lua index 14722937..60764175 100755 --- a/lib/MineOSCore.lua +++ b/lib/MineOSCore.lua @@ -1,5 +1,5 @@ ----------------------------------------------- Библиотеки ------------------------------------------------------------------------ +---------------------------------------------- Libraries ------------------------------------------------------------------------ local libraries = { component = "component", @@ -16,13 +16,14 @@ local libraries = { for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end; libraries = nil ------------------------------------------------------------------------------------------------------------------------------------ +---------------------------------------------- Core constants ------------------------------------------------------------------------ local MineOSCore = {} MineOSCore.showApplicationIcons = true MineOSCore.iconWidth = 12 MineOSCore.iconHeight = 6 +MineOSCore.iconClickDelay = 0.1 MineOSCore.paths = {} MineOSCore.paths.OS = "/MineOS/" @@ -34,16 +35,17 @@ MineOSCore.paths.pictures = MineOSCore.paths.OS .. "Pictures/" MineOSCore.paths.desktop = MineOSCore.paths.OS .. "Desktop/" MineOSCore.paths.applicationList = MineOSCore.paths.system .. "OS/Applications.txt" MineOSCore.paths.trash = MineOSCore.paths.OS .. "Trash/" +MineOSCore.paths.OSSettings = MineOSCore.paths.system .. "OS/OSSettings.cfg" -MineOSCore.sortingMethods = { - type = 0, - name = 1, - date = 2, -} +MineOSCore.sortingMethods = enum( + "type", + "name", + "date" +) MineOSCore.localization = {} ------------------------------------------------------------------------------------------------------------------------------------ +---------------------------------------------- Current sсript processing methods ------------------------------------------------------------------------ function MineOSCore.getCurrentScriptDirectory() return fs.path(getCurrentScript()) @@ -66,16 +68,16 @@ function MineOSCore.getCurrentApplicationLocalization() return MineOSCore.getLocalization(MineOSCore.getCurrentApplicationResourcesDirectory() .. "Localization/") end ------------------------------------------------------------------------------------------------------------------------------------ +---------------------------------------------- Filesystem-related methods ------------------------------------------------------------------------ local function getFilenameAndFormat(path) local fileName, format = string.match(path, "^(.+)(%..+)$") - return fileName or path, format and string.gsub(format, "/", "") or nil + return (fileName or path), (format and string.gsub(format, "%/+$", "") or nil) end local function getFilePathAndName(path) local filePath, fileName = string.math(path, "^(.+%/)(.+)$") - return filePath or "/", fileName or path + return (filePath or "/"), (fileName or path) end function MineOSCore.getFileFormat(path) @@ -88,22 +90,79 @@ function MineOSCore.hideFileFormat(path) return fileName end -function MineOSCore.getFileName(path) - local filePath, fileName = getFilePathAndName(path) - return fileName -end - -function MineOSCore.getFilePath(path) - local filePath, fileName = getFilePathAndName(path) - return filePath -end - function MineOSCore.isFileHidden(path) if string.match(path, "^%..+$") then return true end return false end ------------------------------------------------------------------------------------------------------------------------------------ +function MineOSCore.getFileList(path) + if not fs.exists(path) then error("Failed to get file list: directory \"" .. tostring(path) .. "\" doesn't exists") end + if not fs.isDirectory(path) then error("Failed to get file list: path \"" .. tostring(path) .. "\" is not a directory") end + + local fileList = {} + for file in fs.list(path) do table.insert(fileList, file) end + return fileList +end + +function MineOSCore.sortFileList(path, fileList, sortingMethod, showHiddenFiles) + local sortedFileList = {} + + if sortingMethod == MineOSCore.sortingMethods.type then + local typeList = {} + for i = 1, #fileList do + local fileFormat = MineOSCore.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 MineOSCore.sortingMethods.name then + sortedFileList = fileList + elseif MineOSCore.sortingMethods.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: " .. tostring(sortingMethod)) + end + + local i = 1 + while i <= #sortedFileList do + if not showHiddenFiles and MineOSCore.isFileHidden(sortedFileList[i]) then + table.remove(sortedFileList, i) + else + i = i + 1 + end + end + + return sortedFileList +end + +---------------------------------------------- MineOS Icons related methods ------------------------------------------------------------------------ + +function MineOSCore.saveOSSettings() + table.toFile(MineOSCore.paths.OSSettings, _G.OSSettings, true) +end + +function MineOSCore.loadOSSettings() + _G.OSSettings = table.fromFile(MineOSCore.paths.OSSettings) +end function MineOSCore.loadIcon(name, path) if not MineOSCore.icons[name] then MineOSCore.icons[name] = image.load(path) end @@ -131,60 +190,187 @@ function MineOSCore.init() MineOSCore.loadStandartIcons() end ------------------------------------------------------------------------------------------------------------------------------------ - ---Отрисовка одной иконки -function MineOSCore.drawIcon(x, y, path, showFileFormat, nameColor, name) - local fileFormat = MineOSCore.getFileFormat(path) - local icon - - if fs.isDirectory(path) then - if fileFormat == ".app" then +function MineOSCore.analyseIconFormat(iconObject) + if iconObject.isDirectory then + if iconObject.format == ".app" then if MineOSCore.showApplicationIcons then - icon = "cyka" - MineOSCore.icons[icon] = image.load(path .. "/Resources/Icon.pic") + iconObject.iconImage.image = image.load(iconObject.path .. "/Resources/Icon.pic") else - icon = "application" + iconObject.iconImage.image = MineOSCore.icons.application + end + + iconObject.launch = function() + ecs.applicationHelp(iconObject.path) + MineOSCore.safeLaunch(iconObject.path .. "/" .. MineOSCore.hideFileFormat(fs.name(iconObject.path)) .. ".lua") end else - icon = "folder" + iconObject.iconImage.image = MineOSCore.icons.folder + iconObject.launch = function() + MineOSCore.safeLaunch("/MineOS/Applications/Finder.app/Finder.lua", "open", iconObject.path) + end end else - if fileFormat == ".lnk" then - MineOSCore.drawIcon(x, y, ecs.readShortcut(path), showFileFormat, nameColor, fs.name(path)) - buffer.set(x + MineOSCore.iconWidth - 3, y + MineOSCore.iconHeight - 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 == ".paste" then - icon = "pastebin" - elseif fileFormat == ".pkg" then - icon = "archive" - elseif fileFormat == ".3dm" then - icon = "model3D" - elseif not fs.exists(path) then - icon = "fileNotExists" + if iconObject.format == ".lnk" then + iconObject.shortcutPath = ecs.readShortcut(iconObject.path) + iconObject.shortcutFormat = MineOSCore.getFileFormat(iconObject.shortcutPath) + iconObject.shortcutIsDirectory = fs.isDirectory(iconObject.shortcutPath) + iconObject.isShortcut = true + + local shortcutIconObject = MineOSCore.analyseIconFormat({ + path = iconObject.shortcutPath, + format = iconObject.shortcutFormat, + isDirectory = iconObject.shortcutIsDirectory, + iconImage = iconObject.iconImage + }) + + iconObject.iconImage.image = shortcutIconObject.iconImage.image + iconObject.launch = shortcutIconObject.launch + + shortcutIconObject = nil + elseif iconObject.format == ".cfg" or iconObject.format == ".config" then + iconObject.iconImage.image = MineOSCore.icons.config + iconObject.launch = function() + ecs.prepareToExit() + MineOSCore.safeLaunch("/bin/edit.lua", icon.path) + end + elseif iconObject.format == ".txt" or iconObject.format == ".rtf" then + iconObject.iconImage.image = MineOSCore.icons.text + iconObject.launch = function() + ecs.prepareToExit() + MineOSCore.safeLaunch("/bin/edit.lua", icon.path) + end + elseif iconObject.format == ".lua" then + iconObject.iconImage.image = MineOSCore.icons.lua + iconObject.launch = function() + ecs.prepareToExit() + MineOSCore.safeLaunch("/bin/edit.lua", icon.path) + end + elseif iconObject.format == ".pic" or iconObject.format == ".png" then + iconObject.iconImage.image = MineOSCore.icons.image + iconObject.launch = function() + MineOSCore.safeLaunch("/MineOS/Applications/Viewer.app/Viewer.lua", "open", icon.path) + end + elseif iconObject.format == ".pkg" or iconObject.format == ".zip" then + iconObject.iconImage.image = MineOSCore.icons.archive + iconObject.launch = function() + zip.unarchive(icon.path, (fs.path(icon.path) or "")) + end + elseif iconObject.format == ".3dm" then + iconObject.iconImage.image = MineOSCore.icons.model3D + iconObject.launch = function() + MineOSCore.safeLaunch("/MineOS/Applications/3DPrint.app/3DPrint.lua", "open", icon.path) + end + elseif not fs.exists(iconObject.path) then + iconObject.iconImage.image = MineOSCore.icons.fileNotExists + iconObject.launch = function() + GUI.error("Application is corrupted") + end else - icon = "script" + iconObject.iconImage.image = MineOSCore.icons.script + iconObject.launch = function() + ecs.prepareToExit() + MineOSCore.safeLaunch("/bin/edit.lua", icon.path) + end end end - --Рисуем иконку - buffer.image(x + 2, y, MineOSCore.icons[icon]) + return iconObject +end - --Делаем текст для иконки - local text = name or fs.name(path) - if not showFileFormat and fileFormat then text = unicode.sub(text, 1, -(unicode.len(fileFormat) + 1)) end - text = ecs.stringLimit("end", text, MineOSCore.iconWidth) - x = x + math.floor(MineOSCore.iconWidth / 2 - unicode.len(text) / 2) - --Рисуем текст под иконкой - buffer.text(x, y + MineOSCore.iconHeight - 1, nameColor or 0xffffff, text) +function MineOSCore.getParametersForDrawingIcons(fieldWidth, fieldHeight, xSpaceBetweenIcons, ySpaceBetweenIcons) + local xCountOfIcons, yCountOfIcons = math.floor(fieldWidth / (MineOSCore.iconWidth + xSpaceBetweenIcons)), math.floor(fieldHeight / (MineOSCore.iconHeight + ySpaceBetweenIcons)) + local totalCountOfIcons = xCountOfIcons * yCountOfIcons + return xCountOfIcons, yCountOfIcons, totalCountOfIcons +end + +function MineOSCore.createIconObject(x, y, path, textColor) + local iconObject = GUI.container(x, y, MineOSCore.iconWidth, MineOSCore.iconHeight) + + iconObject.path = path + iconObject.isDirectory = fs.isDirectory(iconObject.path) + iconObject.format = MineOSCore.getFileFormat(iconObject.path) + iconObject.showFormat = false + iconObject.isShortcut = false + iconObject.isSelected = false + + iconObject.iconImage = iconObject:addImage(3, 1, {width = 8, height = 4}) + iconObject.textLabel = iconObject:addLabel(1, MineOSCore.iconHeight, MineOSCore.iconWidth, 1, textColor, fs.name(iconObject.path)):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top) + + local oldDraw = iconObject.draw + iconObject.draw = function(iconObject) + if iconObject.isSelected then buffer.square(iconObject.x, iconObject.y, iconObject.width, iconObject.height, 0xFFFFFF, 0x000000, " ", 50) end + if iconObject.showFormat then iconObject.textLabel.text = fs.name(iconObject.path) else iconObject.textLabel.text = MineOSCore.hideFileFormat(fs.name(iconObject.path)) end + oldDraw(iconObject) + if iconObject.isShortcut then buffer.set(iconObject.iconImage.x + iconObject.iconImage.width - 1, iconObject.iconImage.y + iconObject.iconImage.height - 1, 0xFFFFFF, 0x000000, "<") end + end + + -- Поддержка изменяемых извне функций правого и левого кликов + iconObject.onLeftClick = MineOSCore.iconLeftClick + iconObject.onRightClick = MineOSCore.iconRightClick + + -- Обработка клика непосредственно на иконку + iconObject.iconImage.onTouch = function(eventData) + iconObject.isSelected = true + local firstParent = iconObject:getFirstParent() + firstParent:draw() + + if eventData[5] == 0 then + os.sleep(MineOSCore.iconClickDelay) + iconObject.onLeftClick(iconObject, eventData) + else + iconObject.onRightClick(iconObject, eventData) + end + + iconObject.isSelected = false + firstParent:draw() + end + + -- Онализ формата и прочего говна иконки для последующего получения изображения иконки и функции-лаунчера + MineOSCore.analyseIconFormat(iconObject) + + return iconObject +end + +local function updateIconFieldFileList(iconField) + iconField.fileList = MineOSCore.getFileList(iconField.workPath) + iconField.fileList = MineOSCore.sortFileList(iconField.workPath, iconField.fileList, iconField.sortingMethod, iconField.showHiddenFiles) + iconField.children = {} + + local xPos, yPos, counter = 1, 1, 1 + for i = iconField.fromFile, iconField.fromFile + iconField.iconCount.total - 1 do + if not iconField.fileList[i] then break end + + iconField:addChild(MineOSCore.createIconObject(xPos, yPos, iconField.workPath .. iconField.fileList[i], iconField.colors.iconText, iconField.showFileFormat), GUI.objectTypes.container) + + xPos, counter = xPos + MineOSCore.iconWidth + iconField.spaceBetweenIcons.x, counter + 1 + if counter > iconField.iconCount.width then + xPos, counter = 1, 1 + yPos = yPos + MineOSCore.iconHeight + iconField.spaceBetweenIcons.y + end + end + + return iconField +end + +function MineOSCore.createIconField(x, y, width, height, xCountOfIcons, yCountOfIcons, totalCountOfIcons, xSpaceBetweenIcons, ySpaceBetweenIcons, iconTextColor, showFileFormat, showHiddenFiles, sortingMethod, workPath) + local iconField = GUI.container(x, y, width, height) + + iconField.colors = {iconText = iconTextColor} + + iconField.iconCount = {} + iconField.spaceBetweenIcons = {x = xSpaceBetweenIcons, y = ySpaceBetweenIcons} + iconField.iconCount.width, iconField.iconCount.height, iconField.iconCount.total = xCountOfIcons, yCountOfIcons, totalCountOfIcons + + iconField.workPath = workPath + iconField.showFileFormat = showFileFormat + iconField.showHiddenFiles = showHiddenFiles + iconField.sortingMethod = sortingMethod + iconField.fileList = {} + iconField.fromFile = fromFile + + iconField.updateFileList = updateIconFieldFileList + + return iconField end ----------------------------------------------------------------------------------------------------------------------------------- @@ -369,10 +555,6 @@ function MineOSCore.safeLaunch(path, ...) -- end -- end - -- ecs.error("EXISTS: " .. tostring(applicationExists)) - -- ecs.error("PATH: " .. errorPath .. ", ERRORLINE: " .. errorLine) - -- ecs.error("REASON: " .. finalReason) - drawErrorWindow(errorPath, programVersion, errorLine, finalReason, applicationExists) else GUI.error("Unknown error in lib/MineOSCore.lua due program execution: possible reason is \"" .. tostring(finalReason) .. "\"") @@ -385,120 +567,26 @@ end ----------------------------------------------------------------------------------------------------------------------------------- --- Запуск приложения -function MineOSCore.launchIcon(path, translate) - --Получаем файл формат заранее - local fileFormat = ecs.getFileFormat(path) - local isDirectory = fs.isDirectory(path) - --Если это приложение - if fileFormat == ".app" then - ecs.applicationHelp(path) - MineOSCore.safeLaunch(path .. "/" .. ecs.hideFileFormat(fs.name(path)) .. ".lua") - --Если это папка - elseif (fileFormat == "" or fileFormat == nil) and isDirectory then - MineOSCore.safeLaunch("/MineOS/Applications/Finder.app/Finder.lua", "open", path) - --Если это обычный луа файл - т.е. скрипт - elseif fileFormat == ".lua" or fileFormat == nil then - buffer.clear(0x262626) - ecs.prepareToExit() - MineOSCore.safeLaunch(path) - - --Если это фоточка - elseif fileFormat == ".pic" then - MineOSCore.safeLaunch("MineOS/Applications/Viewer.app/Viewer.lua", "open", path) - - --Если это 3D-модель - elseif fileFormat == ".3dm" then - MineOSCore.safeLaunch("MineOS/Applications/3DPrint.app/3DPrint.lua", "open", path) - - --Если это текст или конфиг или языковой - elseif fileFormat == ".txt" or fileFormat == ".cfg" or fileFormat == ".lang" then - ecs.prepareToExit() - MineOSCore.safeLaunch("bin/edit.lua", path) - - --Если это ярлык - elseif fileFormat == ".lnk" then - local shortcutLink = ecs.readShortcut(path) - if fs.exists(shortcutLink) then - MineOSCore.launchIcon(shortcutLink) +function MineOSCore.iconLeftClick(iconObject, eventData) + if iconObject.isDirectory then + if iconObject.format == ".app" then + iconObject.launch() + computer.pushSignal("MineOSCore", "updateFileList") else - GUI.error(MineOSCore.localization.shortcutIsCorrupted) - end - - --Если это архив - elseif fileFormat == ".zip" then - zip.unarchive(path, (fs.path(path) or "")) - end -end ------------------------------------------------------------------------------------------------------------------------------------ - -function MineOSCore.getParametersForDrawingIcons(fieldWidth, fieldHeight, xSpaceBetweenIcons, ySpaceBetweenIcons) - local xCountOfIcons, yCountOfIcons = math.floor(fieldWidth / (MineOSCore.iconWidth + xSpaceBetweenIcons)), math.floor(fieldHeight / (MineOSCore.iconHeight + ySpaceBetweenIcons)) - local totalCountOfIcons = xCountOfIcons * yCountOfIcons - return xCountOfIcons, yCountOfIcons, totalCountOfIcons -end - -function MineOSCore.drawIconField(x, y, xCountOfIcons, yCountOfIcons, fromIcon, totalCountOfIcons, xSpaceBetweenIcons, ySpaceBetweenIcons, path, fileList, showFileFormat, iconTextColor) - local iconObjects = {} - - local xPos, yPos, iconCounter = x, y, 1 - for i = fromIcon, (fromIcon + totalCountOfIcons - 1) do - if not fileList[i] then break end - - local iconObject = GUI.object(xPos, yPos, MineOSCore.iconWidth, MineOSCore.iconHeight) - iconObject.path = path .. fileList[i] - table.insert(iconObjects, iconObject) - MineOSCore.drawIcon(xPos, yPos, iconObject.path, showFileFormat, iconTextColor) - - xPos = xPos + MineOSCore.iconWidth + xSpaceBetweenIcons - iconCounter = iconCounter + 1 - if iconCounter > xCountOfIcons then - xPos = x - yPos = yPos + MineOSCore.iconHeight + ySpaceBetweenIcons - iconCounter = 1 - end - end - - return iconObjects -end - ------------------------------------------------------------------------------------------------------------------------------------ - -local function executeMethod(methodArray) - methodArray.method(table.unpack(methodArray.arguments)) -end - -function MineOSCore.iconSelect(icon, selectionColor, selectionTransparency, iconTextColor) - local oldPixelsOfIcon = buffer.copy(icon.x, icon.y, MineOSCore.iconWidth, MineOSCore.iconHeight) - buffer.square(icon.x, icon.y, MineOSCore.iconWidth, MineOSCore.iconHeight, selectionColor, 0xFFFFFF, " ", selectionTransparency) - MineOSCore.drawIcon(icon.x, icon.y, icon.path, false, iconTextColor) - buffer.draw() - return oldPixelsOfIcon -end - -function MineOSCore.iconLeftClick(icon, oldPixelsOfIcon, fileFormat, drawAllMethod, fullRefreshMethod, changeCurrentPathMethod) - if fs.isDirectory(icon.path) then - if fileFormat == ".app" then - MineOSCore.launchIcon(icon.path) - executeMethod(fullRefreshMethod) - else - executeMethod(changeCurrentPathMethod) - executeMethod(drawAllMethod) + computer.pushSignal("MineOSCore", "updateFileListAndBufferTrueRedraw") end else - MineOSCore.launchIcon(icon.path) - buffer.start() - executeMethod(fullRefreshMethod) - -- GUI.error("Скрипт выполнен успешно") + iconObject.launch() + computer.pushSignal("MineOSCore", "updateFileListAndBufferTrueRedraw") end end -function MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, somethingCanBeAddedToDock, drawAllMethod, fullRefreshMethod, changeCurrentPathMethod) +function MineOSCore.iconRightClick(icon, eventData) local action -- Разные контекстные меню - if fs.isDirectory(icon.path) then - if fileFormat == ".app" then + if icon.isDirectory then + if icon.format == ".app" then action = GUI.contextMenu(eventData[3], eventData[4], {MineOSCore.localization.contextMenuShowPackageContent}, "-", @@ -506,7 +594,7 @@ function MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, {MineOSCore.localization.contextMenuCopy}, "-", {MineOSCore.localization.contextMenuRename}, - {MineOSCore.localization.contextMenuCreateShortcut, fileFormat == ".lnk"}, + {MineOSCore.localization.contextMenuCreateShortcut, icon.format == ".lnk"}, -- "-", -- {MineOSCore.localization.contextMenuUploadToPastebin, true}, "-", @@ -518,7 +606,7 @@ function MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, {MineOSCore.localization.contextMenuCut}, {MineOSCore.localization.contextMenuCopy}, {MineOSCore.localization.contextMenuRename}, - {MineOSCore.localization.contextMenuCreateShortcut, fileFormat == ".lnk"}, + {MineOSCore.localization.contextMenuCreateShortcut, icon.format == ".lnk"}, "-", {MineOSCore.localization.contextMenuArchive}, "-", @@ -526,7 +614,7 @@ function MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, ):show() end else - if fileFormat == ".pic" then + if icon.format == ".pic" then action = GUI.contextMenu(eventData[3], eventData[4], -- {MineOSCore.localization.contextMenuEdit}, {MineOSCore.localization.contextMenuEditInPhotoshop}, @@ -535,14 +623,14 @@ function MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, {MineOSCore.localization.contextMenuCut}, {MineOSCore.localization.contextMenuCopy}, {MineOSCore.localization.contextMenuRename}, - {MineOSCore.localization.contextMenuCreateShortcut, fileFormat == ".lnk"}, + {MineOSCore.localization.contextMenuCreateShortcut, icon.format == ".lnk"}, -- "-", -- {MineOSCore.localization.contextMenuUploadToPastebin, true}, "-", {MineOSCore.localization.contextMenuAddToDock}, {MineOSCore.localization.contextMenuDelete, false} ):show() - elseif fileFormat == ".lua" then + elseif icon.format == ".lua" then action = GUI.contextMenu(eventData[3], eventData[4], {MineOSCore.localization.contextMenuEdit}, {MineOSCore.localization.contextMenuFlashEEPROM, (not component.isAvailable("eeprom") or fs.size(icon.path) > 4096)}, @@ -551,7 +639,7 @@ function MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, {MineOSCore.localization.contextMenuCut}, {MineOSCore.localization.contextMenuCopy}, {MineOSCore.localization.contextMenuRename}, - {MineOSCore.localization.contextMenuCreateShortcut, fileFormat == ".lnk"}, + {MineOSCore.localization.contextMenuCreateShortcut, icon.format == ".lnk"}, -- "-", -- {MineOSCore.localization.contextMenuUploadToPastebin, true}, "-", @@ -566,7 +654,7 @@ function MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, {MineOSCore.localization.contextMenuCut}, {MineOSCore.localization.contextMenuCopy}, {MineOSCore.localization.contextMenuRename}, - {MineOSCore.localization.contextMenuCreateShortcut, fileFormat == ".lnk"}, + {MineOSCore.localization.contextMenuCreateShortcut, icon.format == ".lnk"}, -- "-", -- {MineOSCore.localization.contextMenuUploadToPastebin, true}, "-", @@ -578,102 +666,55 @@ function MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, if action == MineOSCore.localization.contextMenuEdit then ecs.prepareToExit() - MineOSCore.safeLaunch("bin/edit.lua", icon.path) - executeMethod(fullRefreshMethod) + MineOSCore.safeLaunch("/bin/edit.lua", icon.path) + computer.pushSignal("MineOSCore", "updateFileListAndBufferTrueRedraw") elseif action == MineOSCore.localization.contextMenuEditInPhotoshop then MineOSCore.safeLaunch("MineOS/Applications/Photoshop.app/Photoshop.lua", "open", icon.path) - executeMethod(fullRefreshMethod) - -- buffer.paste(1, 1, oldPixelsOfFullScreen) - -- drawAll(true) + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuAddToFavourites then - -- addToFavourites(fs.name(path), path) computer.pushSignal("finderFavouriteAdded", icon.path) - executeMethod(drawAllMethod) elseif action == MineOSCore.localization.contextMenuShowPackageContent then - executeMethod(changeCurrentPathMethod) - executeMethod(drawAllMethod) - -- changePath(path) - -- drawAll() + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuCopy then _G.clipboard = icon.path - executeMethod(drawAllMethod) elseif action == MineOSCore.localization.contextMenuCut then _G.clipboard = icon.path _G.clipboardCut = true - executeMethod(drawAllMethod) + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuDelete then fs.remove(icon.path) - executeMethod(drawAllMethod) - -- getFileList(workPathHistory[currentWorkPathHistoryElement]) - -- drawAll() + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuRename then ecs.rename(icon.path) - executeMethod(drawAllMethod) - -- getFileList(workPathHistory[currentWorkPathHistoryElement]) - -- drawAll() + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuCreateShortcut then ecs.createShortCut(fs.path(icon.path) .. "/" .. ecs.hideFileFormat(fs.name(icon.path)) .. ".lnk", icon.path) - executeMethod(drawAllMethod) - -- getFileList(workPathHistory[currentWorkPathHistoryElement]) - -- drawAll() + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuArchive then -- ecs.info("auto", "auto", "", "Архивация файлов...") archive.pack(ecs.hideFileFormat(fs.name(icon.path))..".pkg", icon.path) - executeMethod(drawAllMethod) - -- getFileList(workPathHistory[currentWorkPathHistoryElement]) - -- drawAll() - elseif action == MineOSCore.localization.contextMenuUploadToPastebin then - MineOSCore.safeLaunch("MineOS/Applications/Pastebin.app/Pastebin.lua", "upload", icon.path) - executeMethod(fullRefreshMethod) - -- shell.execute("MineOS/Applications/Pastebin.app/Pastebin.lua upload " .. path) - -- getFileList(workPathHistory[currentWorkPathHistoryElement]) - -- drawAll(true) + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuSetAsWallpaper then - --ecs.error(path) local wallpaperPath = "MineOS/System/OS/Wallpaper.lnk" fs.remove(wallpaperPath) ecs.createShortCut(wallpaperPath, icon.path) - computer.pushSignal("OSWallpaperChanged") - executeMethod(drawAllMethod) - return true - -- buffer.paste(1, 1, oldPixelsOfFullScreen) - -- buffer.draw() + computer.pushSignal("MineOSCore", "updateWallpaper") elseif action == MineOSCore.localization.contextMenuFlashEEPROM then local file = io.open(icon.path, "r") component.eeprom.set(file:read("*a")) file:close() computer.beep(1500, 0.2) - executeMethod(drawAllMethod) elseif action == MineOSCore.localization.contextMenuCreateApplication then ecs.newApplicationFromLuaFile(icon.path, fs.path(icon.path) or "") - executeMethod(drawAll) - -- getFileList(workPathHistory[currentWorkPathHistoryElement]) - -- drawAll() + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuAddToDock then table.insert(_G.OSSettings.dockShortcuts, {path = icon.path}) - ecs.saveOSSettings() - executeMethod(fullRefreshMethod) - else - buffer.paste(icon.x, icon.y, oldPixelsOfIcon) - buffer.draw() + MineOSCore.saveOSSettings() + computer.pushSignal("MineOSCore", "updateFileList") end end -function MineOSCore.iconClick(icon, eventData, selectionColor, selectionTransparency, iconTextColor, clickSleepDelay, somethingCanBeAddedToDock, drawAllMethod, fullRefreshMethod, changeCurrentPathMethod) - local fileFormat = ecs.getFileFormat(icon.path) - local oldPixelsOfIcon = MineOSCore.iconSelect(icon, selectionColor, selectionTransparency, iconTextColor) - local dataToReturn - - if eventData[5] == 0 then - os.sleep(clickSleepDelay) - dataToReturn = MineOSCore.iconLeftClick(icon, oldPixelsOfIcon, fileFormat, drawAllMethod, fullRefreshMethod, changeCurrentPathMethod) - else - dataToReturn = MineOSCore.iconRightClick(icon, oldPixelsOfIcon, eventData, fileFormat, somethingCanBeAddedToDock, drawAllMethod, fullRefreshMethod, changeCurrentPathMethod) - end - return dataToReturn -end - -function MineOSCore.emptyZoneClick(eventData, workPath, drawAllMethod, fullRefreshMethod) +function MineOSCore.emptyZoneClick(eventData, workspace, workPath) local action = GUI.contextMenu(eventData[3], eventData[4], {MineOSCore.localization.contextMenuNewFile}, {MineOSCore.localization.contextMenuNewFolder}, @@ -681,12 +722,13 @@ function MineOSCore.emptyZoneClick(eventData, workPath, drawAllMethod, fullRefre "-", {MineOSCore.localization.contextMenuPaste, (_G.clipboard == nil)} ):show() + if action == MineOSCore.localization.contextMenuNewFile then ecs.newFile(workPath) - executeMethod(fullRefreshMethod) + computer.pushSignal("MineOSCore", "updateFileListAndBufferTrueRedraw") elseif action == MineOSCore.localization.contextMenuNewFolder then ecs.newFolder(workPath) - executeMethod(drawAllMethod) + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuPaste then ecs.copy(_G.clipboard, workPath) if _G.clipboardCut then @@ -694,10 +736,10 @@ function MineOSCore.emptyZoneClick(eventData, workPath, drawAllMethod, fullRefre _G.clipboardCut = nil _G.clipboard = nil end - executeMethod(drawAllMethod) + computer.pushSignal("MineOSCore", "updateFileList") elseif action == MineOSCore.localization.contextMenuNewApplication then ecs.newApplication(workPath) - executeMethod(drawAllMethod) + computer.pushSignal("MineOSCore", "updateFileList") end end diff --git a/lib/advancedLua.lua b/lib/advancedLua.lua index d125b52d..d23f89f9 100755 --- a/lib/advancedLua.lua +++ b/lib/advancedLua.lua @@ -76,7 +76,11 @@ bit32.numberFromByteArray = bit32.byteArrayToNumber -------------------------------------------------- Math extensions -------------------------------------------------- function math.round(num) - if num >= 0 then return math.floor(num + 0.5) else return math.ceil(num - 0.5) end + if num >= 0 then + return math.floor(num + 0.5) + else + return math.ceil(num - 0.5) + end end function math.roundToDecimalPlaces(num, decimalPlaces) @@ -85,18 +89,31 @@ function math.roundToDecimalPlaces(num, decimalPlaces) end function math.getDigitCount(num) - local count = 0 - while number > 0 do - number = math.floor(number / 10) - count = count + 1 - end - return count + return num == 0 and 1 or math.ceil(math.log(num + 1, 10)) end function math.doubleToString(num, digitCount) return string.format("%." .. (digitCount or 1) .. "f", num) end +function math.shortenNumber(number, digitCount) + local shortcuts = { + "K", + "M", + "B", + "T" + } + + local index = math.floor(math.log(number, 1000)) + if number < 1000 then + return number + elseif index > #shortcuts then + index = #shortcuts + end + + return math.roundToDecimalPlaces(number / 1000 ^ index, digitCount) .. shortcuts[index] +end + -------------------------------------------------- Table extensions -------------------------------------------------- local function doSerialize(array, text, prettyLook, indentationSymbol, oldIndentationSymbol, equalsSymbol, currentRecusrionStack, recursionStackLimit) diff --git a/lib/colorlib.lua b/lib/colorlib.lua index b801c214..4d588ff9 100755 --- a/lib/colorlib.lua +++ b/lib/colorlib.lua @@ -90,9 +90,9 @@ function colorlib.alphaBlend(firstColor, secondColor, alphaChannel) local secondColorRed, secondColorGreen, secondColorBlue = colorlib.HEXtoRGB(secondColor) return colorlib.RGBtoHEX( - secondColorRed * invertedAlphaChannelDividedBy255 + firstColorRed * alphaChannel, - secondColorGreen * invertedAlphaChannelDividedBy255 + firstColorGreen * alphaChannel, - secondColorBlue * invertedAlphaChannelDividedBy255 + firstColorBlue * alphaChannel + math.floor(secondColorRed * invertedAlphaChannelDividedBy255 + firstColorRed * alphaChannel), + math.floor(secondColorGreen * invertedAlphaChannelDividedBy255 + firstColorGreen * alphaChannel), + math.floor(secondColorBlue * invertedAlphaChannelDividedBy255 + firstColorBlue * alphaChannel) ) end diff --git a/lib/windows.lua b/lib/windows.lua index 6374e81b..a0e35dde 100755 --- a/lib/windows.lua +++ b/lib/windows.lua @@ -41,38 +41,46 @@ local function executeObjectMethod(method, ...) end local function buttonHandler(window, object, objectIndex, eventData) - object.pressed = true; window:draw(); buffer.draw() + object.pressed = true + window:draw() os.sleep(0.2) - object.pressed = false; window:draw(); buffer.draw() + object.pressed = false + window:draw() executeObjectMethod(object.onTouch, eventData) end local function tabBarTabHandler(window, object, objectIndex, eventData) object.parent.parent.selectedTab = objectIndex - window:draw(); buffer:draw() + window:draw() executeObjectMethod(object.parent.parent.onTabSwitched, eventData) end local function inputTextBoxHandler(window, object, objectIndex, eventData) object:input() - window:draw(); buffer:draw() + window:draw() executeObjectMethod(object.onInputFinished, eventData) end local function textBoxScrollHandler(window, object, objectIndex, eventData) - if eventData[5] == 1 then object:scrollUp(); window:draw(); buffer.draw() else object:scrollDown(); window:draw(); buffer.draw() end + if eventData[5] == 1 then + object:scrollUp() + window:draw() + else + object:scrollDown() + window:draw() + end end local function horizontalSliderHandler(window, object, objectIndex, eventData) local clickPosition = eventData[3] - object.x + 1 object.value = object.minimumValue + (clickPosition * (object.maximumValue - object.minimumValue) / object.width) - window:draw(); buffer:draw() + window:draw() executeObjectMethod(object.onValueChanged, eventData) end local function switchHandler(window, object, objectIndex, eventData) object.state = not object.state - window:draw(); buffer:draw() + window:draw() executeObjectMethod(object.onStateChanged, eventData) end @@ -172,12 +180,12 @@ function windows.correctWindowCoordinates(x, y, width, height, minimumWidth, min return x, y, width, height end -local function drawWindow(window) +local function drawWindow(window, bufferForcedRedraw) if window.onDrawStarted then window.onDrawStarted() end window:update() if window.drawShadow then GUI.windowShadow(window.x, window.y, window.width, window.height, 50) end if window.onDrawFinished then window.onDrawFinished() end - buffer.draw() + buffer.draw(bufferForcedRedraw) end local function newWindow(x, y, width, height, minimumWidth, minimumHeight) @@ -234,7 +242,6 @@ end -- end -- myWindow:draw() --- buffer.draw() -- myWindow:handleEvents() ----------------------------------------- End of shit -----------------------------------------