mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2026-01-07 19:52:40 +01:00
Added Multiscreen and Shooting applications
This commit is contained in:
parent
fe0e286ee0
commit
10ad19ae75
BIN
Applications/Multiscreen.app/Icon.pic
Normal file
BIN
Applications/Multiscreen.app/Icon.pic
Normal file
Binary file not shown.
313
Applications/Multiscreen.app/Main.lua
Normal file
313
Applications/Multiscreen.app/Main.lua
Normal file
@ -0,0 +1,313 @@
|
||||
|
||||
local color = require("Color")
|
||||
local screen = require("Screen")
|
||||
local GUI = require("GUI")
|
||||
local event = require("Event")
|
||||
local filesystem = require("Filesystem")
|
||||
local system = require("System")
|
||||
local paths = require("Paths")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local configPath = paths.user.applicationData .. "MultiScreen/Config.cfg"
|
||||
local elementWidth = 48
|
||||
local baseResolutionWidth = 146
|
||||
local baseResolutionHeight = 54
|
||||
local GPUProxy = screen.getGPUProxy()
|
||||
local mainScreenAddress = GPUProxy.getScreen()
|
||||
|
||||
local config = {
|
||||
backgroundColor = 0x0,
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
if filesystem.exists(configPath) then
|
||||
config = filesystem.readTable(configPath)
|
||||
end
|
||||
|
||||
local function saveConfig()
|
||||
filesystem.writeTable(configPath, config, true)
|
||||
end
|
||||
|
||||
local workspace, window = system.addWindow(GUI.filledWindow(1, 1, 64, 37, 0x2D2D2D))
|
||||
|
||||
local layout = window:addChild(GUI.layout(1, 1, window.width, window.height, 1, 1))
|
||||
|
||||
local function clearScreens()
|
||||
for address in component.list("screen") do
|
||||
if address ~= mainScreenAddress then
|
||||
GPUProxy.bind(address, false)
|
||||
GPUProxy.setDepth(8)
|
||||
GPUProxy.setResolution(baseResolutionWidth, baseResolutionHeight)
|
||||
GPUProxy.setBackground(config.backgroundColor)
|
||||
GPUProxy.fill(1, 1, baseResolutionWidth, baseResolutionHeight, " ")
|
||||
end
|
||||
end
|
||||
|
||||
GPUProxy.bind(mainScreenAddress, false)
|
||||
end
|
||||
|
||||
local function addButton(text)
|
||||
local button = layout:addChild(GUI.button(1, 1, elementWidth, 3, 0x4B4B4B, 0xD2D2D2, 0xD2D2D2, 0x4B4B4B, text))
|
||||
button.colors.disabled.background = 0x3C3C3C
|
||||
button.colors.disabled.text = 0x5A5A5A
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
local function addTextBox(lines)
|
||||
local textBox = layout:addChild(GUI.textBox(1, 1, elementWidth, 16, nil, 0x969696, lines, 1, 0, 0, true, true))
|
||||
textBox.eventHandler = nil
|
||||
|
||||
return textBox
|
||||
end
|
||||
|
||||
local function mainMenu(force)
|
||||
layout:removeChildren()
|
||||
|
||||
local lines = {
|
||||
{color = 0xE1E1E1, text = "Welcome to MultiScreen software"},
|
||||
" ",
|
||||
"You can combine multiple screens into a single cluster and draw huge images saved in OCIF5 format. Image converter converter can be downloaded from it's repository:",
|
||||
"github.com/IgorTimofeev/OCIFImageConverter",
|
||||
" ",
|
||||
"There's some useful tips for best experience:",
|
||||
"• Use maximum size constructions for each screen (8x6 blocks)",
|
||||
"• Connect more power sources to screens if they're blinking",
|
||||
" "
|
||||
}
|
||||
|
||||
if config.map then
|
||||
table.insert(lines, {color = 0xE1E1E1, text = "Current cluster properties:"})
|
||||
table.insert(lines, " ")
|
||||
local width, height = #config.map[1], #config.map
|
||||
table.insert(lines, width .. "x" .. height .. " screen blocks")
|
||||
table.insert(lines, width * baseResolutionWidth .. "x" .. height * baseResolutionHeight .. " OpenComputers pixels")
|
||||
table.insert(lines, width * baseResolutionWidth * 2 .. "x" .. height * baseResolutionHeight * 4 .. " pixels using Braille font")
|
||||
else
|
||||
table.insert(lines, {color = 0xFF4940, text = "Calibrate your system before starting"})
|
||||
end
|
||||
|
||||
addTextBox(lines)
|
||||
|
||||
local actionComboBox = layout:addChild(GUI.comboBox(1, 1, elementWidth, 3, 0xEEEEEE, 0x2D2D2D, 0x3C3C3C, 0x888888))
|
||||
actionComboBox:addItem("Draw image")
|
||||
actionComboBox:addItem("Clear screens")
|
||||
actionComboBox:addItem("Calibrate")
|
||||
|
||||
local filesystemChooser = layout:addChild(GUI.filesystemChooser(1, 1, elementWidth, 3, 0xE1E1E1, 0x888888, 0x3C3C3C, 0x888888, nil, "Open", "Cancel", "Choose file", "/"))
|
||||
filesystemChooser:setMode(GUI.IO_MODE_OPEN, GUI.IO_MODE_FILE)
|
||||
filesystemChooser:addExtensionFilter(".pic")
|
||||
|
||||
local colorSelector = layout:addChild(GUI.colorSelector(2, 2, elementWidth, 3, config.backgroundColor, "Choose color"))
|
||||
|
||||
local actionButton = addButton("Next")
|
||||
|
||||
actionComboBox.onItemSelected = function()
|
||||
filesystemChooser.hidden = actionComboBox.selectedItem ~= 1
|
||||
colorSelector.hidden = actionComboBox.selectedItem ~= 2
|
||||
actionButton.disabled = actionComboBox.selectedItem == 1 and (not filesystemChooser.path or not config.map)
|
||||
end
|
||||
|
||||
filesystemChooser.onSubmit = function()
|
||||
actionComboBox.onItemSelected()
|
||||
workspace:draw()
|
||||
end
|
||||
|
||||
actionButton.onTouch = function()
|
||||
if actionComboBox.selectedItem == 1 then
|
||||
local file = filesystem.open(filesystemChooser.path, "rb")
|
||||
|
||||
local signature = file:readString(4)
|
||||
if signature == "OCIF" then
|
||||
local encodingMethod = file:readBytes(1)
|
||||
if encodingMethod == 5 then
|
||||
local width = file:readBytes(2)
|
||||
local height = file:readBytes(2)
|
||||
|
||||
clearScreens()
|
||||
|
||||
local background, foreground, symbol, currentBackground, currentForeground, currentAddress
|
||||
for y = 1, height do
|
||||
for x = 1, width do
|
||||
background = color.to24Bit(file:readBytes(1))
|
||||
foreground = color.to24Bit(file:readBytes(1))
|
||||
file:readBytes(1)
|
||||
symbol = file:readUnicodeChar()
|
||||
|
||||
local xMonitor = math.ceil(x / baseResolutionWidth)
|
||||
local yMonitor = math.ceil(y / baseResolutionHeight)
|
||||
|
||||
if config.map[yMonitor] and config.map[yMonitor][xMonitor] then
|
||||
if currentAddress ~= config.map[yMonitor][xMonitor] then
|
||||
GPUProxy.bind(config.map[yMonitor][xMonitor], false)
|
||||
GPUProxy.setBackground(background)
|
||||
GPUProxy.setForeground(foreground)
|
||||
|
||||
currentAddress, currentBackground, currentForeground = config.map[yMonitor][xMonitor], background, foreground
|
||||
end
|
||||
|
||||
if currentBackground ~= background then
|
||||
GPUProxy.setBackground(background)
|
||||
currentBackground = background
|
||||
end
|
||||
|
||||
if currentForeground ~= foreground then
|
||||
GPUProxy.setForeground(foreground)
|
||||
currentForeground = foreground
|
||||
end
|
||||
|
||||
GPUProxy.set(x - (xMonitor - 1) * baseResolutionWidth, y - (yMonitor - 1) * baseResolutionHeight, symbol)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
file:close()
|
||||
|
||||
GPUProxy.bind(mainScreenAddress, false)
|
||||
GUI.alert("Done.")
|
||||
else
|
||||
file:close()
|
||||
GUI.alert("Wrong encodingMethod: " .. tostring(encodingMethod))
|
||||
end
|
||||
else
|
||||
file:close()
|
||||
GUI.alert("Wrong signature: " .. tostring(signature))
|
||||
end
|
||||
elseif actionComboBox.selectedItem == 2 then
|
||||
config.backgroundColor = colorSelector.color
|
||||
saveConfig()
|
||||
clearScreens()
|
||||
else
|
||||
layout:removeChildren()
|
||||
|
||||
addTextBox({
|
||||
{color = 0xE1E1E1, text = "Screen cluster calibration"},
|
||||
" ",
|
||||
"Specify required count of screens (not screen blocks, screens!) by horizontal and vertical"
|
||||
})
|
||||
|
||||
local hSlider = layout:addChild(GUI.slider(1, 1, elementWidth, 0x66DB80, 0x0, 0xFFFFFF, 0xAAAAAA, 1, 10, 5, false, "Screens by horizontal: ", ""))
|
||||
hSlider.roundValues = true
|
||||
hSlider.height = 2
|
||||
|
||||
local vSlider = layout:addChild(GUI.slider(1, 1, elementWidth, 0x66DB80, 0x0, 0xFFFFFF, 0xAAAAAA, 1, 10, 4, false, "Screens by vertical: ", ""))
|
||||
vSlider.roundValues = true
|
||||
vSlider.height = 2
|
||||
|
||||
addButton("Next").onTouch = function()
|
||||
local connectedCount = -1
|
||||
for address in component.list("screen") do
|
||||
connectedCount = connectedCount + 1
|
||||
end
|
||||
|
||||
hSlider.value, vSlider.value = math.floor(hSlider.value), math.floor(vSlider.value)
|
||||
local specifiedCount = hSlider.value * vSlider.value
|
||||
|
||||
if specifiedCount <= connectedCount then
|
||||
layout:removeChildren()
|
||||
|
||||
addTextBox({
|
||||
{color = 0xE1E1E1, text = "Screen cluster calibration"},
|
||||
" ",
|
||||
"Touch highlighted screen with your hand once. After touching all of screens calibration will be finished"
|
||||
})
|
||||
|
||||
local SSX, SSY = 1, 1
|
||||
local function screenObjectDraw(object)
|
||||
screen.drawRectangle(object.x, object.y, object.width, object.height, (SSX == object.SX and SSY == object.SY) and 0x22FF22 or 0xE1E1E1, 0x0, " ")
|
||||
end
|
||||
|
||||
local function newScreen(SX, SY)
|
||||
local object = GUI.object(1, 1, 8, 3)
|
||||
object.draw = screenObjectDraw
|
||||
object.SX = SX
|
||||
object.SY = SY
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
local function newScreenLine(SY)
|
||||
local lineLayout = GUI.layout(1, 1, layout.width, 3, 1, 1)
|
||||
lineLayout:setDirection(1, 1, GUI.DIRECTION_HORIZONTAL)
|
||||
lineLayout:setSpacing(1, 1, 2)
|
||||
|
||||
for SX = 1, hSlider.value do
|
||||
lineLayout:addChild(newScreen(SX, SY))
|
||||
end
|
||||
|
||||
return lineLayout
|
||||
end
|
||||
|
||||
for SY = 1, vSlider.value do
|
||||
layout:addChild(newScreenLine(SY))
|
||||
end
|
||||
|
||||
workspace:draw()
|
||||
|
||||
clearScreens(0x0)
|
||||
|
||||
config.map = {}
|
||||
local hue, hueStep = 0, 360 / specifiedCount
|
||||
while true do
|
||||
local e1, e2 = event.pull()
|
||||
if e1 == "touch" then
|
||||
if e2 ~= mainScreenAddress then
|
||||
GPUProxy.bind(e2, false)
|
||||
GPUProxy.setDepth(8)
|
||||
GPUProxy.setResolution(baseResolutionWidth, baseResolutionHeight)
|
||||
GPUProxy.setBackground(color.HSBToInteger(hue, 1, 1))
|
||||
GPUProxy.setForeground(0x0)
|
||||
GPUProxy.fill(1, 1, baseResolutionWidth, baseResolutionHeight, " ")
|
||||
|
||||
local text = "Screen " .. SSX .. "x" .. SSY .. " has been calibrated"
|
||||
GPUProxy.set(math.floor(baseResolutionWidth / 2 - unicode.len(text) / 2), math.floor(baseResolutionHeight / 2), text)
|
||||
|
||||
GPUProxy.bind(mainScreenAddress, false)
|
||||
|
||||
config.map[SSY] = config.map[SSY] or {}
|
||||
config.map[SSY][SSX] = e2
|
||||
|
||||
SSX, hue = SSX + 1, hue + hueStep
|
||||
if SSX > hSlider.value then
|
||||
SSX, SSY = 1, SSY + 1
|
||||
if SSY > vSlider.value then
|
||||
saveConfig()
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
workspace:draw()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
GUI.alert("All screens has been successfully calibrated")
|
||||
mainMenu()
|
||||
else
|
||||
GUI.alert("Invalid count of connected screens. You're specified " .. specifiedCount .. " of screens, but there's " .. connectedCount .. " connected screens")
|
||||
end
|
||||
end
|
||||
|
||||
workspace:draw()
|
||||
end
|
||||
end
|
||||
|
||||
actionComboBox.onItemSelected()
|
||||
workspace:draw(force)
|
||||
end
|
||||
|
||||
window.onResize = function(width, height)
|
||||
window.backgroundPanel.width = width
|
||||
window.backgroundPanel.height = height
|
||||
|
||||
layout.width = width
|
||||
layout.height = height
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
window:resize(window.width, window.height)
|
||||
mainMenu(true)
|
||||
workspace:draw()
|
||||
BIN
Applications/Shooting.app/Icon.pic
Normal file
BIN
Applications/Shooting.app/Icon.pic
Normal file
Binary file not shown.
3
Applications/Shooting.app/Localizations/English.lang
Normal file
3
Applications/Shooting.app/Localizations/English.lang
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
greeting = "Hello, "
|
||||
}
|
||||
3
Applications/Shooting.app/Localizations/French.lang
Normal file
3
Applications/Shooting.app/Localizations/French.lang
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
greeting = "Bonjour, "
|
||||
}
|
||||
3
Applications/Shooting.app/Localizations/German.lang
Normal file
3
Applications/Shooting.app/Localizations/German.lang
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
greeting = "Gruß, "
|
||||
}
|
||||
3
Applications/Shooting.app/Localizations/Italian.lang
Normal file
3
Applications/Shooting.app/Localizations/Italian.lang
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
greeting = "Ciao, "
|
||||
}
|
||||
3
Applications/Shooting.app/Localizations/Russian.lang
Normal file
3
Applications/Shooting.app/Localizations/Russian.lang
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
greeting = "Привет, "
|
||||
}
|
||||
3
Applications/Shooting.app/Localizations/Ukrainian.lang
Normal file
3
Applications/Shooting.app/Localizations/Ukrainian.lang
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
greeting = "Привіт, "
|
||||
}
|
||||
101
Applications/Shooting.app/Main.lua
Normal file
101
Applications/Shooting.app/Main.lua
Normal file
@ -0,0 +1,101 @@
|
||||
|
||||
local GUI = require("GUI")
|
||||
local system = require("System")
|
||||
local screen = require("Screen")
|
||||
local color = require("Color")
|
||||
local bigLetters = require("BigLetters")
|
||||
local color = require("Color")
|
||||
local system = require("System")
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
local function drawcircle(x0, y0, radius, color)
|
||||
local x = radius - 1
|
||||
local y = 0
|
||||
local dx = 1
|
||||
local dy = 1
|
||||
local err = dx - bit32.lshift(radius, 1)
|
||||
|
||||
while x >= y do
|
||||
screen.drawSemiPixelLine(x0 - x, y0 + y, x0 + x, y0 + y, color)
|
||||
screen.drawSemiPixelLine(x0 - y, y0 + x, x0 + y, y0 + x, color)
|
||||
screen.drawSemiPixelLine(x0 - x, y0 - y, x0 + x, y0 - y, color)
|
||||
screen.drawSemiPixelLine(x0 - y, y0 - x, x0 + y, y0 - x, color)
|
||||
|
||||
if err <= 0 then
|
||||
y = y + 1
|
||||
err = err + dy
|
||||
dy = dy + 2
|
||||
end
|
||||
|
||||
if err > 0 then
|
||||
x = x - 1
|
||||
dx = dx + 2
|
||||
err = err + dx - bit32.lshift(radius, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local radius = 30
|
||||
local size = radius * 2
|
||||
local points = {}
|
||||
local players = {}
|
||||
local lastPlayer
|
||||
|
||||
local workspace, window = system.addWindow(GUI.filledWindow(1, 1, 104, 34, 0x1E1E1E))
|
||||
|
||||
local layout = window:addChild(GUI.layout(1, 1, window.width, window.height, 1, 1))
|
||||
layout:setDirection(1, 1, GUI.DIRECTION_HORIZONTAL)
|
||||
layout:setSpacing(1, 1, 8)
|
||||
|
||||
local circle = layout:addChild(GUI.object(1, 1, size, math.floor(size / 2)))
|
||||
|
||||
local function getColor()
|
||||
return lastPlayer and players[lastPlayer].color or 0x0092FF
|
||||
end
|
||||
|
||||
circle.draw = function()
|
||||
local r, limit = radius, 6
|
||||
for i = 1, limit do
|
||||
drawcircle(circle.x + radius - 1, circle.y * 2 + radius - 2, r, i == limit and 0xFF4940 or i % 2 == 0 and 0x0 or 0xE1E1E1)
|
||||
r = r - 5
|
||||
end
|
||||
|
||||
for i = 1, #points do
|
||||
screen.drawText(circle.x + points[i][1], circle.y + points[i][2], getColor(), "⬤")
|
||||
end
|
||||
end
|
||||
|
||||
local counter = layout:addChild(GUI.object(1, 1, 24, 5))
|
||||
counter.draw = function()
|
||||
local radius = 4
|
||||
drawcircle(counter.x + radius, counter.y * 2 + radius, radius, getColor())
|
||||
bigLetters.drawText(counter.x + radius * 2 + 4, counter.y, 0xE1E1E1, lastPlayer and tostring(players[lastPlayer].score) or "0")
|
||||
end
|
||||
|
||||
circle.eventHandler = function(workspace, circle, e1, e2, e3, e4, e5, e6)
|
||||
if e1 == "touch" then
|
||||
lastPlayer = e6
|
||||
players[lastPlayer] = players[lastPlayer] or {
|
||||
color = color.HSBToInteger(math.random(360), 1, 1),
|
||||
score = 0
|
||||
}
|
||||
|
||||
players[lastPlayer].score = math.max(0, radius - math.floor(math.sqrt((e3 - (circle.x + radius)) ^ 2 + (e4 * 2 - (circle.y * 2 + radius)) ^ 2)))
|
||||
|
||||
table.insert(points, {e3 - circle.x, e4 - circle.y})
|
||||
workspace:draw()
|
||||
end
|
||||
end
|
||||
|
||||
window.onResize = function(width, height)
|
||||
window.backgroundPanel.width = width
|
||||
window.backgroundPanel.height = height
|
||||
|
||||
layout.width = width
|
||||
layout.height = height
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
workspace:draw()
|
||||
@ -149,6 +149,12 @@
|
||||
"Libraries/OpenComputersGL/Renderer.lua",
|
||||
"Libraries/OpenComputersGL/Materials.lua",
|
||||
"Libraries/Vector.lua",
|
||||
-- Multiscreen
|
||||
{ path="Applications/Multiscreen.app/Main.lua", id=1055, shortcut = true },
|
||||
"Applications/Multiscreen.app/Icon.pic",
|
||||
-- Shooting
|
||||
{ path="Applications/Shooting.app/Main.lua", id=1055, shortcut = true },
|
||||
"Applications/Shooting.app/Icon.pic",
|
||||
-- Reinstall OS
|
||||
{ path="Applications/Reinstall OS.app/Main.lua", id=1055, shortcut = true },
|
||||
"Applications/Reinstall OS.app/Icon.pic",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user