mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2026-01-08 04:02:40 +01:00
хуй!
This commit is contained in:
parent
1a37616ffe
commit
9ffa89a081
@ -531,6 +531,69 @@
|
||||
version=1.0,
|
||||
},
|
||||
----------------------------------------------------- Приложения --------------------------------------------------------------------------
|
||||
{
|
||||
name="MineOS/Applications/SmartHouse",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/SmartHouse.lua",
|
||||
type="Application",
|
||||
icon="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Icon.pic",
|
||||
createShortcut="desktop",
|
||||
version=1.21,
|
||||
resources={
|
||||
{
|
||||
name="Modules/redstone/Icon.pic",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/redstone/Icon.pic",
|
||||
},
|
||||
{
|
||||
name="Modules/redstone/Main.lua",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/redstone/Main.lua",
|
||||
},
|
||||
--
|
||||
{
|
||||
name="Modules/mfsu/Icon.pic",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/mfsu/Icon.pic",
|
||||
},
|
||||
{
|
||||
name="Modules/mfsu/Main.lua",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/mfsu/Main.lua",
|
||||
},
|
||||
--
|
||||
{
|
||||
name="Modules/screen/Icon.pic",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/screen/Icon.pic",
|
||||
},
|
||||
{
|
||||
name="Modules/screen/Main.lua",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/screen/Main.lua",
|
||||
},
|
||||
--
|
||||
{
|
||||
name="Modules/homePC/Icon.pic",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/homePC/Icon.pic",
|
||||
},
|
||||
{
|
||||
name="Modules/homePC/Main.lua",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/homePC/Main.lua",
|
||||
},
|
||||
--
|
||||
{
|
||||
name="Modules/motion_sensor/Icon.pic",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/motion_sensor/Icon.pic",
|
||||
},
|
||||
{
|
||||
name="Modules/motion_sensor/Main.lua",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/motion_sensor/Main.lua",
|
||||
},
|
||||
--
|
||||
{
|
||||
name="Modules/reactor/Icon.pic",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/reactor/Icon.pic",
|
||||
},
|
||||
{
|
||||
name="Modules/reactor/Main.lua",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/SmartHouse/Modules/reactor/Main.lua",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name="MineOS/Applications/VK",
|
||||
url="IgorTimofeev/OpenComputers/master/Applications/VK/VK.lua",
|
||||
|
||||
BIN
Applications/.DS_Store
vendored
BIN
Applications/.DS_Store
vendored
Binary file not shown.
BIN
Applications/SmartHouse/Icon.pic
Normal file
BIN
Applications/SmartHouse/Icon.pic
Normal file
Binary file not shown.
BIN
Applications/SmartHouse/Modules/computer/Icon.pic
Normal file
BIN
Applications/SmartHouse/Modules/computer/Icon.pic
Normal file
Binary file not shown.
35
Applications/SmartHouse/Modules/computer/Main.lua
Executable file
35
Applications/SmartHouse/Modules/computer/Main.lua
Executable file
@ -0,0 +1,35 @@
|
||||
|
||||
local module = {
|
||||
allowSignalConnections = false,
|
||||
updateWhenModuleDetailsIsHidden = false,
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This method is called once during module initialization
|
||||
function module.start(moduleContainer)
|
||||
|
||||
end
|
||||
|
||||
-- This method is called on each frame update (every second by default), but only if module details is not hidden or updateWhenModuleDetailsIsHidden == true
|
||||
function module.update(moduleContainer, eventData)
|
||||
|
||||
end
|
||||
|
||||
-- This method is called when a this module receives virtual signal from the another module, but only if field allowSignalConnections == true
|
||||
function module.onSignalReceived(moduleContainer, ...)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Applications/SmartHouse/Modules/homePC/Icon.pic
Normal file
BIN
Applications/SmartHouse/Modules/homePC/Icon.pic
Normal file
Binary file not shown.
35
Applications/SmartHouse/Modules/homePC/Main.lua
Executable file
35
Applications/SmartHouse/Modules/homePC/Main.lua
Executable file
@ -0,0 +1,35 @@
|
||||
|
||||
local module = {
|
||||
allowSignalConnections = false,
|
||||
updateWhenModuleDetailsIsHidden = false,
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This method is called once during module initialization
|
||||
function module.start(moduleContainer)
|
||||
|
||||
end
|
||||
|
||||
-- This method is called on each frame update (every second by default), but only if module details is not hidden or updateWhenModuleDetailsIsHidden == true
|
||||
function module.update(moduleContainer, eventData)
|
||||
|
||||
end
|
||||
|
||||
-- This method is called when a this module receives virtual signal from the another module, but only if field allowSignalConnections == true
|
||||
function module.onSignalReceived(moduleContainer, ...)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Applications/SmartHouse/Modules/mfsu/Icon.pic
Normal file
BIN
Applications/SmartHouse/Modules/mfsu/Icon.pic
Normal file
Binary file not shown.
41
Applications/SmartHouse/Modules/mfsu/Main.lua
Executable file
41
Applications/SmartHouse/Modules/mfsu/Main.lua
Executable file
@ -0,0 +1,41 @@
|
||||
|
||||
local module = {
|
||||
allowSignalConnections = false,
|
||||
updateWhenModuleDetailsIsHidden = false,
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This method is called once during module initialization
|
||||
function module.start(moduleContainer)
|
||||
local x, y = 2, moduleContainer.children[#moduleContainer.children].localPosition.y + 2
|
||||
|
||||
moduleContainer.capaticyLabel = moduleContainer:addLabel("capaticyLabel", x, y, moduleContainer.width - 2, 1, 0xDDDDDD, "Capacity"):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top); y = y + 1
|
||||
moduleContainer.chart = moduleContainer:addChart("chart", x, y, moduleContainer.width - 2, math.floor(moduleContainer.width - 2) / 2, 0xFFFFFF, 0x999999, 0xFFDB40, "t", "%", 0, 100, {})
|
||||
end
|
||||
|
||||
-- This method is called on each frame update (every second by default), but only if module details is not hidden or updateWhenModuleDetailsIsHidden == true
|
||||
function module.update(moduleContainer, eventData)
|
||||
table.insert(moduleContainer.chart.values, math.ceil(moduleContainer.componentProxy.getStored() / moduleContainer.componentProxy.getCapacity() * 100))
|
||||
if #moduleContainer.chart.values > moduleContainer.chart.width - 1 then
|
||||
table.remove(moduleContainer.chart.values, 1)
|
||||
end
|
||||
end
|
||||
|
||||
-- This method is called when a this module receives virtual signal from the another module, but only if field allowSignalConnections == true
|
||||
function module.onSignalReceived(moduleContainer, ...)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Applications/SmartHouse/Modules/motion_sensor/Icon.pic
Normal file
BIN
Applications/SmartHouse/Modules/motion_sensor/Icon.pic
Normal file
Binary file not shown.
53
Applications/SmartHouse/Modules/motion_sensor/Main.lua
Executable file
53
Applications/SmartHouse/Modules/motion_sensor/Main.lua
Executable file
@ -0,0 +1,53 @@
|
||||
|
||||
local module = {
|
||||
allowSignalConnections = false,
|
||||
updateWhenModuleDetailsIsHidden = true,
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local sleepValue = 1
|
||||
|
||||
-- This method is called once during module initialization
|
||||
function module.start(moduleContainer)
|
||||
local x, y = 1, moduleContainer.children[#moduleContainer.children].localPosition.y + 2
|
||||
|
||||
local lines = {limit = 5}
|
||||
moduleContainer.editWhitelistButton = moduleContainer:addButton("editWhitelistButton", 2, y, moduleContainer.width - 2, 1, 0xDDDDDD, 0x262626, 0xAAAAAA, 0x262626, "Whitelist")
|
||||
y = y + 2
|
||||
moduleContainer.sleepSlider = moduleContainer:addHorizontalSlider("sleepSlider", x, y, moduleContainer.width, 0xFFDB80, 0x000000, 0xFFDB40, 0xDDDDDD, 0.5, 2, sleepValue, false, "Sleep: ")
|
||||
moduleContainer.sleepSlider.onValueChanged = function()
|
||||
sleepValue = moduleContainer.sleepSlider.value
|
||||
end
|
||||
end
|
||||
|
||||
-- This method is called on each frame update (every second by default), but only if module details is not hidden or updateWhenModuleDetailsIsHidden == true
|
||||
function module.update(moduleContainer, eventData)
|
||||
if eventData[1] == "motion" then
|
||||
if moduleContainer.componentProxy.address == eventData[2] then
|
||||
if eventData[6] == "ECS" then
|
||||
moduleContainer:pushSignal("redstone", "setValue", 15)
|
||||
os.sleep(sleepValue)
|
||||
moduleContainer:pushSignal("redstone", "setValue", 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This method is called when a this module receives virtual signal from the another module, but only if field allowSignalConnections == true
|
||||
function module.onSignalReceived(moduleContainer, ...)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Applications/SmartHouse/Modules/reactor/Icon.pic
Normal file
BIN
Applications/SmartHouse/Modules/reactor/Icon.pic
Normal file
Binary file not shown.
38
Applications/SmartHouse/Modules/reactor/Main.lua
Executable file
38
Applications/SmartHouse/Modules/reactor/Main.lua
Executable file
@ -0,0 +1,38 @@
|
||||
|
||||
local module = {
|
||||
allowSignalConnections = false,
|
||||
updateWhenModuleDetailsIsHidden = false,
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This method is called once during module initialization
|
||||
function module.start(moduleContainer)
|
||||
local x, y = 2, moduleContainer.children[#moduleContainer.children].localPosition.y + 2
|
||||
|
||||
moduleContainer.heatLabel = moduleContainer:addLabel("heatLabel", x, y, moduleContainer.width - 2, 1, 0xDDDDDD, ""); y = y + 1
|
||||
moduleContainer.outputLabel = moduleContainer:addLabel("outputLabel", x, y, moduleContainer.width - 2, 1, 0xDDDDDD, "")
|
||||
end
|
||||
|
||||
-- This method is called on each frame update (every second by default), but only if module details is not hidden or updateWhenModuleDetailsIsHidden == true
|
||||
function module.update(moduleContainer, eventData)
|
||||
moduleContainer.heatLabel.text = "Heat: " .. math.ceil(moduleContainer.componentProxy.getHeat() / moduleContainer.componentProxy.getMaxHeat() * 100) .. "%"
|
||||
moduleContainer.outputLabel.text = "Output: " .. moduleContainer.componentProxy.getReactorEnergyOutput()
|
||||
end
|
||||
|
||||
-- This method is called when a this module receives virtual signal from the another module, but only if field allowSignalConnections == true
|
||||
function module.onSignalReceived(moduleContainer, ...)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Applications/SmartHouse/Modules/redstone/Icon.pic
Normal file
BIN
Applications/SmartHouse/Modules/redstone/Icon.pic
Normal file
Binary file not shown.
90
Applications/SmartHouse/Modules/redstone/Main.lua
Executable file
90
Applications/SmartHouse/Modules/redstone/Main.lua
Executable file
@ -0,0 +1,90 @@
|
||||
local sides = require("sides")
|
||||
|
||||
local module = {
|
||||
allowSignalConnections = true,
|
||||
updateWhenModuleDetailsIsHidden = false,
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local function changeRedstoneState(moduleContainer, state)
|
||||
local sidesThatWillBeChanged = {}
|
||||
local comboBoxText = moduleContainer.sidesComboBox.items[moduleContainer.sidesComboBox.currentItem].text
|
||||
if comboBoxText == "All" then
|
||||
sidesThatWillBeChanged = {0,1,2,3,4,5}
|
||||
-- ecs.error("ALLL SIDES YOPTA")
|
||||
else
|
||||
sidesThatWillBeChanged = {sides[string.lower(comboBoxText)]}
|
||||
-- ecs.error("HERE HERE: " .. sides[string.lower(comboBoxText)])
|
||||
end
|
||||
|
||||
for i = 1, #sidesThatWillBeChanged do
|
||||
moduleContainer.redstoneStates[sidesThatWillBeChanged[i]] = state
|
||||
moduleContainer.componentProxy.setOutput(sidesThatWillBeChanged[i], state and 15 or 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- This method is called once during module initialization
|
||||
function module.start(moduleContainer)
|
||||
local x, y = 2, moduleContainer.children[#moduleContainer.children].localPosition.y + 2
|
||||
|
||||
moduleContainer.redstoneStates = {}
|
||||
for i = 0, 5 do
|
||||
local signalStrength = moduleContainer.componentProxy.getOutput(i)
|
||||
moduleContainer.redstoneStates[i] = signalStrength > 0 and true or false
|
||||
end
|
||||
|
||||
moduleContainer:addLabel("toggleLabel", x, y, moduleContainer.width - 2, 1, 0xDDDDDD, "Signal:")
|
||||
moduleContainer.signalSwitch = moduleContainer:addSwitch("redstoneSwitch", moduleContainer.width - 6, y, 6, 0xFFDB40, 0xBBBBBB, 0xFFFFFF, false)
|
||||
moduleContainer.signalSwitch.onStateChanged = function()
|
||||
changeRedstoneState(moduleContainer, moduleContainer.signalSwitch.state)
|
||||
end
|
||||
y = y + 2
|
||||
moduleContainer.emitOnceButton = moduleContainer:addButton("emitOnceButton", 2, y, moduleContainer.width - 2, 1, 0xDDDDDD, 0x262626, 0xAAAAAA, 0x262626, "Emit once")
|
||||
moduleContainer.emitOnceButton.onTouch = function()
|
||||
changeRedstoneState(moduleContainer, true)
|
||||
os.sleep(0.1)
|
||||
changeRedstoneState(moduleContainer, false)
|
||||
moduleContainer.signalSwitch.state = false
|
||||
end
|
||||
y = y + 2
|
||||
moduleContainer:addLabel("sideLabel", x, y, moduleContainer.width - 2, 1, 0xFFFFFF, "Side"):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top)
|
||||
y = y + 2
|
||||
moduleContainer.sidesComboBox = moduleContainer:addComboBox("comboBox", x, y, moduleContainer.width - 2, 1, 0xDDDDDD, 0x262626, 0xCCCCCC, 0x262626, {"All", "Up", "Down", "North", "South", "West", "East"})
|
||||
moduleContainer.sidesComboBox.onItemSelected = function()
|
||||
local comboBoxText = moduleContainer.sidesComboBox.items[moduleContainer.sidesComboBox.currentItem].text
|
||||
if comboBoxText == "All" then
|
||||
moduleContainer.signalSwitch.state = false
|
||||
else
|
||||
local side = sides[string.lower(comboBoxText)]
|
||||
moduleContainer.signalSwitch.state = moduleContainer.redstoneStates[side]
|
||||
end
|
||||
end
|
||||
y = y + 2
|
||||
end
|
||||
|
||||
-- This method is called on each frame update (every second by default), but only if module details is not hidden or updateWhenModuleDetailsIsHidden == true
|
||||
function module.update(moduleContainer, eventData)
|
||||
|
||||
end
|
||||
|
||||
-- This method is called when a this module receives virtual signal from the another module, but only if field allowSignalConnections == true
|
||||
function module.onSignalReceived(moduleContainer, ...)
|
||||
local data = {...}
|
||||
if data[1] == "redstone" and data[2] == "setState" and type(data[3]) == "boolean" then
|
||||
changeRedstoneState(moduleContainer, data[3])
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Applications/SmartHouse/Modules/screen/Icon.pic
Normal file
BIN
Applications/SmartHouse/Modules/screen/Icon.pic
Normal file
Binary file not shown.
35
Applications/SmartHouse/Modules/screen/Main.lua
Executable file
35
Applications/SmartHouse/Modules/screen/Main.lua
Executable file
@ -0,0 +1,35 @@
|
||||
|
||||
local module = {
|
||||
allowSignalConnections = false,
|
||||
updateWhenModuleDetailsIsHidden = false,
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- This method is called once during module initialization
|
||||
function module.start(moduleContainer)
|
||||
|
||||
end
|
||||
|
||||
-- This method is called on each frame update (every second by default), but only if module details is not hidden or updateWhenModuleDetailsIsHidden == true
|
||||
function module.update(moduleContainer, eventData)
|
||||
|
||||
end
|
||||
|
||||
-- This method is called when a this module receives virtual signal from the another module, but only if field allowSignalConnections == true
|
||||
function module.onSignalReceived(moduleContainer, ...)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
503
Applications/SmartHouse/SmartHouse.lua
Executable file
503
Applications/SmartHouse/SmartHouse.lua
Executable file
@ -0,0 +1,503 @@
|
||||
|
||||
local libraries = {
|
||||
sides = "sides",
|
||||
component = "component",
|
||||
advancedLua = "advancedLua",
|
||||
image = "image",
|
||||
buffer = "doubleBuffering",
|
||||
keyboard = "keyboard",
|
||||
GUI = "GUI",
|
||||
ecs = "ECSAPI",
|
||||
windows = "windows",
|
||||
MineOSCore = "MineOSCore",
|
||||
computer = "computer",
|
||||
fs = "filesystem",
|
||||
}
|
||||
|
||||
for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end; libraries = nil
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local window
|
||||
|
||||
local paths = {}
|
||||
paths.resources = MineOSCore.getCurrentApplicationResourcesDirectory(),
|
||||
-- paths.resources = "/SmartHouse/"
|
||||
paths.modules = paths.resources .. "Modules/"
|
||||
|
||||
local colors = {
|
||||
-- background = image.load("/MineOS/Pictures/Ciri.pic"),
|
||||
background = 0xDDDDDD,
|
||||
connectionLines = 0x262626,
|
||||
devicesBackgroundTransparency = 40,
|
||||
devicesBackground = 0x0,
|
||||
devicesButtonBackground = 0xFFFFFF,
|
||||
devicesButtonText = 0x262626,
|
||||
devicesInfoText = 0xDDDDDD,
|
||||
groupsTransparency = nil,
|
||||
}
|
||||
|
||||
local signals = {}
|
||||
local groups = {}
|
||||
local modules = {}
|
||||
local offset = {x = 0, y = 0}
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local function loadModule(modulePath)
|
||||
local success, module = pcall(loadfile(modulePath .. "/Main.lua"))
|
||||
if success then
|
||||
module.icon = image.load(modulePath .. "/Icon.pic")
|
||||
modules[fs.name(modulePath)] = module
|
||||
else
|
||||
error("Module loading failed: " .. module)
|
||||
end
|
||||
end
|
||||
|
||||
local function loadModules()
|
||||
modules = {}
|
||||
for file in fs.list(paths.modules) do
|
||||
local modulePath = paths.modules .. file
|
||||
if fs.isDirectory(modulePath) then
|
||||
loadModule(modulePath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function highlightDiviceAsSignal(deviceContainer, color)
|
||||
buffer.square(deviceContainer.x - 1, deviceContainer.y, deviceContainer.width + 2, deviceContainer.height, color)
|
||||
buffer.text(deviceContainer.x - 1, deviceContainer.y - 1, color, string.rep("▄", deviceContainer.width + 2))
|
||||
buffer.text(deviceContainer.x - 1, deviceContainer.y + deviceContainer.height, color, string.rep("▀", deviceContainer.width + 2))
|
||||
end
|
||||
|
||||
local function createNewGroup(name, color)
|
||||
table.insert(groups, {
|
||||
color = color,
|
||||
name = name,
|
||||
devices = {}
|
||||
})
|
||||
end
|
||||
|
||||
local function removeDeviceFromGroup(address)
|
||||
for groupIndex = 1, #groups do
|
||||
local deviceIndex = 1
|
||||
while deviceIndex <= #groups[groupIndex].devices do
|
||||
if groups[groupIndex].devices[deviceIndex].componentProxy.address == address then
|
||||
table.remove(groups[groupIndex].devices, deviceIndex)
|
||||
deviceIndex = deviceIndex - 1
|
||||
if #groups[groupIndex].devices == 0 then
|
||||
groups[groupIndex] = nil
|
||||
return
|
||||
end
|
||||
end
|
||||
deviceIndex = deviceIndex + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function addDeviceToGroup(deviceContainer, name, color)
|
||||
local groupIndex
|
||||
|
||||
for i = 1, #groups do
|
||||
if groups[i].name == name then groupIndex = i; break end
|
||||
end
|
||||
|
||||
if not groupIndex then
|
||||
createNewGroup(name, color)
|
||||
groupIndex = #groups
|
||||
end
|
||||
|
||||
table.insert(groups[groupIndex].devices, deviceContainer)
|
||||
groups[groupIndex].color = color
|
||||
end
|
||||
|
||||
local function containerPushSignal(container, ...)
|
||||
for signalIndex = 1, #signals do
|
||||
if signals[signalIndex].fromDevice == container then
|
||||
for toDeviceIndex = 1, #signals[signalIndex].toDevices do
|
||||
if signals[signalIndex].toDevices[toDeviceIndex].module.onSignalReceived then
|
||||
signals[signalIndex].toDevices[toDeviceIndex].module.onSignalReceived(signals[signalIndex].toDevices[toDeviceIndex], ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function changeChildrenState(container, state)
|
||||
for i = 3, #container.children do
|
||||
container.children[i].hidden = state
|
||||
end
|
||||
end
|
||||
|
||||
local function createDevice(x, y, componentName, componentProxy, name)
|
||||
if not modules[componentName] then error("No such module: " .. componentName) end
|
||||
local container = window:addContainer(name, x, y, 16, 9)
|
||||
|
||||
container.name = name
|
||||
container.module = modules[componentName]
|
||||
container.componentProxy = componentProxy
|
||||
container.componentName = componentName
|
||||
container.detailsIsHidden = true
|
||||
|
||||
x, y = 1, 1
|
||||
local deviceImage = container:addImage("deviceImage", x, y, container.module.icon); y = y + 8
|
||||
local stateButton = container:addButton("stateButton", 1, y, container.width, 1, colors.devicesButtonBackground, colors.devicesButtonText, colors.devicesButtonText, colors.devicesButtonBackground, "*")
|
||||
stateButton.onTouch = function()
|
||||
container.detailsIsHidden = not container.detailsIsHidden
|
||||
changeChildrenState(container, container.detailsIsHidden)
|
||||
if container.detailsIsHidden then
|
||||
stateButton.localPosition.y = container.backgroundPanel.localPosition.y
|
||||
else
|
||||
stateButton.localPosition.y = container.backgroundPanel.localPosition.y + container.backgroundPanel.height
|
||||
end
|
||||
end
|
||||
|
||||
container.backgroundPanel = container:addPanel("backgroundPanel", 1, y, container.width, 1, colors.devicesBackground, colors.devicesBackgroundTransparency)
|
||||
|
||||
|
||||
container:addLabel("nameLabel", 2, y, container.width - 2, 1, 0xFFFFFF, container.name):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top); y = y + 1
|
||||
container:addLabel("addressLabel", 2, y, container.width - 2, 1, 0x999999, container.componentProxy.address):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top); y = y + 2
|
||||
|
||||
container.module.start(container)
|
||||
container.module.update(container, {})
|
||||
|
||||
y = container.children[#container.children].localPosition.y + (container.children[#container.children].height or 0) + 1
|
||||
container.backgroundPanel.height = container.backgroundPanel.height + (y - container.backgroundPanel.y - 1)
|
||||
|
||||
deviceImage.onTouch = function(eventData)
|
||||
if eventData[5] == 0 then
|
||||
window.deviceToDrag = container
|
||||
container:moveToFront()
|
||||
if keyboard.isShiftDown() then
|
||||
local x, y = container.x + 8, container.y + 4
|
||||
signals.fromDevice = container
|
||||
signals.toPoint = {x = x, y = y}
|
||||
end
|
||||
else
|
||||
local action = GUI.contextMenu(eventData[3], eventData[4], {"Add to group"}, {"Remove from group"}):show()
|
||||
if action == "Add to group" then
|
||||
local data = ecs.universalWindow("auto", "auto", 36, 0x262626, true,
|
||||
{"EmptyLine"},
|
||||
{"CenterText", ecs.colors.orange, "Add to group"},
|
||||
{"EmptyLine"},
|
||||
{"Input", 0xFFFFFF, ecs.colors.orange, "Group #1"},
|
||||
{"Color", "Group color", 0xAAAAAA},
|
||||
{"EmptyLine"},
|
||||
{"Button", {ecs.colors.orange, 0xffffff, "OK"}, {0x999999, 0xffffff, "Cancel"}}
|
||||
)
|
||||
|
||||
if data[3] == "OK" then
|
||||
addDeviceToGroup(container, data[1], data[2])
|
||||
end
|
||||
elseif action == "Remove from group" then
|
||||
removeDeviceFromGroup(container.componentProxy.address)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local oldDraw = container.draw
|
||||
container.draw = function()
|
||||
if container.highlightColor then
|
||||
highlightDiviceAsSignal(container, container.highlightColor)
|
||||
end
|
||||
oldDraw(container)
|
||||
end
|
||||
container.pushSignal = containerPushSignal
|
||||
|
||||
changeChildrenState(container, container.detailsIsHidden)
|
||||
return container
|
||||
end
|
||||
|
||||
local function drawConnectionLine(x1, y1, x2, y2, thin, color, cutAfterPixels)
|
||||
local symbol = ""
|
||||
if x1 < x2 then
|
||||
if y1 < y2 then
|
||||
symbol = thin and "┐" or "█"
|
||||
else
|
||||
symbol = thin and "┘" or "▀"
|
||||
end
|
||||
else
|
||||
if y1 < y2 then
|
||||
symbol = thin and "┌" or "█"
|
||||
else
|
||||
symbol = thin and "└" or "▀"
|
||||
end
|
||||
end
|
||||
|
||||
local x, y, counter, xIncrement, yIncrement = x1, y1, 1, (x1 <= x2 and 1 or -1), (y1 <= y2 and 1 or -1)
|
||||
|
||||
while true do
|
||||
local bg = buffer.get(x, y)
|
||||
buffer.set(x, y, bg, color, thin and "─" or "▀")
|
||||
x = x + xIncrement
|
||||
|
||||
if counter < cutAfterPixels then
|
||||
counter = counter + 1
|
||||
else
|
||||
x = x + xIncrement
|
||||
end
|
||||
|
||||
if x1 <= x2 then
|
||||
if x >= x2 - 1 then break end
|
||||
else
|
||||
if x < x2 + 1 then break end
|
||||
end
|
||||
end
|
||||
|
||||
buffer.text(x, y, color, symbol)
|
||||
y = y + yIncrement
|
||||
|
||||
while true do
|
||||
local bg = buffer.get(x, y)
|
||||
buffer.set(x, y, bg, color, thin and "│" or "█")
|
||||
y = y + yIncrement
|
||||
|
||||
if counter < cutAfterPixels then
|
||||
counter = counter + 1
|
||||
else
|
||||
y = y + yIncrement
|
||||
end
|
||||
|
||||
if y1 <= y2 then
|
||||
if y >= y2 then break end
|
||||
else
|
||||
if y < y2 then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function moveDevice(container, x, y)
|
||||
container.localPosition.x, container.localPosition.y = container.localPosition.x + x, container.localPosition.y + y
|
||||
end
|
||||
|
||||
local function moveDevices(x, y)
|
||||
for i = 1, #window.children do
|
||||
moveDevice(window.children[i], x, y)
|
||||
end
|
||||
end
|
||||
|
||||
local function getGroupGeometry(devices)
|
||||
local geometry = {}
|
||||
|
||||
for deviceIndex = 1, #devices do
|
||||
geometry.x = math.min(geometry.x or devices[deviceIndex].localPosition.x, devices[deviceIndex].localPosition.x)
|
||||
geometry.y = math.min(geometry.y or devices[deviceIndex].localPosition.y, devices[deviceIndex].localPosition.y)
|
||||
|
||||
geometry.xMax = math.max(geometry.xMax or devices[deviceIndex].localPosition.x, devices[deviceIndex].localPosition.x)
|
||||
geometry.yMax = math.max(geometry.yMax or devices[deviceIndex].localPosition.y, devices[deviceIndex].localPosition.y)
|
||||
end
|
||||
|
||||
local xOffset, yOffset = 2, 2
|
||||
geometry.width, geometry.height = geometry.xMax - geometry.x + 16 + xOffset * 2, geometry.yMax - geometry.y + 9 + yOffset * 2
|
||||
geometry.x, geometry.y = geometry.x - xOffset, geometry.y - yOffset - 1
|
||||
|
||||
return geometry
|
||||
end
|
||||
|
||||
local function drawGroups()
|
||||
for groupIndex = 1, #groups do
|
||||
local groupGeometry = getGroupGeometry(groups[groupIndex].devices)
|
||||
buffer.square(groupGeometry.x, groupGeometry.y, groupGeometry.width, groupGeometry.height, groups[groupIndex].color)
|
||||
GUI.label(groupGeometry.x, groupGeometry.y + 1, groupGeometry.width, 1, 0x000000, groups[groupIndex].name):setAlignment(GUI.alignment.horizontal.center, GUI.alignment.vertical.top):draw()
|
||||
end
|
||||
end
|
||||
|
||||
local function drawSignals()
|
||||
local colorPrimary = 0xFF4940
|
||||
local step = 16
|
||||
|
||||
if signals.fromDevice then
|
||||
drawConnectionLine(
|
||||
signals.fromDevice.x + 8,
|
||||
signals.fromDevice.y + 4,
|
||||
signals.toPoint.x,
|
||||
signals.toPoint.y,
|
||||
false, colorPrimary, step
|
||||
)
|
||||
signals.fromDevice.highlightColor = colorPrimary
|
||||
end
|
||||
|
||||
for signalIndex = 1, #signals do
|
||||
--Подсветка подключенных устройств
|
||||
for toDeviceIndex = 1, #signals[signalIndex].toDevices do
|
||||
signals[signalIndex].toDevices[toDeviceIndex].highlightColor = colorPrimary
|
||||
drawConnectionLine(
|
||||
signals[signalIndex].fromDevice.x + 8,
|
||||
signals[signalIndex].fromDevice.y + 4,
|
||||
signals[signalIndex].toDevices[toDeviceIndex].x + 8,
|
||||
signals[signalIndex].toDevices[toDeviceIndex].y + 4,
|
||||
false, colorPrimary, step
|
||||
)
|
||||
end
|
||||
-- Подсветка стартового устройства
|
||||
signals[signalIndex].fromDevice.highlightColor = colorPrimary
|
||||
end
|
||||
end
|
||||
|
||||
local function createWindow()
|
||||
window = windows.fullScreen()
|
||||
|
||||
-- Создаем главное и неебически важное устройство домашнего писюка
|
||||
local homePC = createDevice(math.floor(window.width / 2 - 8), math.floor(window.height / 2 - 4), "homePC", component.proxy(computer.address()), "Сервак")
|
||||
|
||||
-- Перед отрисовкой окна чистим буфер фоном и перехуячиваем позиции объектов групп
|
||||
window.onDrawStarted = function()
|
||||
buffer.clear(colors.background)
|
||||
drawGroups()
|
||||
|
||||
local xPC, yPC = homePC.x + 8, homePC.y + 4
|
||||
for i = 1, #window.children do
|
||||
drawConnectionLine(xPC, yPC, window.children[i].x + 8, window.children[i].y + 4, true, colors.connectionLines, math.huge)
|
||||
end
|
||||
|
||||
drawSignals()
|
||||
end
|
||||
|
||||
window.onAnyEvent = function(eventData)
|
||||
if eventData[1] == "key_down" then
|
||||
if eventData[4] == 19 then
|
||||
colors.background = math.random(0x0, 0xFFFFFF)
|
||||
elseif eventData[4] == 200 then
|
||||
moveDevices(0, -2)
|
||||
elseif eventData[4] == 208 then
|
||||
moveDevices(0, 2)
|
||||
elseif eventData[4] == 203 then
|
||||
moveDevices(-4, 0)
|
||||
elseif eventData[4] == 205 then
|
||||
moveDevices(4, 0)
|
||||
end
|
||||
elseif eventData[1] == "touch" then
|
||||
window.dragOffset = {x = eventData[3], y = eventData[4]}
|
||||
elseif eventData[1] == "drag" then
|
||||
if keyboard.isShiftDown() then
|
||||
if signals.fromDevice then
|
||||
signals.toPoint.x, signals.toPoint.y = eventData[3], eventData[4]
|
||||
end
|
||||
else
|
||||
if eventData[5] == 0 and window.deviceToDrag then
|
||||
window.deviceToDrag.localPosition.x, window.deviceToDrag.localPosition.y = window.deviceToDrag.localPosition.x + (eventData[3] - window.dragOffset.x), window.deviceToDrag.y + (eventData[4] - window.dragOffset.y)
|
||||
end
|
||||
end
|
||||
window.dragOffset = {x = eventData[3], y = eventData[4]}
|
||||
elseif eventData[1] == "drop" then
|
||||
if keyboard.isShiftDown() and signals.fromDevice then
|
||||
--Создаем новый сигнал, если такового еще не существовало
|
||||
local signalIndex
|
||||
for i = 1, #signals do
|
||||
if signals[i].fromDevice == signals.fromDevice then signalIndex = i; break end
|
||||
end
|
||||
if not signalIndex then
|
||||
table.insert(signals, {fromDevice = signals.fromDevice, toDevices = {}})
|
||||
signalIndex = #signals
|
||||
end
|
||||
|
||||
--Ищем контейнер, на который дропнулось
|
||||
local container
|
||||
for i = 1, #window.children do
|
||||
if window.children[i]:isClicked(eventData[3], eventData[4]) then
|
||||
container = window.children[i]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Если контейнер найден, то
|
||||
if container then
|
||||
--Чекаем, принимает ли модуль этого контейнера сигналы, и если принимает, то
|
||||
if container.module.allowSignalConnections then
|
||||
--Проверяем, нет ли часом этого устройства в УЖЕ подключенных
|
||||
local deviceExists = false
|
||||
for i = 1, #signals[signalIndex].toDevices do
|
||||
if signals[signalIndex].toDevices[i] == container then deviceExists = true end
|
||||
end
|
||||
|
||||
--И если нет, а также если это устройство не является устройством, от которого ВЕЛОСЬ подключение, то
|
||||
if not deviceExists and container ~= signals[signalIndex].fromDevice then
|
||||
table.insert(signals[signalIndex].toDevices, container)
|
||||
end
|
||||
else
|
||||
GUI.error("This device doesn't support virtual signal receiving", {title = {text = "Warning", color = 0xFF5555}})
|
||||
if #signals[signalIndex].toDevices <= 0 then
|
||||
signals[signalIndex].fromDevice.highlightColor = nil
|
||||
signals[signalIndex] = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
-- А если мы дропнули на пустую точку, то оффаем выделение
|
||||
if #signals[signalIndex].toDevices <= 0 then
|
||||
signals[signalIndex].fromDevice.highlightColor = nil
|
||||
signals[signalIndex] = nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Удаляем временные сигнальные переменные
|
||||
signals.fromDevice, signals.toPoint = nil, nil
|
||||
-- Сбрасываем также общее смещение драга
|
||||
window.dragOffset = nil
|
||||
window.deviceToDrag = nil
|
||||
end
|
||||
|
||||
for i = 1, #window.children do
|
||||
if not window.children[i].detailsIsHidden or window.children[i].module.updateWhenModuleDetailsIsHidden then
|
||||
window.children[i].module.update(window.children[i], eventData)
|
||||
end
|
||||
end
|
||||
|
||||
window:draw()
|
||||
end
|
||||
end
|
||||
|
||||
local function getComputerInfo()
|
||||
local currentComputerAddress = computer.address()
|
||||
for address, information in pairs(computer.getDeviceInfo()) do
|
||||
if currentComputerAddress == address then
|
||||
return information.description
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function refreshComponents()
|
||||
local devices = {}
|
||||
for componentAddress, componentName in pairs(component.list()) do
|
||||
if modules[componentName] then
|
||||
table.insert(devices, {componentAddress = componentAddress, componentName = componentName})
|
||||
end
|
||||
end
|
||||
local x, y = math.floor(buffer.screen.width / 2 - #devices * 18 / 2 + 1), 2
|
||||
for i = 1, #devices do
|
||||
createDevice(x, y, devices[i].componentName, component.proxy(devices[i].componentAddress), devices[i].componentName)
|
||||
x = x + 18
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
buffer.start()
|
||||
|
||||
loadModules()
|
||||
createWindow()
|
||||
refreshComponents()
|
||||
window:draw()
|
||||
window:handleEvents(1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
418
lib/GUI.lua
418
lib/GUI.lua
@ -38,9 +38,9 @@ GUI.colors = {
|
||||
text = 0xAAAAAA
|
||||
},
|
||||
contextMenu = {
|
||||
background = 0xFFFFFF,
|
||||
separator = 0xAAAAAA,
|
||||
default = {
|
||||
background = 0xFFFFFF,
|
||||
text = 0x2D2D2D
|
||||
},
|
||||
disabled = {
|
||||
@ -57,7 +57,7 @@ GUI.colors = {
|
||||
}
|
||||
}
|
||||
|
||||
GUI.contextMenuElementTypes = enum(
|
||||
GUI.dropDownMenuElementTypes = enum(
|
||||
"default",
|
||||
"separator"
|
||||
)
|
||||
@ -80,14 +80,16 @@ GUI.objectTypes = enum(
|
||||
"textBox",
|
||||
"horizontalSlider",
|
||||
"switch",
|
||||
"progressBar"
|
||||
"progressBar",
|
||||
"chart",
|
||||
"comboBox"
|
||||
)
|
||||
|
||||
----------------------------------------- Primitive objects -----------------------------------------
|
||||
|
||||
-- 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.invisible ~= false 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.hidden then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
@ -163,26 +165,78 @@ end
|
||||
function GUI.getClickedObject(container, xEvent, yEvent)
|
||||
local clickedObject, clickedIndex
|
||||
for objectIndex = #container.children, 1, -1 do
|
||||
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)
|
||||
if clickedObject then break end
|
||||
elseif not container.children[objectIndex].disableClicking and container.children[objectIndex]:isClicked(xEvent, yEvent) then
|
||||
clickedObject, clickedIndex = container.children[objectIndex], objectIndex
|
||||
break
|
||||
if not container.children[objectIndex].hidden 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)
|
||||
if clickedObject then break end
|
||||
elseif not container.children[objectIndex].disableClicking and container.children[objectIndex]:isClicked(xEvent, yEvent) then
|
||||
clickedObject, clickedIndex = container.children[objectIndex], objectIndex
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return clickedObject, clickedIndex
|
||||
end
|
||||
|
||||
local function checkObjectParentExists(object)
|
||||
if not object.parent then error("Object doesn't have a parent container") end
|
||||
end
|
||||
|
||||
local function containerObjectIndexOf(object)
|
||||
checkObjectParentExists(object)
|
||||
for objectIndex = 1, #object.parent.children do
|
||||
if object.parent.children[objectIndex] == object then
|
||||
return objectIndex
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Move container's object "closer" to our eyes
|
||||
local function containerObjectMoveForward(object)
|
||||
local objectIndex = object:indexOf()
|
||||
if objectIndex < #object.parent.children then
|
||||
object.parent.children[index], object.parent.children[index + 1] = swap(object.parent.children[index], object.parent.children[index + 1])
|
||||
end
|
||||
end
|
||||
|
||||
-- Move container's object "more far out" of our eyes
|
||||
local function containerObjectMoveBackward(object)
|
||||
local objectIndex = object:indexOf()
|
||||
if objectIndex > 1 then
|
||||
object.parent.children[index], object.parent.children[index - 1] = swap(object.parent.children[index], object.parent.children[index - 1])
|
||||
end
|
||||
end
|
||||
|
||||
-- Move container's object to front of all objects
|
||||
local function containerObjectMoveToFront(object)
|
||||
local objectIndex = object:indexOf()
|
||||
table.insert(object.parent.children, object)
|
||||
table.remove(object.parent.children, objectIndex)
|
||||
end
|
||||
|
||||
-- Move container's object to back of all objects
|
||||
local function containerObjectMoveToBack(object)
|
||||
local objectIndex = object:indexOf()
|
||||
table.insert(object.parent.children, 1, object)
|
||||
table.remove(object.parent.children, objectIndex + 1)
|
||||
end
|
||||
|
||||
-- Add any object as children to parent container with specified objectName
|
||||
local function addObjectToContainer(container, objectType, objectName, object)
|
||||
object.name = objectName
|
||||
object.type = objectType
|
||||
object.parent = container
|
||||
object.indexOf = containerObjectIndexOf
|
||||
object.moveToFront = containerObjectMoveToFront
|
||||
object.moveToBack = containerObjectMoveToBack
|
||||
object.moveForward = containerObjectMoveForward
|
||||
object.moveBackward = containerObjectMoveBackward
|
||||
object.localPosition = {x = object.x, y = object.y}
|
||||
|
||||
table.insert(container.children, object)
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
@ -266,18 +320,31 @@ local function addSwitchObjectToContainer(container, objectName, ...)
|
||||
return addObjectToContainer(container, GUI.objectTypes.switch, objectName, GUI.switch(...))
|
||||
end
|
||||
|
||||
-- Add Chart object to container
|
||||
local function addChartObjectToContainer(container, objectName, ...)
|
||||
return addObjectToContainer(container, GUI.objectTypes.chart, objectName, GUI.chart(...))
|
||||
end
|
||||
|
||||
-- Add ComboBox object to container
|
||||
local function addComboBoxObjectToContainer(container, objectName, ...)
|
||||
return addObjectToContainer(container, GUI.objectTypes.comboBox, objectName, GUI.comboBox(...))
|
||||
end
|
||||
|
||||
-- Recursively draw container's content including all children container's content
|
||||
local function drawContainerContent(container)
|
||||
for objectIndex = 1, #container.children do
|
||||
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
|
||||
-- drawContainerContent(container.children[objectIndex])
|
||||
container.children[objectIndex]:draw()
|
||||
else
|
||||
if container.children[objectIndex].draw then
|
||||
if not container.children[objectIndex].hidden 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
|
||||
-- drawContainerContent(container.children[objectIndex])
|
||||
-- We use :draw() method against of recursive call. The reason is possible user-defined :draw() reimplementations
|
||||
container.children[objectIndex]:draw()
|
||||
else
|
||||
error("Container object with index " .. objectIndex .. " and name \"" .. tostring(container.children[objectIndex].name) .. "\" doesn't have :draw() method")
|
||||
if container.children[objectIndex].draw then
|
||||
container.children[objectIndex]:draw()
|
||||
else
|
||||
error("Container object with index " .. objectIndex .. " and name \"" .. tostring(container.children[objectIndex].name) .. "\" doesn't have :draw() method")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -315,6 +382,8 @@ function GUI.container(x, y, width, height)
|
||||
container.addHorizontalSlider = addHorizontalSliderObjectToContainer
|
||||
container.addSwitch = addSwitchObjectToContainer
|
||||
container.addProgressBar = addProgressBarObjectToContainer
|
||||
container.addChart = addChartObjectToContainer
|
||||
container.addComboBox = addComboBoxObjectToContainer
|
||||
|
||||
return container
|
||||
end
|
||||
@ -513,72 +582,70 @@ function GUI.windowActionButtons(x, y, fatSymbol)
|
||||
return container
|
||||
end
|
||||
|
||||
----------------------------------------- Context Menu -----------------------------------------
|
||||
----------------------------------------- Dropdown Menu -----------------------------------------
|
||||
|
||||
local function drawContextMenuElement(contextMenuObject, elementIndex, isPressed)
|
||||
if contextMenuObject.elements[elementIndex].type == GUI.contextMenuElementTypes.default then
|
||||
local textColor = contextMenuObject.elements[elementIndex].disabled and GUI.colors.contextMenu.disabled.text or (contextMenuObject.elements[elementIndex].color or GUI.colors.contextMenu.default.text)
|
||||
|
||||
local function drawDropDownMenuElement(object, itemIndex, isPressed)
|
||||
local y = object.y + itemIndex * (object.spaceBetweenElements + 1) - 1
|
||||
local yText = math.floor(y)
|
||||
|
||||
if object.items[itemIndex].type == GUI.dropDownMenuElementTypes.default then
|
||||
local textColor = object.items[itemIndex].disabled and object.colors.disabled.text or (object.items[itemIndex].color or object.colors.default.text)
|
||||
|
||||
-- Нажатие
|
||||
if isPressed then
|
||||
buffer.square(contextMenuObject.x, contextMenuObject.y + elementIndex - 1, contextMenuObject.width, 1, GUI.colors.contextMenu.pressed.background, GUI.colors.contextMenu.pressed.text, " ")
|
||||
textColor = GUI.colors.contextMenu.pressed.text
|
||||
buffer.square(object.x, y - object.spaceBetweenElements, object.width, object.spaceBetweenElements * 2 + 1, object.colors.pressed.background, object.colors.pressed.text, " ")
|
||||
textColor = object.colors.pressed.text
|
||||
end
|
||||
|
||||
buffer.text(contextMenuObject.x + 2, contextMenuObject.y + elementIndex - 1, textColor, contextMenuObject.elements[elementIndex].text)
|
||||
|
||||
if contextMenuObject.elements[elementIndex].shortcut then
|
||||
buffer.text(contextMenuObject.x + contextMenuObject.width - unicode.len(contextMenuObject.elements[elementIndex].shortcut) - 2, contextMenuObject.y + elementIndex - 1, textColor, contextMenuObject.elements[elementIndex].shortcut)
|
||||
-- Основной текст
|
||||
buffer.text(object.x + object.sidesOffset, yText, textColor, string.limit(object.items[itemIndex].text, object.width - object.sidesOffset * 2, false))
|
||||
-- Шурткатикус
|
||||
if object.items[itemIndex].shortcut then
|
||||
buffer.text(object.x + object.width - unicode.len(object.items[itemIndex].shortcut) - object.sidesOffset, yText, textColor, object.items[itemIndex].shortcut)
|
||||
end
|
||||
else
|
||||
buffer.text(contextMenuObject.x, contextMenuObject.y + elementIndex - 1, GUI.colors.contextMenu.separator, string.rep("─", contextMenuObject.width))
|
||||
-- Сепаратор
|
||||
buffer.text(object.x, yText, object.colors.separator, string.rep("─", object.width))
|
||||
end
|
||||
end
|
||||
|
||||
local function drawContextMenu(contextMenuObject)
|
||||
buffer.square(contextMenuObject.x, contextMenuObject.y, contextMenuObject.width, contextMenuObject.height, GUI.colors.contextMenu.background, GUI.colors.contextMenu.default.text, " ", GUI.colors.contextMenu.transparency.background)
|
||||
GUI.windowShadow(contextMenuObject.x, contextMenuObject.y, contextMenuObject.width, contextMenuObject.height, GUI.colors.contextMenu.transparency.shadow, true)
|
||||
for elementIndex = 1, #contextMenuObject.elements do drawContextMenuElement(contextMenuObject, elementIndex, false) end
|
||||
local function drawDropDownMenu(object)
|
||||
buffer.square(object.x, object.y, object.width, object.height, object.colors.default.background, object.colors.default.text, " ", object.colors.transparency)
|
||||
if object.drawShadow then GUI.windowShadow(object.x, object.y, object.width, object.height, GUI.colors.contextMenu.transparency.shadow, true) end
|
||||
for itemIndex = 1, #object.items do drawDropDownMenuElement(object, itemIndex, false) end
|
||||
end
|
||||
|
||||
local function showContextMenu(contextMenuObject)
|
||||
local function showDropDownMenu(object)
|
||||
local oldDrawLimit = buffer.getDrawLimit(); buffer.resetDrawLimit()
|
||||
-- Расчет ширины окна меню
|
||||
local longestElement, longestShortcut = 0, 0
|
||||
for elementIndex = 1, #contextMenuObject.elements do
|
||||
if contextMenuObject.elements[elementIndex].type == GUI.contextMenuElementTypes.default then
|
||||
longestElement = math.max(longestElement, unicode.len(contextMenuObject.elements[elementIndex].text))
|
||||
if contextMenuObject.elements[elementIndex].shortcut then longestShortcut = math.max(longestShortcut, unicode.len(contextMenuObject.elements[elementIndex].shortcut)) end
|
||||
end
|
||||
end
|
||||
contextMenuObject.width, contextMenuObject.height = longestElement + 4 + (longestShortcut > 0 and longestShortcut + 3 or 0), #contextMenuObject.elements
|
||||
object.height = #object.items * (object.spaceBetweenElements + 1) + object.spaceBetweenElements
|
||||
|
||||
-- А это чтоб за края экрана не лезло
|
||||
if contextMenuObject.y + contextMenuObject.height >= buffer.screen.height then contextMenuObject.y = buffer.screen.height - contextMenuObject.height end
|
||||
if contextMenuObject.x + contextMenuObject.width + 1 >= buffer.screen.width then contextMenuObject.x = buffer.screen.width - contextMenuObject.width - 1 end
|
||||
|
||||
local oldPixels = buffer.copy(contextMenuObject.x, contextMenuObject.y, contextMenuObject.width + 1, contextMenuObject.height + 1)
|
||||
local oldPixels = buffer.copy(object.x, object.y, object.width + 1, object.height + 1)
|
||||
local function quit()
|
||||
buffer.paste(contextMenuObject.x, contextMenuObject.y, oldPixels)
|
||||
buffer.paste(object.x, object.y, oldPixels)
|
||||
buffer.draw()
|
||||
buffer.setDrawLimit(oldDrawLimit)
|
||||
end
|
||||
|
||||
drawContextMenu(contextMenuObject)
|
||||
drawDropDownMenu(object)
|
||||
buffer.draw()
|
||||
|
||||
while true do
|
||||
local e = {event.pull()}
|
||||
if e[1] == "touch" then
|
||||
local objectFound = false
|
||||
for elementIndex = 1, #contextMenuObject.elements do
|
||||
if e[3] >= contextMenuObject.x and e[3] <= contextMenuObject.x + contextMenuObject.width - 1 and e[4] == contextMenuObject.y + elementIndex - 1 then
|
||||
for itemIndex = 1, #object.items do
|
||||
if
|
||||
e[3] >= object.x and
|
||||
e[3] <= object.x + object.width - 1 and
|
||||
e[4] == object.y + itemIndex * (object.spaceBetweenElements + 1) - 1
|
||||
then
|
||||
objectFound = true
|
||||
if not contextMenuObject.elements[elementIndex].disabled and contextMenuObject.elements[elementIndex].type == GUI.contextMenuElementTypes.default then
|
||||
drawContextMenuElement(contextMenuObject, elementIndex, true)
|
||||
if not object.items[itemIndex].disabled and object.items[itemIndex].type == GUI.dropDownMenuElementTypes.default then
|
||||
drawDropDownMenuElement(object, itemIndex, true)
|
||||
buffer.draw()
|
||||
os.sleep(0.2)
|
||||
quit()
|
||||
return contextMenuObject.elements[elementIndex].text
|
||||
return object.items[itemIndex].text, itemIndex
|
||||
end
|
||||
break
|
||||
end
|
||||
@ -589,43 +656,97 @@ local function showContextMenu(contextMenuObject)
|
||||
end
|
||||
end
|
||||
|
||||
local function addContextMenuElement(contextMenuObject, text, disabled, shortcut, color)
|
||||
local element = {}
|
||||
element.type = GUI.contextMenuElementTypes.default
|
||||
element.text = text
|
||||
element.disabled = disabled
|
||||
element.shortcut = shortcut
|
||||
element.color = color or GUI.colors.contextMenu.default.text --OPTIMIZATION
|
||||
local function addDropDownMenuItem(object, text, disabled, shortcut, color)
|
||||
local item = {}
|
||||
item.type = GUI.dropDownMenuElementTypes.default
|
||||
item.text = text
|
||||
item.disabled = disabled
|
||||
item.shortcut = shortcut
|
||||
item.color = color
|
||||
|
||||
table.insert(contextMenuObject.elements, element)
|
||||
return element
|
||||
table.insert(object.items, item)
|
||||
return item
|
||||
end
|
||||
|
||||
local function addContextMenuSeparator(contextMenuObject)
|
||||
local element = {type = GUI.contextMenuElementTypes.separator}
|
||||
table.insert(contextMenuObject.elements, element)
|
||||
return element
|
||||
local function addDropDownMenuSeparator(object)
|
||||
local item = {type = GUI.dropDownMenuElementTypes.separator}
|
||||
table.insert(object.items, item)
|
||||
return item
|
||||
end
|
||||
|
||||
function GUI.dropDownMenu(x, y, width, spaceBetweenElements, backgroundColor, textColor, backgroundPressedColor, textPressedColor, disabledColor, separatorColor, transparency, items)
|
||||
local object = GUI.object(x, y, width, 1)
|
||||
object.colors = {
|
||||
default = {
|
||||
background = backgroundColor,
|
||||
text = textColor
|
||||
},
|
||||
pressed = {
|
||||
background = backgroundPressedColor,
|
||||
text = textPressedColor
|
||||
},
|
||||
disabled = {
|
||||
text = disabledColor
|
||||
},
|
||||
separator = separatorColor,
|
||||
transparency = transparency
|
||||
}
|
||||
object.sidesOffset = 2
|
||||
object.spaceBetweenElements = spaceBetweenElements
|
||||
object.addSeparator = addDropDownMenuSeparator
|
||||
object.addItem = addDropDownMenuItem
|
||||
object.items = {}
|
||||
if items then
|
||||
for i = 1, #items do
|
||||
object:addItem(items[i])
|
||||
end
|
||||
end
|
||||
object.drawShadow = true
|
||||
object.draw = drawDropDownMenu
|
||||
object.show = showDropDownMenu
|
||||
return object
|
||||
end
|
||||
|
||||
----------------------------------------- Context Menu -----------------------------------------
|
||||
|
||||
local function showContextMenu(object)
|
||||
-- Расчет ширины окна меню
|
||||
local longestItem, longestShortcut = 0, 0
|
||||
for itemIndex = 1, #object.items do
|
||||
if object.items[itemIndex].type == GUI.dropDownMenuElementTypes.default then
|
||||
longestItem = math.max(longestItem, unicode.len(object.items[itemIndex].text))
|
||||
if object.items[itemIndex].shortcut then longestShortcut = math.max(longestShortcut, unicode.len(object.items[itemIndex].shortcut)) end
|
||||
end
|
||||
end
|
||||
object.width = object.sidesOffset + longestItem + (longestShortcut > 0 and 3 + longestShortcut or 0) + object.sidesOffset
|
||||
object.height = #object.items * (object.spaceBetweenElements + 1) + object.spaceBetweenElements
|
||||
|
||||
-- А это чтоб за края экрана не лезло
|
||||
if object.y + object.height >= buffer.screen.height then object.y = buffer.screen.height - object.height end
|
||||
if object.x + object.width + 1 >= buffer.screen.width then object.x = buffer.screen.width - object.width - 1 end
|
||||
|
||||
object:reimplementedShow()
|
||||
end
|
||||
|
||||
function GUI.contextMenu(x, y, ...)
|
||||
local argumentElements = {...}
|
||||
local argumentItems = {...}
|
||||
local object = GUI.dropDownMenu(x, y, 1, 0, GUI.colors.contextMenu.default.background, GUI.colors.contextMenu.default.text, GUI.colors.contextMenu.pressed.background, GUI.colors.contextMenu.pressed.text, GUI.colors.contextMenu.disabled.text, GUI.colors.contextMenu.separator, GUI.colors.contextMenu.transparency.background)
|
||||
|
||||
local contextMenuObject = GUI.object(x, y, 1, 1)
|
||||
contextMenuObject.elements = {}
|
||||
contextMenuObject.addElement = addContextMenuElement
|
||||
contextMenuObject.addSeparator = addContextMenuSeparator
|
||||
contextMenuObject.show = showContextMenu
|
||||
contextMenuObject.selectedElement = nil
|
||||
|
||||
for elementIndex = 1, #argumentElements do
|
||||
if argumentElements[elementIndex] == "-" then
|
||||
contextMenuObject:addSeparator()
|
||||
-- Заполняем менюшку парашей
|
||||
for itemIndex = 1, #argumentItems do
|
||||
if argumentItems[itemIndex] == "-" then
|
||||
object:addSeparator()
|
||||
else
|
||||
contextMenuObject:addElement(argumentElements[elementIndex][1], argumentElements[elementIndex][2], argumentElements[elementIndex][3], argumentElements[elementIndex][4])
|
||||
object:addItem(argumentItems[itemIndex][1], argumentItems[itemIndex][2], argumentItems[itemIndex][3], argumentItems[itemIndex][4])
|
||||
end
|
||||
end
|
||||
|
||||
return contextMenuObject
|
||||
object.reimplementedShow = object.show
|
||||
object.show = showContextMenu
|
||||
object.selectedElement = nil
|
||||
object.spaceBetweenElements = 0
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
----------------------------------------- Menu -----------------------------------------
|
||||
@ -1155,15 +1276,144 @@ function GUI.switch(x, y, width, activeColor, passiveColor, pipeColor, state)
|
||||
return object
|
||||
end
|
||||
|
||||
----------------------------------------- Chart object -----------------------------------------
|
||||
|
||||
local function drawChart(object)
|
||||
-- Ебошем пездатые оси
|
||||
for i = object.y, object.y + object.height - 2 do buffer.text(object.x, i, object.colors.axis, "│") end
|
||||
buffer.text(object.x + 1, object.y + object.height - 1, object.colors.axis, string.rep("─", object.width - 1))
|
||||
buffer.text(object.x, object.y + object.height - 1, object.colors.axis, "└")
|
||||
|
||||
if #object.values > 1 then
|
||||
local oldDrawLimit = buffer.getDrawLimit()
|
||||
buffer.setDrawLimit(object.x, object.y, object.width, object.height)
|
||||
|
||||
local delta, fieldWidth, fieldHeight = object.maximumValue - object.minimumValue, object.width - 2, object.height - 1
|
||||
|
||||
-- Рисуем линии значений
|
||||
local roundValues = object.maximumValue > 10
|
||||
local step = 0.2 * fieldHeight
|
||||
for i = step, fieldHeight, step do
|
||||
local value = object.minimumValue + delta * (i / fieldHeight)
|
||||
local stringValue = roundValues and tostring(math.floor(value)) or math.doubleToString(value, 1)
|
||||
buffer.text(object.x + 1, math.floor(object.y + fieldHeight - i), object.colors.value, string.rep("─", object.width - unicode.len(stringValue) - 2) .. " " .. stringValue)
|
||||
end
|
||||
|
||||
-- Рисуем графек, йопта
|
||||
local function getDotPosition(valueIndex)
|
||||
return
|
||||
object.x + math.round((fieldWidth * (valueIndex - 1) / (#object.values - 1))) + 1,
|
||||
object.y + math.round(((fieldHeight - 1) * (object.maximumValue - object.values[valueIndex]) / delta))
|
||||
end
|
||||
|
||||
local x, y = getDotPosition(1)
|
||||
for valueIndex = 2, #object.values do
|
||||
local xNew, yNew = getDotPosition(valueIndex)
|
||||
buffer.semiPixelLine(x, y * 2, xNew, yNew * 2, object.colors.chart)
|
||||
x, y = xNew, yNew
|
||||
end
|
||||
|
||||
buffer.setDrawLimit(oldDrawLimit)
|
||||
end
|
||||
|
||||
-- Дорисовываем названия осей
|
||||
if object.axisNames.y then buffer.text(object.x + 1, object.y, object.colors.axis, object.axisNames.y) end
|
||||
if object.axisNames.x then buffer.text(object.x + object.width - unicode.len(object.axisNames.x), object.y + object.height - 2, object.colors.axis, object.axisNames.x) end
|
||||
end
|
||||
|
||||
function GUI.chart(x, y, width, height, axisColor, axisValueColor, chartColor, xAxisName, yAxisName, minimumValue, maximumValue, values)
|
||||
if minimumValue >= maximumValue then error("Chart's minimum value can't be >= maximum value!") end
|
||||
local object = GUI.object(x, y, width, height)
|
||||
object.colors = {axis = axisColor, chart = chartColor, value = axisValueColor}
|
||||
object.draw = drawChart
|
||||
object.values = values
|
||||
object.minimumValue = minimumValue
|
||||
object.maximumValue = maximumValue
|
||||
object.axisNames = {x = xAxisName, y = yAxisName}
|
||||
return object
|
||||
end
|
||||
|
||||
----------------------------------------- Combo Box Object -----------------------------------------
|
||||
|
||||
local function drawComboBox(object)
|
||||
buffer.square(object.x, object.y, object.width, object.height, object.colors.default.background)
|
||||
local x, y, limit, arrowSize = object.x + 1, math.floor(object.y + object.height / 2), object.width - 5, object.height
|
||||
buffer.text(x, y, object.colors.default.text, string.limit(object.items[object.currentItem].text, limit, false))
|
||||
GUI.button(object.x + object.width - arrowSize * 2 + 1, object.y, arrowSize * 2 - 1, arrowSize, object.colors.arrow.background, object.colors.arrow.text, 0x0, 0x0, object.state and "▲" or "▼"):draw()
|
||||
end
|
||||
|
||||
local function selectComboBoxItem(object)
|
||||
object.state = true
|
||||
object:draw()
|
||||
|
||||
local dropDownMenu = GUI.dropDownMenu(object.x, object.y + object.height, object.width, object.height == 1 and 0 or 1, object.colors.default.background, object.colors.default.text, object.colors.pressed.background, object.colors.pressed.text, GUI.colors.contextMenu.disabled.text, GUI.colors.contextMenu.separator, GUI.colors.contextMenu.transparency.background, object.items)
|
||||
dropDownMenu.items = object.items
|
||||
dropDownMenu.sidesOffset = 1
|
||||
local _, itemIndex = dropDownMenu:show()
|
||||
|
||||
object.currentItem = itemIndex or object.currentItem
|
||||
object.state = false
|
||||
object:draw()
|
||||
buffer.draw()
|
||||
end
|
||||
|
||||
function GUI.comboBox(x, y, width, height, backgroundColor, textColor, arrowBackgroundColor, arrowTextColor, items)
|
||||
local object = GUI.object(x, y, width, height)
|
||||
object.colors = {
|
||||
default = {
|
||||
background = backgroundColor,
|
||||
text = textColor
|
||||
},
|
||||
pressed = {
|
||||
background = GUI.colors.contextMenu.pressed.background,
|
||||
text = GUI.colors.contextMenu.pressed.text
|
||||
},
|
||||
arrow = {
|
||||
background = arrowBackgroundColor,
|
||||
text = arrowTextColor
|
||||
}
|
||||
}
|
||||
object.items = {}
|
||||
object.currentItem = 1
|
||||
object.addItem = addDropDownMenuItem
|
||||
object.addSeparator = addDropDownMenuSeparator
|
||||
if items then
|
||||
for i = 1, #items do
|
||||
object:addItem(items[i])
|
||||
end
|
||||
end
|
||||
object.draw = drawComboBox
|
||||
object.selectItem = selectComboBoxItem
|
||||
object.state = false
|
||||
return object
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- buffer.start()
|
||||
-- buffer.clear(0x1b1b1b)
|
||||
-- buffer.draw(true)
|
||||
|
||||
-- GUI.switch(2, 2, 8, 0x77FF77, 0x999999, 0xFFFFFF, true):draw()
|
||||
-- local comboBox = GUI.comboBox(2, 2, 30, 1, 0xFFFFFF, 0x262626, 0xDDDDDD, 0x262626, {"PIC", "RAW", "PNG", "JPG"})
|
||||
-- comboBox:selectItem()
|
||||
|
||||
-- buffer.draw()
|
||||
|
||||
-- GUI.chart(2, 10, 40, 20, 0xFFFFFF, 0xBBBBBB, 0xFFDB40, "t", "EU", 0, 2, {
|
||||
-- 0.5,
|
||||
-- 0.12
|
||||
-- }):draw()
|
||||
|
||||
-- local menu = GUI.dropDownMenu(2, 2, 40, 1, 0xFFFFFF, 0x000000, 0xFFDB40, 0xFFFFFF, 0x999999, 0x777777, 50)
|
||||
-- menu:addItem("New")
|
||||
-- menu:addItem("Open")
|
||||
-- menu:addSeparator()
|
||||
-- menu:addItem("Save")
|
||||
-- menu:addItem("Save as")
|
||||
-- menu:show()
|
||||
|
||||
-- GUI.contextMenu(2, 2, {"Hello"}, {"World"}, "-", {"You are the"}, {"Best of best", false, "^S"}, {"And bestest yopta"}):show()
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return GUI
|
||||
|
||||
@ -8,6 +8,7 @@ local libraries = {
|
||||
|
||||
for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end; libraries = nil
|
||||
|
||||
local gpu = component.gpu
|
||||
local buffer = {}
|
||||
|
||||
------------------------------------------------- Вспомогательные методы -----------------------------------------------------------------
|
||||
@ -71,12 +72,12 @@ end
|
||||
|
||||
-- Инициализация буфера со всеми необходимыми параметрами, вызывается автоматически
|
||||
function buffer.start()
|
||||
buffer.flush(component.gpu.getResolution())
|
||||
buffer.flush(gpu.getResolution())
|
||||
end
|
||||
|
||||
-- Изменение разрешения экрана и пересоздание массивов буфера
|
||||
function buffer.changeResolution(width, height)
|
||||
component.gpu.setResolution(width, height)
|
||||
gpu.setResolution(width, height)
|
||||
buffer.flush(width, height)
|
||||
end
|
||||
|
||||
@ -495,6 +496,42 @@ function buffer.semiPixelSquare(x, y, width, height, color)
|
||||
end
|
||||
end
|
||||
|
||||
function buffer.semiPixelLine(x0, y0, x1, y1, color)
|
||||
local steep = false;
|
||||
|
||||
if math.abs(x0 - x1) < math.abs(y0 - y1 ) then
|
||||
x0, y0 = swap(x0, y0)
|
||||
x1, y1 = swap(x1, y1)
|
||||
steep = true;
|
||||
end
|
||||
|
||||
if (x0 > x1) then
|
||||
x0, x1 = swap(x0, x1)
|
||||
y0, y1 = swap(y0, y1)
|
||||
end
|
||||
|
||||
local dx = x1 - x0;
|
||||
local dy = y1 - y0;
|
||||
local derror2 = math.abs(dy) * 2
|
||||
local error2 = 0;
|
||||
local y = y0;
|
||||
|
||||
for x = x0, x1, 1 do
|
||||
if steep then
|
||||
buffer.semiPixelSet(y, x, color);
|
||||
else
|
||||
buffer.semiPixelSet(x, y, color)
|
||||
end
|
||||
|
||||
error2 = error2 + derror2;
|
||||
|
||||
if error2 > dx then
|
||||
y = y + (y1 > y0 and 1 or -1);
|
||||
error2 = error2 - dx * 2;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------- Просчет изменений и отрисовка ------------------------------------------------------------------------
|
||||
|
||||
--Функция рассчитывает изменения и применяет их, возвращая то, что было изменено
|
||||
@ -595,11 +632,11 @@ function buffer.draw(force)
|
||||
|
||||
--Перебираем все цвета текста и фона, выполняя гпу-операции
|
||||
for foreground in pairs(buffer.screen.changes) do
|
||||
if currentForeground ~= foreground then component.gpu.setForeground(foreground); currentForeground = foreground end
|
||||
if currentForeground ~= foreground then gpu.setForeground(foreground); currentForeground = foreground end
|
||||
for background in pairs(buffer.screen.changes[foreground]) do
|
||||
if currentBackground ~= background then component.gpu.setBackground(background); currentBackground = background end
|
||||
if currentBackground ~= background then gpu.setBackground(background); currentBackground = background end
|
||||
for i = 1, #buffer.screen.changes[foreground][background], 3 do
|
||||
component.gpu.set(buffer.screen.changes[foreground][background][i], buffer.screen.changes[foreground][background][i + 1], buffer.screen.changes[foreground][background][i + 2])
|
||||
gpu.set(buffer.screen.changes[foreground][background][i], buffer.screen.changes[foreground][background][i + 1], buffer.screen.changes[foreground][background][i + 2])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -44,19 +44,19 @@ local function buttonHandler(window, object, objectIndex, eventData)
|
||||
object.pressed = true; window:draw(); buffer.draw()
|
||||
os.sleep(0.2)
|
||||
object.pressed = false; window:draw(); buffer.draw()
|
||||
executeObjectMethod(object.onTouch, object, eventData)
|
||||
executeObjectMethod(object.onTouch, eventData)
|
||||
end
|
||||
|
||||
local function tabBarTabHandler(window, object, objectIndex, eventData)
|
||||
object.parent.parent.selectedTab = objectIndex
|
||||
window:draw(); buffer:draw()
|
||||
executeObjectMethod(object.parent.parent.onTabSwitched, object, eventData)
|
||||
executeObjectMethod(object.parent.parent.onTabSwitched, eventData)
|
||||
end
|
||||
|
||||
local function inputTextBoxHandler(window, object, objectIndex, eventData)
|
||||
object:input()
|
||||
window:draw(); buffer:draw()
|
||||
executeObjectMethod(object.onInputFinished, object, eventData)
|
||||
executeObjectMethod(object.onInputFinished, eventData)
|
||||
end
|
||||
|
||||
local function textBoxScrollHandler(window, object, objectIndex, eventData)
|
||||
@ -67,13 +67,18 @@ 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()
|
||||
executeObjectMethod(object.onValueChanged, object, eventData)
|
||||
executeObjectMethod(object.onValueChanged, eventData)
|
||||
end
|
||||
|
||||
local function switchHandler(window, object, objectIndex, eventData)
|
||||
object.state = not object.state
|
||||
window:draw(); buffer:draw()
|
||||
executeObjectMethod(object.onStateChanged, object, eventData)
|
||||
executeObjectMethod(object.onStateChanged, eventData)
|
||||
end
|
||||
|
||||
local function comboBoxHandler(window, object, objectIndex, eventData)
|
||||
object:selectItem()
|
||||
executeObjectMethod(object.onItemSelected, eventData)
|
||||
end
|
||||
|
||||
function windows.handleEventData(window, eventData)
|
||||
@ -90,6 +95,8 @@ function windows.handleEventData(window, eventData)
|
||||
horizontalSliderHandler(window, object, objectIndex, eventData)
|
||||
elseif object.type == GUI.objectTypes.switch then
|
||||
switchHandler(window, object, objectIndex, eventData)
|
||||
elseif object.type == GUI.objectTypes.comboBox then
|
||||
comboBoxHandler(window, object, objectIndex, eventData)
|
||||
elseif object.onTouch then
|
||||
executeObjectMethod(object.onTouch, eventData)
|
||||
end
|
||||
@ -118,6 +125,15 @@ function windows.handleEventData(window, eventData)
|
||||
else
|
||||
executeObjectMethod(window.onDrag, eventData)
|
||||
end
|
||||
elseif eventData[1] == "drop" then
|
||||
local object, objectIndex = window:getClickedObject(eventData[3], eventData[4])
|
||||
if object then
|
||||
if object.onDrag then
|
||||
executeObjectMethod(object.onDrop, eventData)
|
||||
end
|
||||
else
|
||||
executeObjectMethod(window.onDrop, eventData)
|
||||
end
|
||||
elseif eventData[1] == "key_down" then
|
||||
executeObjectMethod(window.onKeyDown, eventData)
|
||||
elseif eventData[1] == "key_up" then
|
||||
@ -158,7 +174,7 @@ end
|
||||
|
||||
local function drawWindow(window)
|
||||
if window.onDrawStarted then window.onDrawStarted() end
|
||||
window:reimplementedDraw()
|
||||
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()
|
||||
@ -171,7 +187,7 @@ local function newWindow(x, y, width, height, minimumWidth, minimumHeight)
|
||||
window.minimumWidth = minimumWidth
|
||||
window.minimumHeight = minimumHeight
|
||||
window.drawShadow = true
|
||||
window.reimplementedDraw = window.draw
|
||||
window.update = window.draw
|
||||
window.draw = drawWindow
|
||||
window.handleEventData = windows.handleEventData
|
||||
window.handleEvents = windows.handleEvents
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user